diff --git a/.coderabbit.yaml b/.coderabbit.yaml deleted file mode 100644 index 46a4f0b9..00000000 --- a/.coderabbit.yaml +++ /dev/null @@ -1,5 +0,0 @@ -reviews: - auto_review: - enabled: true - auto_incremental_review: true - drafts: false diff --git a/.gemini/config.yaml b/.gemini/config.yaml deleted file mode 100644 index 3b5e413e..00000000 --- a/.gemini/config.yaml +++ /dev/null @@ -1,23 +0,0 @@ -have_fun: false - -ignore_patterns: - - "**/charts/**" - - "**/vendor/**" - - "**/zz_generated.*.go" - - "**/pkg/generated/**" - - "**/_out/**" - - "**/*.tgz" - - "**/dashboards/**/*.json" - - "**/*.patch" - - "**/*.diff" - - "**/images/*.json" - -code_review: - disable: false - comment_severity_threshold: LOW - max_review_comments: 50 - pull_request_opened: - help: false - summary: true - code_review: true - include_drafts: false diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md deleted file mode 100644 index 7185a625..00000000 --- a/.gemini/styleguide.md +++ /dev/null @@ -1,110 +0,0 @@ -# Cozystack Review Guidelines - -## Project Architecture - -Cozystack is a Kubernetes-based PaaS built on Helm umbrella charts and FluxCD. -Packages live in `packages/{core,system,apps,extra,library,tests}/`. The `library/` group holds reusable helper charts; the `tests/` group exists because library charts are not directly testable. -Each package wraps one or more upstream Helm charts. -Go code in `cmd/`, `internal/`, `pkg/` implements Kubernetes controllers and API server. -Static CRDs are generated by `hack/update-codegen.sh` from types under `api/v1alpha1/`, `api/backups/`, and `api/dashboard/`. -App Kinds (like `Postgres`, `Kafka`) live in `api/apps/v1alpha1/` but are registered dynamically at runtime from `ApplicationDefinition` resources — they are not static CRDs. - -## Vendored Code — Critical Rules - -**Never suggest editing files inside any `charts/` directory under `packages/`.** -Those are upstream Helm charts vendored via `make update` (which runs `helm pull`). -Any direct edit is overwritten on the next update and provides zero value. - -If you find an issue that appears to live in vendored chart code: - -- For configuration-level changes: suggest overrides in the package root `values.yaml`. -- For structural changes: suggest a patch file in `packages//patches/` applied by the Makefile. -- For source-code changes in images: suggest a patch in `packages//images//patches/`. -- For true upstream bugs: point to the upstream repository and suggest an upstream issue/PR. -- Do NOT suggest creating `charts/patches/` — patches never live inside `charts/`. - -Similarly, never propose edits to: - -- `vendor/` — Go dependencies. Changes go through `go get` and `go mod tidy`. -- `zz_generated.*.go` — regenerated by `make generate`. -- `pkg/generated/` — auto-generated Kubernetes client code. -- Image digest values in `values.yaml` — set by CI via `make image`, not by humans. -- `go.mod` / `go.sum` by hand — use `go get` and `go mod tidy`. - -## Commit and PR Requirements - -Each commit must follow [Conventional Commits](https://www.conventionalcommits.org/) format: `type(scope): brief description`. - -Valid types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`. - -Valid scopes: - -- System: `dashboard`, `platform`, `cilium`, `kube-ovn`, `linstor`, `fluxcd`, `cluster-api` -- Apps: `postgres`, `mariadb`, `redis`, `kafka`, `clickhouse`, `kubernetes`, `virtual-machine` -- Meta: `api`, `hack`, `tests`, `ci`, `docs` -- Package-specific: any `` matching a directory under `packages/` - -Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer. - -Each commit must have a `Signed-off-by:` trailer (produced by `git commit --signoff`). - -PR body must contain a release note block: - -````text -```release-note -type(scope): human-readable changelog entry -``` -```` - -Flag any PR whose commits lack the Conventional Commits format or signoff, or whose body has no release-note block. - -## Helm Chart Conventions - -Packages follow an umbrella chart pattern: - -- `charts/` — vendored upstream, read-only -- `templates/` — Cozystack-specific extra manifests -- `values.yaml` — override values for the upstream chart -- `values.schema.json` — JSON Schema for dashboard UI and input validation - -When reviewing `values.schema.json`: - -- `make generate` regenerates this file and strips `title`, `description`, and `x-*` custom annotations. Do not suggest adding fields that will be stripped on the next regeneration. -- Focus on type correctness, `required` fields, `enum` values, and default values. -- Flag breaking changes: removing a field, changing its type, or narrowing its enum. - -## Sensitive Components - -**`packages/core/platform/`**: the platform chart that deploys everything. Changes here can require updates to the migration flow — the Helm hook in `packages/core/platform/templates/migration-hook.yaml` and the runner image with scripts in `packages/core/platform/images/migrations/`. Flag any change to this package that lacks a corresponding migration update or an explicit note that backward compatibility is preserved. - -**`api/apps/v1alpha1/`**: app CRD Kinds are registered at runtime from `ApplicationDefinition` resources and the matching `values.schema.json`. Suggest changes to the relevant package schema rather than hand-editing generated types. - -**RBAC, ServiceAccounts, and SecurityContext**: flag overly broad RBAC (`*` on resources or verbs without justification), missing `securityContext`, containers running as root without an explicit reason, and `hostPath`/`hostNetwork` usage without clear rationale. - -## Go Code Standards - -- Use controller-runtime patterns for reconcilers. -- Use structured logging via `logr` — flag `fmt.Print*` and `log.Print*` in controller code. -- Handle errors explicitly. Discarding meaningful errors with `_` is a bug. -- Propagate `context.Context` through call chains. Flag `context.Background()` created inside a reconciler or request handler. -- Prefer `ctrl.Result{RequeueAfter: ...}` over empty requeue for predictable reconciliation loops. -- Tests live beside the code (`*_test.go`). New behavior without tests is worth flagging. - -## What to Review Carefully - -- Logic errors, off-by-one bugs, nil dereferences. -- Missing error handling, especially in reconcilers and API handlers. -- Helm template correctness: missing `quote`, incorrect indentation, wrong scope in `with`/`range`. -- Security: permissive RBAC, privileged containers, secrets in environment variables, hardcoded credentials. -- Missing resource requests/limits on new workloads. -- Breaking changes in `values.schema.json`: removed fields, tightened types, narrower enums. - -## Anti-patterns — Do Not Flag These - -- Large JSON files in `dashboards/` — imported from upstream Grafana sources, not hand-written. -- Files under any `charts/` directory — vendored upstream, left as-is intentionally. -- Whitespace or formatting in `*.patch` / `*.diff` files — machine-applied, not authored. -- Missing comments on generated code. -- `go.sum` changes accompanying `go.mod` changes — expected and correct. -- Fork relationships for vendored tooling images — intentional (e.g., `cozystack/kilo` fork is expected). -- Absence of unit tests for vendored chart overrides — covered by E2E tests in `hack/e2e-apps/`. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2482712d..1530cb1c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @kvaps @lllamnyp @lexfrei @androndo @IvanHunters @sircthulhu @myasnikovdaniil +* @kvaps @lllamnyp @nbykov0 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fefdab82..1a119259 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: Bug report about: Create a report to help us improve -labels: 'kind/bug' +labels: 'bug' assignees: '' --- diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 044dd6a0..9a52457c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,11 +1,8 @@ - ### Release note ```release-note - +[] ``` \ No newline at end of file diff --git a/.github/labels.yml b/.github/labels.yml deleted file mode 100644 index 2ce04130..00000000 --- a/.github/labels.yml +++ /dev/null @@ -1,371 +0,0 @@ -# Cozystack repository labels -# -# Label conventions follow the Kubernetes scheme: -# https://github.com/kubernetes/test-infra/blob/master/label_sync/labels.md -# -# Synced into the repository by .github/workflows/labels.yaml -# (EndBug/label-sync@v2). Edit this file via pull request — UI changes -# will be overwritten on the next sync. -# -# Constraints (enforced by the validate job in labels.yaml): -# - description ≤ 100 characters (GitHub REST API limit) -# - color is a 6-character hex string (no leading #) -# - label names are unique -# - aliases do not collide with top-level names -# -# Categories: -# kind/ issue or PR type -# priority/ urgency -# triage/ review state -# lifecycle/ issue or PR lifecycle -# area/ subsystem; extensible — add when 3+ open issues exist -# do-not-merge/ PR merge blockers -# security/ security-finding severity and status (Cozystack-specific) -# size: PR size (auto-applied) -# -# `aliases:` lets EndBug/label-sync rename existing labels without losing -# references on already-tagged issues and PRs. -# -# GitHub-default labels not migrated here (`wontfix`, `invalid`) currently -# carry zero issues/PRs in this repo and will be removed in a follow-up -# cleanup PR rather than aliased to a different namespace. - -# ────────────────────────────────────────────── -# kind/ — issue or PR type -# ────────────────────────────────────────────── - -- name: kind/bug - color: 'd73a4a' - description: Categorizes issue or PR as related to a bug - aliases: ['bug'] - -- name: kind/feature - color: 'a2eeef' - description: Categorizes issue or PR as related to a new feature - aliases: ['enhancement'] - -- name: kind/documentation - color: '0075ca' - description: Categorizes issue or PR as related to documentation - aliases: ['documentation'] - -- name: kind/support - color: 'd876e3' - description: Categorizes issue as a support question - aliases: ['question'] - -- name: kind/cleanup - color: 'c7def8' - description: Categorizes issue or PR as related to cleanup of code, process, or technical debt - -- name: kind/regression - color: 'e11d21' - description: Categorizes issue or PR as related to a regression from a prior release - -- name: kind/flake - color: 'f7c6c7' - description: Categorizes issue or PR as related to a flaky test - -- name: kind/failing-test - color: 'e11d21' - description: Categorizes issue or PR as related to a consistently or frequently failing test - -- name: kind/api-change - color: 'c7def8' - description: Categorizes issue or PR as related to adding, removing, or otherwise changing an API - -- name: kind/breaking-change - color: 'e11d21' - description: Indicates the change introduces a breaking API or behaviour change - -# ────────────────────────────────────────────── -# priority/ — urgency -# ────────────────────────────────────────────── - -- name: priority/critical-urgent - color: 'e11d21' - description: Highest priority. Must be actively worked on as someone's top priority right now - -- name: priority/important-soon - color: 'eb6420' - description: Must be staffed and worked on either currently, or very soon, ideally in time for the next release - -- name: priority/important-longterm - color: 'fbca04' - description: Important over the long term, but may not be staffed and/or may need multiple releases to complete - -- name: priority/backlog - color: 'fef2c0' - description: General backlog priority. Lower than priority/important-longterm - -# ────────────────────────────────────────────── -# triage/ — review state -# ────────────────────────────────────────────── - -- name: triage/needs-triage - color: 'ededed' - description: Indicates an issue needs triage by a maintainer - -- name: triage/accepted - color: '0e8a16' - description: Indicates an issue is ready to be actively worked on - -- name: triage/needs-information - color: 'fbca04' - description: Indicates an issue needs more information in order to work on it - -- name: triage/not-reproducible - color: 'fbca04' - description: Indicates an issue can not be reproduced as described - -- name: triage/duplicate - color: 'cfd3d7' - description: Indicates an issue is a duplicate of another issue - aliases: ['duplicate'] - -- name: triage/unresolved - color: 'cfd3d7' - description: Indicates an issue that can not or will not be resolved - -# ────────────────────────────────────────────── -# lifecycle/ — issue or PR lifecycle -# ────────────────────────────────────────────── - -- name: lifecycle/active - color: '1d76db' - description: Indicates that an issue or PR is actively being worked on by a contributor - -- name: lifecycle/frozen - color: 'db5dd6' - description: Indicates that an issue or PR should not be auto-closed due to staleness - aliases: ['frozen'] - -- name: lifecycle/stale - color: 'dadada' - description: Denotes an issue or PR has remained open with no activity and has become stale - aliases: ['stale'] - -- name: lifecycle/rotten - color: '795548' - description: Denotes an issue or PR that has aged beyond stale and will be auto-closed - -# ────────────────────────────────────────────── -# area/ — subsystem (extensible) -# Add a new area/* when there are 3+ open issues on the topic. -# ────────────────────────────────────────────── - -- name: area/api - color: 'bfd4f2' - description: Issues or PRs related to the cozystack-api aggregated API server - -- name: area/ai - color: 'bfd4f2' - description: Issues or PRs related to AI agent guides, AGENTS.md, docs/agents/ - -- name: area/build - color: 'bfd4f2' - description: Issues or PRs related to image build infrastructure, multi-arch support - -- name: area/ci - color: 'bfd4f2' - description: Issues or PRs related to CI workflows, GitHub Actions, automation - -- name: area/dashboard - color: 'bfd4f2' - description: Issues or PRs related to the dashboard / UI - -- name: area/extra - color: 'bfd4f2' - description: Issues or PRs related to tenant-specific modules (packages/extra/) - -- name: area/database - color: 'bfd4f2' - description: Issues or PRs related to managed databases (postgres, mariadb, redis, etcd, kafka, clickhouse) - -- name: area/kubernetes - color: 'bfd4f2' - description: Issues or PRs related to the tenant Kubernetes app - -- name: area/monitoring - color: 'bfd4f2' - description: Issues or PRs related to the monitoring stack (vlogs, vmstack, grafana, workloadmonitor) - -- name: area/networking - color: 'bfd4f2' - description: Issues or PRs related to networking (ingress, gateway, vpn, metallb, cilium, kube-ovn) - -- name: area/platform - color: 'bfd4f2' - description: Issues or PRs related to platform infrastructure (bundle, flux, talos, installer) - -- name: area/release - color: 'bfd4f2' - description: Issues or PRs related to release tooling (changelog, backport, release pipeline) - -- name: area/storage - color: 'bfd4f2' - description: Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) - -- name: area/testing - color: 'bfd4f2' - description: Issues or PRs related to testing (e2e, bats, unit tests) - -- name: area/virtualization - color: 'bfd4f2' - description: Issues or PRs related to virtualization (kubevirt, cdi, vmi, vm-import) - -- name: area/uncategorized - color: 'fbca04' - description: PR auto-labeler could not map title scope to a known area/*; please review - -# ────────────────────────────────────────────── -# do-not-merge/ — PR merge blockers (Prow convention) -# ────────────────────────────────────────────── - -- name: do-not-merge/work-in-progress - color: 'e11d21' - description: Indicates that a PR should not merge because it is a work in progress - # Both legacy spellings collapse here. EndBug processes aliases sequentially; - # the second rename hits a name collision and logs a warning — the legacy - # label survives and gets cleaned up in the follow-up dedup PR. - aliases: ['do-not-merge', 'do not merge'] - -- name: do-not-merge/hold - color: 'e11d21' - description: Indicates that a PR should not merge because someone has issued /hold - -# ────────────────────────────────────────────── -# Cozystack-specific (preserved) -# ────────────────────────────────────────────── - -- name: epic - color: 'a335ee' - description: A large development increment that brings definite value to Cozystack users - -- name: community - color: '97458a' - description: Community contributions are welcome in this issue - -- name: help wanted - color: '008672' - description: Extra attention is needed - -- name: good first issue - color: '7057ff' - description: Good for newcomers - -- name: quality-of-life - color: 'aaaaaa' - description: QoL improvements - -- name: upstream-issue - color: 'aaaaaa' - description: Requires resolving an issue in an upstream project - -- name: backport - color: 'fbca04' - description: Should change be backported on previous release - -- name: backport-previous - color: 'fbd876' - description: Backport target — previous release line - -- name: release - color: 'aaaaaa' - description: Releasing a new Cozystack version - -- name: automated - color: 'ededed' - description: Created by automation - -- name: debug - color: '704479' - description: Debugging in progress - -- name: sponsored - color: '00ff00' - description: Sponsored work - -- name: lgtm - color: '238636' - description: This PR has been approved by a maintainer - -- name: ok-to-test - color: '00ff00' - description: Indicates a non-member PR is safe to run CI on - -# ────────────────────────────────────────────── -# size: — PR size (auto-applied by sizing bot) -# ────────────────────────────────────────────── - -- name: 'size:XS' - color: '00ff00' - description: This PR changes 0-9 lines, ignoring generated files - -- name: 'size:S' - color: '77b800' - description: This PR changes 10-29 lines, ignoring generated files - -- name: 'size:M' - color: 'ebb800' - description: This PR changes 30-99 lines, ignoring generated files - -- name: 'size:L' - color: 'eb9500' - description: This PR changes 100-499 lines, ignoring generated files - -- name: 'size:XL' - color: 'ff823f' - description: This PR changes 500-999 lines, ignoring generated files - -- name: 'size:XXL' - color: 'ffb8b8' - description: This PR changes 1000+ lines, ignoring generated files - -# ────────────────────────────────────────────── -# security/ — security-finding severity and status -# ────────────────────────────────────────────── - -- name: security - color: 'aaaaaa' - description: Security-related issues and features - -- name: security/critical - color: 'd73a4a' - description: Critical security vulnerability - -- name: security/high - color: 'e99695' - description: High severity security finding - -- name: security/medium - color: 'f9c513' - description: Medium severity security finding - -- name: security/low - color: '0e8a16' - description: Low severity security finding - -- name: security/triage-needed - color: 'fbca04' - description: Needs security triage - -- name: security/confirmed - color: '1d76db' - description: Confirmed vulnerability - -- name: security/false-positive - color: 'c5def5' - description: Triaged as false positive - -- name: security/accepted-risk - color: 'bfd4f2' - description: Risk accepted with justification - -- name: security/in-progress - color: '0075ca' - description: Fix in progress - -- name: security/fixed - color: '0e8a16' - description: Fix released diff --git a/.github/workflows/auto-release.yaml b/.github/workflows/auto-release.yaml index 44ca8ca6..19d4b460 100644 --- a/.github/workflows/auto-release.yaml +++ b/.github/workflows/auto-release.yaml @@ -20,14 +20,6 @@ jobs: pull-requests: read steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - - name: Checkout code uses: actions/checkout@v4 with: @@ -36,27 +28,27 @@ jobs: - name: Configure git env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} + GH_PAT: ${{ secrets.GH_PAT }} run: | - git config user.name "cozystack-ci[bot]" - git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com" - git remote set-url origin https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY} + git config user.name "cozystack-bot" + git config user.email "217169706+cozystack-bot@users.noreply.github.com" + git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY} git config --unset-all http.https://github.com/.extraheader || true - name: Process release branches uses: actions/github-script@v7 env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} + GH_PAT: ${{ secrets.GH_PAT }} with: - github-token: ${{ steps.app-token.outputs.token }} + github-token: ${{ secrets.GH_PAT }} script: | const { execSync } = require('child_process'); - // Configure git to use GitHub App token for authentication - execSync('git config user.name "cozystack-ci[bot]"', { encoding: 'utf8' }); - execSync('git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com"', { encoding: 'utf8' }); - execSync(`git remote set-url origin https://x-access-token:${process.env.APP_TOKEN}@github.com/${process.env.GITHUB_REPOSITORY}`, { encoding: 'utf8' }); - // Remove GITHUB_TOKEN extraheader to ensure App token is used (needed to trigger other workflows) + // Configure git to use PAT for authentication + execSync('git config user.name "cozystack-bot"', { encoding: 'utf8' }); + execSync('git config user.email "217169706+cozystack-bot@users.noreply.github.com"', { encoding: 'utf8' }); + execSync(`git remote set-url origin https://cozystack-bot:${process.env.GH_PAT}@github.com/${process.env.GITHUB_REPOSITORY}`, { encoding: 'utf8' }); + // Remove GITHUB_TOKEN extraheader to ensure PAT is used (needed to trigger other workflows) execSync('git config --unset-all http.https://github.com/.extraheader || true', { encoding: 'utf8' }); // Get all release-X.Y branches diff --git a/.github/workflows/codegen-drift.yml b/.github/workflows/codegen-drift.yml deleted file mode 100644 index a26caf5e..00000000 --- a/.github/workflows/codegen-drift.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Codegen Drift Check - -on: - pull_request: - types: [opened, synchronize, reopened] - paths: - - 'api/**' - - 'pkg/apis/**' - - 'pkg/generated/**' - - 'internal/crdinstall/manifests/**' - - 'packages/system/cozystack-controller/definitions/**' - - 'packages/system/application-definition-crd/definition/**' - - 'packages/system/backup-controller/definitions/**' - - 'packages/system/backupstrategy-controller/definitions/**' - - 'hack/update-codegen.sh' - - 'hack/boilerplate.go.txt' - - 'Makefile' - - 'go.mod' - - 'go.sum' - - '.github/workflows/codegen-drift.yml' - -concurrency: - group: codegen-drift-${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - codegen-drift: - name: Verify generated code is up to date - runs-on: ubuntu-22.04 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - cache: true - - - name: Pre-fetch k8s.io/code-generator module - # hack/update-codegen.sh sources kube_codegen.sh from the Go module cache. - # The module is not declared in go.mod, so fetch it explicitly at the - # version pinned in the script. - run: | - version=$(grep -oP 'code-generator@\Kv[0-9.]+' hack/update-codegen.sh) - tmpdir=$(mktemp -d) - cd "$tmpdir" - go mod init codegen-fetch - go get "k8s.io/code-generator@${version}" - - - name: Run make generate - run: make generate - - - name: Fail on drift - run: | - if [ -n "$(git status --porcelain)" ]; then - echo "::error::'make generate' produced changes. Run 'make generate' locally and commit the result." - git status --short - git diff --color=always - exit 1 - fi diff --git a/.github/workflows/labels.yaml b/.github/workflows/labels.yaml deleted file mode 100644 index 69c18329..00000000 --- a/.github/workflows/labels.yaml +++ /dev/null @@ -1,84 +0,0 @@ -name: Labels - -on: - pull_request: - paths: - - .github/labels.yml - - .github/workflows/labels.yaml - push: - branches: [main] - paths: - - .github/labels.yml - - .github/workflows/labels.yaml - workflow_dispatch: - schedule: - - cron: '17 4 * * 1' # Mondays at 04:17 UTC - -permissions: - contents: read - -concurrency: - group: labels-sync - cancel-in-progress: false - -jobs: - validate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Validate labels.yml schema - run: | - python3 - <<'PY' - import re, sys, yaml - - path = '.github/labels.yml' - data = yaml.safe_load(open(path)) - errors = [] - - # 1. description ≤ 100 chars (GitHub REST API limit) - for label in data: - desc = label.get('description', '') or '' - if len(desc) > 100: - errors.append(f"{label['name']}: description {len(desc)} chars (max 100)") - - # 2. color is 6-char hex without leading # - for label in data: - color = label.get('color', '') or '' - if not re.match(r'^[0-9A-Fa-f]{6}$', color): - errors.append(f"{label['name']}: bad color {color!r} (must be 6-char hex without #)") - - # 3. unique top-level names - names = [label['name'] for label in data] - dups = sorted({n for n in names if names.count(n) > 1}) - for n in dups: - errors.append(f"duplicate name: {n}") - - # 4. aliases do not collide with any top-level name - name_set = set(names) - for label in data: - for alias in (label.get('aliases') or []): - if alias in name_set: - errors.append(f"alias {alias!r} (under {label['name']!r}) collides with a top-level name") - - if errors: - for err in errors: - print(f"::error::{err}") - sys.exit(1) - - print(f"labels.yml schema OK ({len(data)} labels)") - PY - - sync: - needs: validate - if: github.event_name != 'pull_request' - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/checkout@v4 - - uses: EndBug/label-sync@v2 - with: - config-file: .github/labels.yml - delete-other-labels: false diff --git a/.github/workflows/pr-labeler.yaml b/.github/workflows/pr-labeler.yaml deleted file mode 100644 index 6e6f3017..00000000 --- a/.github/workflows/pr-labeler.yaml +++ /dev/null @@ -1,206 +0,0 @@ -name: PR Auto-Label - -on: - pull_request_target: - types: [opened, edited, reopened, synchronize] - -permissions: - contents: read - pull-requests: write - -jobs: - label: - runs-on: ubuntu-latest - steps: - - name: Apply labels from PR title - uses: actions/github-script@v7 - with: - script: | - // Conventional Commits types accepted by Cozystack (per docs/agents/contributing.md): - // feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert - // Mapping below maps a subset to kind/* — types not listed do not produce a kind/*. - const typeToKind = { - feat: 'kind/feature', - fix: 'kind/bug', - docs: 'kind/documentation', - chore: 'kind/cleanup', - refactor: 'kind/cleanup', - // style, perf, test, build, ci, revert — no kind mapping - }; - - // scope -> area/* mapping. Keys are the scopes observed in cozystack issues - // and PRs. Add new entries when a scope recurs (3+ times). - const scopeToArea = { - // area/api - 'api': 'area/api', - 'cozystack-api': 'area/api', - - // area/ai - 'agents': 'area/ai', - 'ai': 'area/ai', - - // area/build - 'build': 'area/build', - - // area/ci - 'ci': 'area/ci', - - // area/dashboard - 'dashboard': 'area/dashboard', - - // area/database - 'postgres': 'area/database', - 'postgres-operator': 'area/database', - 'mariadb': 'area/database', - 'mariadb-operator': 'area/database', - 'redis': 'area/database', - 'etcd': 'area/database', - 'kafka': 'area/database', - 'clickhouse': 'area/database', - - // area/extra - 'extra': 'area/extra', - - // area/kubernetes - 'kubernetes': 'area/kubernetes', - 'apps/kubernetes': 'area/kubernetes', - - // area/monitoring - 'monitoring': 'area/monitoring', - 'vlogs': 'area/monitoring', - 'vmstack': 'area/monitoring', - 'grafana': 'area/monitoring', - 'workloadmonitor': 'area/monitoring', - - // area/networking - 'ingress': 'area/networking', - 'ingress-nginx': 'area/networking', - 'gateway': 'area/networking', - 'vpn': 'area/networking', - 'metallb': 'area/networking', - 'cilium': 'area/networking', - 'kube-ovn': 'area/networking', - 'tcp-balancer': 'area/networking', - 'securitygroups': 'area/networking', - 'cozy-proxy': 'area/networking', - - // area/platform - 'platform': 'area/platform', - 'bundle': 'area/platform', - 'flux': 'area/platform', - 'fluxcd': 'area/platform', - 'cluster-api': 'area/platform', - 'talos': 'area/platform', - 'installer': 'area/platform', - 'cozyctl': 'area/platform', - 'cozystack-engine': 'area/platform', - 'cozy-lib': 'area/platform', - - // area/release - 'backport': 'area/release', - 'release': 'area/release', - - // area/storage - 'seaweedfs': 'area/storage', - 'seaweedfs-cosi-driver': 'area/storage', - 'bucket': 'area/storage', - 'linstor': 'area/storage', - 'velero': 'area/storage', - 'harbor': 'area/storage', - 'backups': 'area/storage', - - // area/testing - 'tests': 'area/testing', - 'e2e': 'area/testing', - - // area/virtualization - 'kubevirt': 'area/virtualization', - 'cdi': 'area/virtualization', - 'vmi': 'area/virtualization', - 'vm-import': 'area/virtualization', - 'virtual-machine': 'area/virtualization', - 'hami': 'area/virtualization', - 'gpu-operator': 'area/virtualization', - }; - - const pr = context.payload.pull_request; - const title = pr.title || ''; - const body = pr.body || ''; - const existing = new Set((pr.labels || []).map(l => l.name)); - const toAdd = new Set(); - - // 1. Strip "[Backport release-1.x]" prefix if present. - const backportMatch = title.match(/^\[Backport ([^\]]+)\]\s+(.+)$/); - const cleanTitle = backportMatch ? backportMatch[2] : title; - if (backportMatch) { - toAdd.add('area/release'); - toAdd.add('backport'); - } - - // 2. Try Conventional Commits form: type(scope)?(!)?: description - const conv = cleanTitle.match(/^([a-z]+)(?:\(([^)]+)\))?(!)?:\s*.+$/); - // 3. Fall back to bracket form: [scope] description - const bracket = !conv && cleanTitle.match(/^\[([^\]]+)\]\s+.+$/); - - let type = null, scopeStr = null, breaking = false; - if (conv) { - type = conv[1]; - scopeStr = conv[2] || null; - breaking = !!conv[3]; - } else if (bracket) { - scopeStr = bracket[1]; - } - - // 4. Detect BREAKING CHANGE: or BREAKING-CHANGE: footer in body. - // Conventional Commits 1.0 spec item 16 treats them as synonymous. - if (/^BREAKING[ -]CHANGE:/m.test(body)) { - breaking = true; - } - - // 5. Apply kind/* from type. - if (type) { - if (typeToKind[type]) { - toAdd.add(typeToKind[type]); - } else { - core.warning(`type "${type}" has no kind/* mapping — typo or new type? See .github/workflows/pr-labeler.yaml typeToKind`); - } - } - - // 6. Apply area/* from scope. Composite scopes split on comma. - const scopes = (scopeStr || '') - .split(/,\s*/) - .map(s => s.trim()) - .filter(Boolean); - for (const s of scopes) { - if (scopeToArea[s]) { - toAdd.add(scopeToArea[s]); - } else { - core.warning(`scope "${s}" has no area/* mapping — consider extending scopeToArea in .github/workflows/pr-labeler.yaml if it recurs`); - } - } - - // 7. kind/breaking-change. - if (breaking) { - toAdd.add('kind/breaking-change'); - } - - // 8. Fallback: no area/* applied -> area/uncategorized. - const hasArea = [...toAdd].some(l => l.startsWith('area/')); - if (!hasArea) { - toAdd.add('area/uncategorized'); - } - - // 9. Additive only — never remove existing labels. - const newLabels = [...toAdd].filter(l => !existing.has(l)); - if (newLabels.length === 0) { - core.info('No new labels to apply'); - return; - } - - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - labels: newLabels, - }); - core.info(`Applied labels: ${newLabels.join(', ')}`); diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index b2d82ff3..ef1ce088 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -28,7 +28,7 @@ jobs: - name: Install generate run: | - curl -sSL https://github.com/cozystack/cozyvalues-gen/releases/download/v1.3.0/cozyvalues-gen-linux-amd64.tar.gz | tar -xzvf- -C /usr/local/bin/ cozyvalues-gen + curl -sSL https://github.com/cozystack/cozyvalues-gen/releases/download/v1.0.6/cozyvalues-gen-linux-amd64.tar.gz | tar -xzvf- -C /usr/local/bin/ cozyvalues-gen - name: Run pre-commit hooks run: | diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index bb7f5da5..72f31b54 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -23,14 +23,6 @@ jobs: contains(github.event.pull_request.labels.*.name, 'release') steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - # Extract tag from branch name (branch = release-X.Y.Z*) - name: Extract tag from branch name id: get_tag @@ -55,11 +47,11 @@ jobs: - name: Create tag on merge commit env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} + GH_PAT: ${{ secrets.GH_PAT }} run: | - git config user.name "cozystack-ci[bot]" - git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com" - git remote set-url origin https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY} + git config user.name "cozystack-bot" + git config user.email "217169706+cozystack-bot@users.noreply.github.com" + git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY} git tag -f ${{ steps.get_tag.outputs.tag }} ${{ github.sha }} git push -f origin ${{ steps.get_tag.outputs.tag }} @@ -67,7 +59,7 @@ jobs: - name: Ensure maintenance branch release-X.Y uses: actions/github-script@v7 with: - github-token: ${{ steps.app-token.outputs.token }} + github-token: ${{ secrets.GH_PAT }} script: | const tag = '${{ steps.get_tag.outputs.tag }}'; // e.g. v0.1.3 or v0.1.3-rc3 const match = tag.match(/^v(\d+)\.(\d+)\.\d+(?:[-\w\.]+)?$/); diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index d9898616..347bfd30 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -6,6 +6,8 @@ env: on: pull_request: types: [opened, synchronize, reopened] + paths-ignore: + - 'docs/**/*' # Cancel in‑flight runs for the same PR when a new push arrives. concurrency: @@ -13,32 +15,16 @@ concurrency: cancel-in-progress: true jobs: - detect-changes: - name: Detect changes - runs-on: ubuntu-latest - outputs: - code: ${{ steps.filter.outputs.code }} - steps: - - uses: dorny/paths-filter@v3 - id: filter - with: - filters: | - code: - - '!docs/**' - build: name: Build runs-on: [self-hosted] - timeout-minutes: 30 permissions: contents: read packages: write - needs: ["detect-changes"] - # Never run when the PR carries the "release" label or only docs changed. + # Never run when the PR carries the "release" label. if: | - needs.detect-changes.outputs.code == 'true' - && !contains(github.event.pull_request.labels.*.name, 'release') + !contains(github.event.pull_request.labels.*.name, 'release') steps: - name: Checkout code @@ -85,6 +71,18 @@ jobs: name: pr-patch path: _out/assets/pr.patch + - name: Upload CRDs + uses: actions/upload-artifact@v4 + with: + name: cozystack-crds + path: _out/assets/cozystack-crds.yaml + + - name: Upload operator + uses: actions/upload-artifact@v4 + with: + name: cozystack-operator + path: _out/assets/cozystack-operator.yaml + - name: Upload Talos image uses: actions/upload-artifact@v4 with: @@ -96,17 +94,11 @@ jobs: runs-on: ubuntu-latest if: contains(github.event.pull_request.labels.*.name, 'release') outputs: + crds_id: ${{ steps.fetch_assets.outputs.crds_id }} + operator_id: ${{ steps.fetch_assets.outputs.operator_id }} disk_id: ${{ steps.fetch_assets.outputs.disk_id }} steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - - name: Checkout code if: contains(github.event.pull_request.labels.*.name, 'release') uses: actions/checkout@v4 @@ -133,7 +125,7 @@ jobs: id: fetch_assets uses: actions/github-script@v7 with: - github-token: ${{ steps.app-token.outputs.token }} + github-token: ${{ secrets.GH_PAT }} script: | const tag = '${{ steps.get_tag.outputs.tag }}'; const releases = await github.rest.repos.listReleases({ @@ -147,19 +139,22 @@ jobs: return; } const find = (n) => draft.assets.find(a => a.name === n)?.id; + const crdsId = find('cozystack-crds.yaml'); + const operatorId = find('cozystack-operator.yaml'); const diskId = find('nocloud-amd64.raw.xz'); - if (!diskId) { + if (!crdsId || !operatorId || !diskId) { core.setFailed('Required assets missing in draft release'); return; } + core.setOutput('crds_id', crdsId); + core.setOutput('operator_id', operatorId); core.setOutput('disk_id', diskId); e2e: name: "E2E Tests" - runs-on: ${{ contains(github.event.pull_request.labels.*.name, 'debug') && 'self-hosted' || 'oracle-vm-24cpu-96gb-x86-64' }} + runs-on: [oracle-vm-24cpu-96gb-x86-64] #runs-on: [oracle-vm-32cpu-128gb-x86-64] - timeout-minutes: 120 permissions: contents: read packages: read @@ -167,15 +162,6 @@ jobs: if: ${{ always() && (needs.build.result == 'success' || needs.resolve_assets.result == 'success') }} steps: - - name: Generate GitHub App token - if: contains(github.event.pull_request.labels.*.name, 'release') - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - # ▸ Checkout and prepare the codebase - name: Checkout code uses: actions/checkout@v4 @@ -188,6 +174,20 @@ jobs: name: talos-image path: _out/assets + - name: "Download CRDs (regular PR)" + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + uses: actions/download-artifact@v4 + with: + name: cozystack-crds + path: _out/assets + + - name: "Download operator (regular PR)" + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + uses: actions/download-artifact@v4 + with: + name: cozystack-operator + path: _out/assets + - name: Download PR patch if: "!contains(github.event.pull_request.labels.*.name, 'release')" uses: actions/download-artifact@v4 @@ -205,11 +205,17 @@ jobs: if: contains(github.event.pull_request.labels.*.name, 'release') run: | mkdir -p _out/assets - curl -sSL -H "Authorization: token ${APP_TOKEN}" -H "Accept: application/octet-stream" \ + curl -sSL -H "Authorization: token ${GH_PAT}" -H "Accept: application/octet-stream" \ -o _out/assets/nocloud-amd64.raw.xz \ "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.disk_id }}" + curl -sSL -H "Authorization: token ${GH_PAT}" -H "Accept: application/octet-stream" \ + -o _out/assets/cozystack-crds.yaml \ + "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.crds_id }}" + curl -sSL -H "Authorization: token ${GH_PAT}" -H "Accept: application/octet-stream" \ + -o _out/assets/cozystack-operator.yaml \ + "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/assets/${{ needs.resolve_assets.outputs.operator_id }}" env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} + GH_PAT: ${{ secrets.GH_PAT }} - name: Set sandbox ID run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 1b68ee32..16fcbede 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -16,8 +16,6 @@ jobs: prepare-release: name: Prepare Release runs-on: [self-hosted] - outputs: - skip: ${{ steps.check_release.outputs.skip }} permissions: contents: write packages: write @@ -25,14 +23,6 @@ jobs: actions: write steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - # Check if a non-draft release with this tag already exists - name: Check if release already exists id: check_release @@ -123,29 +113,15 @@ jobs: - name: Commit release artifacts if: steps.check_release.outputs.skip == 'false' env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} + GH_PAT: ${{ secrets.GH_PAT }} run: | - git config user.name "cozystack-ci[bot]" - git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com" - git remote set-url origin https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY} + git config user.name "cozystack-bot" + git config user.email "217169706+cozystack-bot@users.noreply.github.com" + git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY} git config --unset-all http.https://github.com/.extraheader || true git add . git commit -m "Prepare release ${GITHUB_REF#refs/tags/}" -s || echo "No changes to commit" - - # Tag the api/apps/v1alpha1 submodule for pkg.go.dev - - name: Tag API submodule - if: steps.check_release.outputs.skip == 'false' - env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - VTAG="${{ steps.tag.outputs.tag }}" - SUBTAG="api/apps/v1alpha1/${VTAG}" - git config user.name "cozystack-ci[bot]" - git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com" - git remote set-url origin https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY} - TARGET="$(git rev-parse "${VTAG}^{}")" - git tag -f "${SUBTAG}" "$TARGET" - git push -f origin "refs/tags/${SUBTAG}" + git push origin HEAD || true # Create or reuse draft release - name: Create / reuse draft release @@ -191,11 +167,11 @@ jobs: - name: Create release branch if: steps.check_release.outputs.skip == 'false' env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} + GH_PAT: ${{ secrets.GH_PAT }} run: | - git config user.name "cozystack-ci[bot]" - git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com" - git remote set-url origin https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY} + git config user.name "cozystack-bot" + git config user.email "217169706+cozystack-bot@users.noreply.github.com" + git remote set-url origin https://cozystack-bot:${GH_PAT}@github.com/${GITHUB_REPOSITORY} BRANCH="release-${GITHUB_REF#refs/tags/v}" git branch -f "$BRANCH" git push -f origin "$BRANCH" @@ -205,7 +181,7 @@ jobs: if: steps.check_release.outputs.skip == 'false' uses: actions/github-script@v7 with: - github-token: ${{ steps.app-token.outputs.token }} + github-token: ${{ secrets.GH_PAT }} script: | const version = context.ref.replace('refs/tags/v', ''); const base = '${{ steps.get_base.outputs.branch }}'; @@ -223,7 +199,7 @@ jobs: repo: context.repo.repo, head, base, - title: `chore(release): cut v${version}`, + title: `Release v${version}`, body: `This PR prepares the release \`v${version}\`.`, draft: false }); @@ -237,312 +213,3 @@ jobs: } else { console.log(`PR already exists from ${head} to ${base}`); } - - generate-changelog: - name: Generate Changelog - runs-on: [self-hosted] - needs: [prepare-release] - permissions: - contents: write - pull-requests: write - if: needs.prepare-release.result == 'success' - steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - - # Read-only token for the AI step. Minting a separate scoped token - # means the Generate changelog using AI step cannot push branches, - # open PRs, or mutate any repository even with --allow-all-tools, - # regardless of whether the agent follows the prompt's instructions. - - name: Generate read-only GitHub App token - id: app-token-read - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - permission-contents: read - permission-pull-requests: read - permission-metadata: read - - - name: Parse tag - id: tag - uses: actions/github-script@v7 - with: - script: | - const ref = context.ref.replace('refs/tags/', ''); - const m = ref.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/); - if (!m) { - core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`); - return; - } - const version = m[1] + (m[2] ?? ''); - - core.setOutput('version', version); - core.setOutput('tag', ref); - - - name: Checkout main branch - uses: actions/checkout@v4 - with: - ref: main - fetch-depth: 0 - fetch-tags: true - token: ${{ steps.app-token.outputs.token }} - - - name: Check if changelog already exists - id: check_changelog - run: | - CHANGELOG_FILE="docs/changelogs/v${{ steps.tag.outputs.version }}.md" - if [ -f "$CHANGELOG_FILE" ]; then - echo "exists=true" >> $GITHUB_OUTPUT - echo "Changelog file $CHANGELOG_FILE already exists" - else - echo "exists=false" >> $GITHUB_OUTPUT - echo "Changelog file $CHANGELOG_FILE does not exist" - fi - - - name: Setup Node.js - if: steps.check_changelog.outputs.exists == 'false' - uses: actions/setup-node@v4 - with: - node-version: 22 - - - name: Install GitHub Copilot CLI - if: steps.check_changelog.outputs.exists == 'false' - run: npm i -g @github/copilot - - - name: Generate changelog using AI - if: steps.check_changelog.outputs.exists == 'false' - timeout-minutes: 30 - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} - GH_TOKEN: ${{ steps.app-token-read.outputs.token }} - VERSION: ${{ steps.tag.outputs.version }} - run: | - copilot \ - --prompt "Generate the release changelog for tag v${VERSION}. Follow the instructions in @docs/agents/changelog.md exactly, including the 'Scope and boundaries' section at the top. Your deliverable is the single file docs/changelogs/v${VERSION}.md — write it and exit; this workflow handles branching, committing, pushing, and opening the PR." \ - --allow-all-tools --allow-all-paths < /dev/null - - - name: Create changelog branch and commit - if: steps.check_changelog.outputs.exists == 'false' - env: - APP_TOKEN: ${{ steps.app-token.outputs.token }} - VERSION: ${{ steps.tag.outputs.version }} - run: | - set -euo pipefail - - CHANGELOG_FILE="docs/changelogs/v${VERSION}.md" - CHANGELOG_BRANCH="changelog-v${VERSION}" - - if [ ! -f "$CHANGELOG_FILE" ]; then - echo "::error::Changelog file $CHANGELOG_FILE was not produced by the Generate changelog using AI step" - exit 1 - fi - if [ ! -s "$CHANGELOG_FILE" ]; then - echo "::error::Changelog file $CHANGELOG_FILE is empty" - exit 1 - fi - - # Snapshot the file across the branch switch — the checkout below - # resets tracked files to match origin/main. - TEMP_FILE="$(mktemp)" - trap 'rm -f "$TEMP_FILE"' EXIT - cp "$CHANGELOG_FILE" "$TEMP_FILE" - - git config user.name "cozystack-ci[bot]" - git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com" - git remote set-url origin "https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY}" - - git fetch origin main - git branch -D "$CHANGELOG_BRANCH" 2>/dev/null || true - git checkout -b "$CHANGELOG_BRANCH" origin/main - - mkdir -p "$(dirname "$CHANGELOG_FILE")" - cp "$TEMP_FILE" "$CHANGELOG_FILE" - - # The `check_changelog` step gated this job on the file being absent - # from origin/main, so `git add` + `git commit` must produce a diff. - # If they don't, something is wrong (e.g. empty file) — fail loud. - git add "$CHANGELOG_FILE" - git commit -m "docs: add changelog for v${VERSION}" -s - git push -f origin "$CHANGELOG_BRANCH" - - - name: Create PR for changelog - if: steps.check_changelog.outputs.exists == 'false' - uses: actions/github-script@v7 - with: - github-token: ${{ steps.app-token.outputs.token }} - script: | - const version = '${{ steps.tag.outputs.version }}'; - const changelogBranch = `changelog-v${version}`; - const baseBranch = 'main'; - - // Check if PR already exists - const prs = await github.rest.pulls.list({ - owner: context.repo.owner, - repo: context.repo.repo, - head: `${context.repo.owner}:${changelogBranch}`, - base: baseBranch, - state: 'open' - }); - - if (prs.data.length > 0) { - const pr = prs.data[0]; - console.log(`PR #${pr.number} already exists for changelog branch ${changelogBranch}`); - - // Update PR body with latest info - const body = `This PR adds the changelog for release \`v${version}\`.\n\n✅ Changelog has been automatically generated in \`docs/changelogs/v${version}.md\`.`; - await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: pr.number, - body: body - }); - console.log(`Updated existing PR #${pr.number}`); - } else { - // Create new PR - const pr = await github.rest.pulls.create({ - owner: context.repo.owner, - repo: context.repo.repo, - head: changelogBranch, - base: baseBranch, - title: `docs(release): add changelog for v${version}`, - body: `This PR adds the changelog for release \`v${version}\`.\n\n✅ Changelog has been automatically generated in \`docs/changelogs/v${version}.md\`.`, - draft: false - }); - - // Add label if needed - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.data.number, - labels: ['kind/documentation', 'automated'] - }); - - console.log(`Created PR #${pr.data.number} for changelog`); - } - - update-website-docs: - name: Update Website Docs - runs-on: [self-hosted] - needs: [generate-changelog, prepare-release] - if: needs.generate-changelog.result == 'success' && needs.prepare-release.outputs.skip != 'true' - permissions: - contents: read - steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.COZYSTACK_CI_APP_ID }} - private-key: ${{ secrets.COZYSTACK_CI_PRIVATE_KEY }} - owner: cozystack - - - name: Parse tag - id: tag - uses: actions/github-script@v7 - with: - script: | - const ref = context.ref.replace('refs/tags/', ''); - const m = ref.match(/^v(\d+\.\d+\.\d+)(-(?:alpha|beta|rc)\.\d+)?$/); - if (!m) { - core.setFailed(`❌ tag '${ref}' must match 'vX.Y.Z' or 'vX.Y.Z-(alpha|beta|rc).N'`); - return; - } - const version = m[1] + (m[2] ?? ''); - core.setOutput('tag', ref); // v0.22.0 - core.setOutput('version', version); // 0.22.0 - - - name: Checkout website repo - uses: actions/checkout@v4 - with: - repository: cozystack/website - token: ${{ steps.app-token.outputs.token }} - ref: main - - # Decide whether this release promotes the `next/` trunk to a new released - # version directory. Per the website repo's contract (see website#495): - # - `make release-next` runs only for new minor/major final releases - # (tag matches `vX.Y.Z` with no prerelease suffix AND `vX.Y/` does - # not yet exist on disk). - # - Prereleases and patch releases skip this step and let - # `make update-all` handle routing on its own. - - name: Determine if this release promotes next/ - id: promote - env: - TAG: ${{ steps.tag.outputs.tag }} - run: | - if [[ ! "$TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then - echo "promote=false" >> "$GITHUB_OUTPUT" - echo "Prerelease tag '$TAG' — skipping release-next." - exit 0 - fi - MAJOR="${BASH_REMATCH[1]}" - MINOR="${BASH_REMATCH[2]}" - if [[ "$MAJOR" == "0" ]]; then - DOC_VERSION="v0" - else - DOC_VERSION="v${MAJOR}.${MINOR}" - fi - if [[ -d "content/en/docs/${DOC_VERSION}" ]]; then - echo "promote=false" >> "$GITHUB_OUTPUT" - echo "content/en/docs/${DOC_VERSION}/ already exists — patch release, skipping release-next." - else - echo "promote=true" >> "$GITHUB_OUTPUT" - echo "New minor/major release ${DOC_VERSION} — will promote next/ → ${DOC_VERSION}/." - fi - - - name: Promote next/ to released version - if: steps.promote.outputs.promote == 'true' - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - TAG: ${{ steps.tag.outputs.tag }} - run: make release-next RELEASE_TAG="$TAG" - - - name: Update docs from release branch - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - TAG: ${{ steps.tag.outputs.tag }} - VERSION: ${{ steps.tag.outputs.version }} - run: make update-all BRANCH="release-$VERSION" RELEASE_TAG="$TAG" - - - name: Commit and push - id: commit - run: | - git config user.name "cozystack-ci[bot]" - git config user.email "274107086+cozystack-ci[bot]@users.noreply.github.com" - git add content hugo.yaml - if git diff --cached --quiet; then - echo "No changes to commit" - echo "changed=false" >> $GITHUB_OUTPUT - exit 0 - fi - BRANCH="update-docs-v${{ steps.tag.outputs.version }}" - git branch -D "$BRANCH" 2>/dev/null || true - git checkout -b "$BRANCH" - git commit --signoff -m "[docs] Update managed apps reference for v${{ steps.tag.outputs.version }}" - git push --force --set-upstream origin "$BRANCH" - echo "changed=true" >> $GITHUB_OUTPUT - - - name: Open pull request - if: steps.commit.outputs.changed == 'true' - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - BRANCH="update-docs-v${{ steps.tag.outputs.version }}" - pr_state=$(gh pr view "$BRANCH" --repo cozystack/website --json state --jq .state 2>/dev/null || echo "") - if [[ "$pr_state" == "OPEN" ]]; then - echo "PR already open, skipping creation." - else - gh pr create \ - --repo cozystack/website \ - --title "[docs] Update managed apps reference for v${{ steps.tag.outputs.version }}" \ - --body "Automated docs update for release \`v${{ steps.tag.outputs.version }}\`." \ - --head "update-docs-v${{ steps.tag.outputs.version }}" \ - --base main - fi diff --git a/.gitignore b/.gitignore index 61003de5..0ecfa223 100644 --- a/.gitignore +++ b/.gitignore @@ -80,7 +80,3 @@ fabric.properties **/.DS_Store tmp/ - -# build revision marker (generated by make image-packages) -packages/core/platform/.build-revision -.claude/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6492b92d..ac0f7e30 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,17 +1,6 @@ repos: - repo: local hooks: - - id: run-make-generate-root - name: Run 'make generate' at repo root - entry: | - flock -x .git/pre-commit.lock sh -c ' - echo "Running make generate at repo root" - make generate || exit $? - git diff --color=always | cat - ' - language: system - files: ^(api/|pkg/apis/|pkg/generated/|internal/crdinstall/manifests/|packages/system/cozystack-controller/definitions/|packages/system/application-definition-crd/definition/|packages/system/backup-controller/definitions/|packages/system/backupstrategy-controller/definitions/|hack/update-codegen\.sh$|hack/boilerplate\.go\.txt$|Makefile$) - pass_filenames: false - id: run-make-generate name: Run 'make generate' in all app directories entry: | diff --git a/AGENTS.md b/AGENTS.md index 1e9c4d15..eb1febf7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,12 +27,6 @@ working with the **Cozystack** project. - Read: [`contributing.md`](./docs/agents/contributing.md) - Action: Read the file to understand git workflow, commit format, PR process -- **Issue and PR labeling, triage** (e.g., "label this issue", "what label should I use", "triage this", "categorize") - - Read: [`.github/labels.yml`](./.github/labels.yml) - - Action: Use labels defined there. Conventions follow the Kubernetes scheme — `kind/*` (type), `area/*` (subsystem), `priority/*` (urgency), `triage/*` (review state), `lifecycle/*` (auto-close), `do-not-merge/*` (PR blockers), `security/*` (severity) - - For `area/*`: accuracy outweighs reuse. If no existing `area/*` truly fits the change, propose a new one via PR (extend `.github/labels.yml` and the scope mapping in `.github/workflows/pr-labeler.yaml`) — do not shoehorn the change into a wrong area. `area/uncategorized` is the auto-labeler fallback; treat it as a signal to pick a fit, create a new area, or correct the PR title - - PR titles: a Conventional Commits header (`type(scope): description`, types from [`contributing.md`](./docs/agents/contributing.md)) auto-applies `kind/*` and `area/*` via `.github/workflows/pr-labeler.yaml`. Append `!` (or add a `BREAKING CHANGE:` footer) to apply `kind/breaking-change` - **Important rules:** - ✅ **ONLY read the file if the task matches the documented process scope** - do not read files for tasks that don't match their purpose - ✅ **ALWAYS read the file FIRST** before starting the task (when applicable) @@ -59,7 +53,7 @@ working with the **Cozystack** project. ### Conventions - **Helm Charts**: Umbrella pattern, vendored upstream charts in `charts/` - **Go Code**: Controller-runtime patterns, kubebuilder style -- **Git Commits**: Conventional Commits (`type(scope): description`) with `--signoff` +- **Git Commits**: `[component] Description` format with `--signoff` ### What NOT to Do - ❌ Edit `/vendor/`, `zz_generated.*.go`, upstream charts directly diff --git a/MAINTAINERS.md b/MAINTAINERS.md index d7061941..9c44daab 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -10,5 +10,3 @@ | Timur Tukaev | [@tym83](https://github.com/tym83) | Ænix | Cozystack Website, Marketing, Community Management | | Kirill Klinchenkov | [@klinch0](https://github.com/klinch0) | Ænix | Core Maintainer | | Nikita Bykov | [@nbykov0](https://github.com/nbykov0) | Ænix | Maintainer of ARM and stuff | -| Matthieu Robin | [@matthieu-robin](https://github.com/matthieu-robin) | Hidora | Managed Applications, Platform Quality & Benchmarking | -| Mattia Eleuteri | [@mattia-eleuteri](https://github.com/mattia-eleuteri) | Hidora | CSI, Storage, Networking & Security | diff --git a/Makefile b/Makefile index acc9b6f6..f1779174 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: manifests assets unit-tests helm-unit-tests bats-unit-tests preflight +.PHONY: manifests assets unit-tests helm-unit-tests include hack/common-envs.mk @@ -11,24 +11,22 @@ build-deps: build: build-deps make -C packages/apps/http-cache image - make -C packages/apps/mariadb image + make -C packages/apps/mysql image make -C packages/apps/clickhouse image make -C packages/apps/kubernetes image - make -C packages/system/monitoring image + make -C packages/extra/monitoring image make -C packages/system/cozystack-api image make -C packages/system/cozystack-controller image make -C packages/system/backup-controller image - make -C packages/system/backupstrategy-controller image make -C packages/system/lineage-controller-webhook image make -C packages/system/cilium image make -C packages/system/linstor image - make -C packages/system/linstor-gui image make -C packages/system/kubeovn-webhook image make -C packages/system/kubeovn-plunger image make -C packages/system/dashboard image make -C packages/system/metallb image make -C packages/system/kamaji image - make -C packages/system/multus image + make -C packages/system/kilo image make -C packages/system/bucket image make -C packages/system/objectstorage-controller image make -C packages/system/grafana-operator image @@ -40,31 +38,29 @@ build: build-deps manifests: mkdir -p _out/assets - cat internal/crdinstall/manifests/*.yaml > _out/assets/cozystack-crds.yaml + helm template installer packages/core/installer -n cozy-system \ + -s templates/crds.yaml \ + > _out/assets/cozystack-crds.yaml # Talos variant (default) helm template installer packages/core/installer -n cozy-system \ - --show-only templates/cozystack-operator.yaml \ - > _out/assets/cozystack-operator-talos.yaml + -s templates/cozystack-operator.yaml \ + -s templates/packagesource.yaml \ + > _out/assets/cozystack-operator.yaml # Generic Kubernetes variant (k3s, kubeadm, RKE2) helm template installer packages/core/installer -n cozy-system \ - --set cozystackOperator.variant=generic \ - --set cozystack.apiServerHost=REPLACE_ME \ - --show-only templates/cozystack-operator.yaml \ + -s templates/cozystack-operator-generic.yaml \ + -s templates/packagesource.yaml \ > _out/assets/cozystack-operator-generic.yaml # Hosted variant (managed Kubernetes) helm template installer packages/core/installer -n cozy-system \ - --set cozystackOperator.variant=hosted \ - --show-only templates/cozystack-operator.yaml \ + -s templates/cozystack-operator-hosted.yaml \ + -s templates/packagesource.yaml \ > _out/assets/cozystack-operator-hosted.yaml cozypkg: go build -ldflags "-X github.com/cozystack/cozystack/cmd/cozypkg/cmd.Version=v$(COZYSTACK_VERSION)" -o _out/bin/cozypkg ./cmd/cozypkg -assets: assets-talos assets-cozypkg openapi-json - -openapi-json: - mkdir -p _out/assets - VERSION=$(shell git describe --tags --always 2>/dev/null || echo dev) go run ./tools/openapi-gen/ 2>/dev/null > _out/assets/openapi.json +assets: assets-talos assets-cozypkg assets-talos: make -C packages/core/talos assets @@ -83,46 +79,11 @@ test: make -C packages/core/testing apply make -C packages/core/testing test -unit-tests: helm-unit-tests bats-unit-tests go-unit-tests +unit-tests: helm-unit-tests helm-unit-tests: hack/helm-unit-tests.sh -# Scoped go test over the cozystack-api surface that this repo owns. Kept -# narrow intentionally - running `go test ./...` pulls in generated code -# round-trip suites whose behavior depends on tool versions outside this -# repo's control (kubebuilder, openapi-gen, etc.) and is better exercised -# from their generator workflows. -go-unit-tests: - go test ./pkg/registry/... ./pkg/config/... ./pkg/cmd/server/... - -# Discover every hack/*.bats file that is NOT an e2e test and run it -# through cozytest.sh. Drop a new *.bats file in hack/ and it is picked -# up automatically on the next `make unit-tests` run. -# -# Caveat: $(wildcard ...) returns space-separated names, so a filename -# containing a literal space would split into multiple tokens here. All -# current bats files use hyphen-separated names; if the project ever -# introduces whitespace-bearing filenames this recipe must be rewritten -# (e.g. to use `find ... -print0 | xargs -0`). -BATS_UNIT_FILES := $(filter-out hack/e2e-%.bats,$(wildcard hack/*.bats)) - -bats-unit-tests: - @if [ -z "$(BATS_UNIT_FILES)" ]; then \ - echo "ERROR: no hack/*.bats unit test files found"; \ - exit 1; \ - fi - @for f in $(BATS_UNIT_FILES); do \ - echo "--- running $$f ---"; \ - hack/cozytest.sh "$$f" || exit 1; \ - done - -# Operator-facing host preflight check. Warns about a standalone -# containerd.service or docker.service running alongside the embedded -# k3s runtime. Safe to run at any time; always exits 0. -preflight: - @hack/check-host-runtime.sh - prepare-env: make -C packages/core/testing apply make -C packages/core/testing prepare-cluster diff --git a/README.md b/README.md index 5bc8d7be..b81af2a7 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,11 @@ [![Support](https://img.shields.io/badge/$-support-12a0df.svg?style=flat)](https://cozystack.io/support/) [![Active](http://img.shields.io/badge/Status-Active-green.svg)](https://github.com/cozystack/cozystack) [![GitHub Release](https://img.shields.io/github/release/cozystack/cozystack.svg?style=flat)](https://github.com/cozystack/cozystack/releases/latest) -[![GitHub Commit](https://img.shields.io/github/commit-activity/y/cozystack/cozystack)](https://github.com/cozystack/cozystack/graphs/contributors) -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/10177/badge)](https://www.bestpractices.dev/projects/10177) +[![GitHub Commit](https://img.shields.io/github/commit-activity/y/cozystack/cozystack)](https://github.com/cozystack/cozystack/graphs/contributors) # Cozystack -**Cozystack** is a free platform and framework for building clouds. +**Cozystack** is a free PaaS platform and framework for building clouds. Cozystack is a [CNCF Sandbox Level Project](https://www.cncf.io/sandbox-projects/) that was originally built and sponsored by [Ænix](https://aenix.io/). diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index b64e533b..00000000 --- a/SECURITY.md +++ /dev/null @@ -1,102 +0,0 @@ -# Security Policy - -## Scope - -This policy applies to the [`cozystack/cozystack`](https://github.com/cozystack/cozystack) repository and to release artifacts produced from it, including Cozystack core components, operators, packaged manifests, container images, and installation assets published by the project. - -Cozystack integrates and ships many upstream cloud native components. If you believe a vulnerability originates in an upstream project rather than in Cozystack-specific code, packaging, defaults, or integration logic, please report it to the upstream project as well. If you are unsure, report it to Cozystack first and we will help route or coordinate the issue. - -## Supported Versions - -As of March 17, 2026, the Cozystack project maintains multiple release lines. Security fixes are prioritized for the latest stable release line and, when needed, backported to other supported lines. - -| Version line | Status | Notes | -| --- | --- | --- | -| `v1.1.x` | Supported | Current stable release line. | -| `v1.0.x` | Supported | Previous stable release line; receives security and important maintenance fixes. | -| `v0.41.x` | Limited support | Legacy pre-v1 line during the v0 to v1 transition; critical security and upgrade-blocking fixes may be backported at maintainer discretion. | -| `< v0.41` | Not supported | Please upgrade to a supported release line before requesting a security fix. | -| `alpha`, `beta`, `rc` releases | Not supported | Pre-release builds are for testing and evaluation only. | - -Supported versions may change over time as new release lines are cut. The authoritative source for current releases is the GitHub Releases page: - - - -## Reporting a Vulnerability - -Please do **not** report security vulnerabilities through public GitHub issues, discussions, pull requests, Telegram, Slack, or other public community channels. - -At the moment, this repository does not publish a dedicated private security mailbox in-tree. If you need to report a vulnerability: - -1. Contact one of the project maintainers listed in `CODEOWNERS` using an existing private channel you already have. -2. If you do not already have a private maintainer contact, use a public community channel only to request a private contact path, without disclosing any vulnerability details. - -Please do not include exploit details, credentials, tokens, private keys, customer data, or other sensitive material in any public message. - -When reporting a vulnerability, please include as much of the following as possible: - -- affected Cozystack version, tag, or commit -- affected component or package, for example operator, API server, dashboard, installer, or a packaged system component -- deployment environment and provider, for example bare metal, Hetzner, Oracle Cloud, or other infrastructure -- prerequisites and exact reproduction steps -- impact, attack scenario, and expected blast radius -- whether authentication, tenant access, cluster-admin access, or network adjacency is required -- known mitigations or workarounds -- whether you believe the issue also affects an upstream dependency - -## What to Expect - -The maintainers will aim to: - -- acknowledge receipt within 3 business days -- perform an initial triage and severity assessment within 7 business days -- keep the reporter informed as the fix and disclosure plan are developed - -Resolution timelines depend on severity, complexity, release branch applicability, and whether coordination with upstream projects is required. - -## Disclosure Process - -The Cozystack project follows a coordinated disclosure model. - -- We ask reporters to keep details private until a fix or mitigation is available and users have had a reasonable opportunity to upgrade. -- When appropriate, maintainers may use GitHub Security Advisories or equivalent coordinated disclosure tooling to manage remediation and public disclosure. -- If appropriate, the project may request or publish a GHSA and/or CVE as part of the disclosure process. -- Fixes will normally be released in the supported version lines affected by the issue, subject to severity and feasibility. - -Public disclosure will typically happen through one or more of the following: - -- GitHub Releases and release notes -- project changelogs and documentation updates -- GitHub Security Advisories, when used for coordinated disclosure - -## Project Security Practices - -Security is part of the normal Cozystack development and release process. Current project practices include: - -- maintainer-owned review through pull requests and `CODEOWNERS` -- automated pull request checks, including pre-commit validation, unit tests, builds, and end-to-end testing -- release automation with patch releases, release branches, and backport workflows -- ongoing maintenance of packaged dependencies and platform integrations across supported release lines - -Because Cozystack is an integration-heavy platform, some vulnerabilities may require coordination across multiple repositories or with upstream maintainers before a public fix can be released. - -## Security Fixes and Announcements - -Security fixes are published in normal release artifacts whenever possible. Users should monitor: - -- GitHub Releases: -- project changelogs in this repository -- the Cozystack website and documentation: - -## Out of Scope - -The following are generally out of scope for private security reporting unless there is a clear Cozystack-specific impact: - -- vulnerabilities in unsupported or end-of-life Cozystack versions -- issues that require access already equivalent to cluster-admin, node root, or direct infrastructure administrator privileges, unless they bypass an expected Cozystack security boundary -- vulnerabilities that exist only in an upstream dependency and are not introduced or materially worsened by Cozystack packaging, configuration, or defaults -- requests for security best-practice advice without a concrete vulnerability - -## Credits - -We appreciate responsible disclosure and will credit reporters in public advisories or release notes unless anonymous disclosure is requested. diff --git a/api/apps/v1alpha1/bucket/types.go b/api/apps/v1alpha1/bucket/types.go deleted file mode 100644 index 96082a67..00000000 --- a/api/apps/v1alpha1/bucket/types.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package bucket - -import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Provisions bucket from the `-lock` BucketClass (with object lock enabled). - // +kubebuilder:default:=false - Locking bool `json:"locking"` - // Selects a specific BucketClass by storage pool name. - // +kubebuilder:default:="" - StoragePool string `json:"storagePool,omitempty"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` -} - -type User struct { - // Whether the user has read-only access. - Readonly bool `json:"readonly,omitempty"` -} diff --git a/api/apps/v1alpha1/bucket/zz_generated.deepcopy.go b/api/apps/v1alpha1/bucket/zz_generated.deepcopy.go deleted file mode 100644 index 26f925cd..00000000 --- a/api/apps/v1alpha1/bucket/zz_generated.deepcopy.go +++ /dev/null @@ -1,88 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package bucket - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/clickhouse/types.go b/api/apps/v1alpha1/clickhouse/types.go deleted file mode 100644 index 153ff5e0..00000000 --- a/api/apps/v1alpha1/clickhouse/types.go +++ /dev/null @@ -1,112 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package clickhouse - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of ClickHouse replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Number of ClickHouse shards. - // +kubebuilder:default:=1 - Shards int `json:"shards"` - // Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Size of Persistent Volume for logs. - // +kubebuilder:default:="2Gi" - LogStorageSize resource.Quantity `json:"logStorageSize"` - // TTL (expiration time) for `query_log` and `query_thread_log`. - // +kubebuilder:default:=15 - LogTTL int `json:"logTTL"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // Backup configuration. - // +kubebuilder:default:={} - Backup Backup `json:"backup"` - // ClickHouse Keeper configuration. - // +kubebuilder:default:={} - ClickhouseKeeper ClickHouseKeeper `json:"clickhouseKeeper"` -} - -type Backup struct { - // Retention strategy for cleaning up old backups. - // +kubebuilder:default:="--keep-last=3 --keep-daily=3 --keep-within-weekly=1m" - CleanupStrategy string `json:"cleanupStrategy"` - // Enable regular backups (default: false). - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Password for Restic backup encryption. - // +kubebuilder:default:="" - ResticPassword string `json:"resticPassword"` - // Access key for S3 authentication. - // +kubebuilder:default:="" - S3AccessKey string `json:"s3AccessKey"` - // S3 bucket used for storing backups. - // +kubebuilder:default:="s3.example.org/clickhouse-backups" - S3Bucket string `json:"s3Bucket"` - // AWS S3 region where backups are stored. - // +kubebuilder:default:="us-east-1" - S3Region string `json:"s3Region"` - // Secret key for S3 authentication. - // +kubebuilder:default:="" - S3SecretKey string `json:"s3SecretKey"` - // Cron schedule for automated backups. - // +kubebuilder:default:="0 2 * * *" - Schedule string `json:"schedule"` -} - -type ClickHouseKeeper struct { - // Deploy ClickHouse Keeper for cluster coordination. - // +kubebuilder:default:=true - Enabled bool `json:"enabled,omitempty"` - // Number of Keeper replicas. - // +kubebuilder:default:=3 - Replicas int `json:"replicas,omitempty"` - // Default sizing preset. - // +kubebuilder:default:="micro" - ResourcesPreset ResourcesPreset `json:"resourcesPreset,omitempty"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="1Gi" - Size resource.Quantity `json:"size,omitempty"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type User struct { - // Password for the user. - Password string `json:"password,omitempty"` - // User is readonly (default: false). - Readonly bool `json:"readonly,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/clickhouse/zz_generated.deepcopy.go b/api/apps/v1alpha1/clickhouse/zz_generated.deepcopy.go deleted file mode 100644 index 2c3a6ed8..00000000 --- a/api/apps/v1alpha1/clickhouse/zz_generated.deepcopy.go +++ /dev/null @@ -1,141 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package clickhouse - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Backup) DeepCopyInto(out *Backup) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup. -func (in *Backup) DeepCopy() *Backup { - if in == nil { - return nil - } - out := new(Backup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClickHouseKeeper) DeepCopyInto(out *ClickHouseKeeper) { - *out = *in - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClickHouseKeeper. -func (in *ClickHouseKeeper) DeepCopy() *ClickHouseKeeper { - if in == nil { - return nil - } - out := new(ClickHouseKeeper) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() - out.LogStorageSize = in.LogStorageSize.DeepCopy() - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - out.Backup = in.Backup - in.ClickhouseKeeper.DeepCopyInto(&out.ClickhouseKeeper) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/foundationdb/types.go b/api/apps/v1alpha1/foundationdb/types.go deleted file mode 100644 index 5b0e5920..00000000 --- a/api/apps/v1alpha1/foundationdb/types.go +++ /dev/null @@ -1,162 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package foundationdb - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Cluster configuration. - // +kubebuilder:default:={} - Cluster Cluster `json:"cluster"` - // Storage configuration. - // +kubebuilder:default:={} - Storage Storage `json:"storage"` - // Explicit CPU and memory configuration for each FoundationDB instance. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="medium" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Backup configuration. - // +kubebuilder:default:={} - Backup Backup `json:"backup"` - // Monitoring configuration. - // +kubebuilder:default:={} - Monitoring Monitoring `json:"monitoring"` - // Custom parameters to pass to FoundationDB. - // +kubebuilder:default:={} - CustomParameters []string `json:"customParameters,omitempty"` - // Container image deployment type. - // +kubebuilder:default:="unified" - ImageType ImageType `json:"imageType"` - // Security context for containers. - // +kubebuilder:default:={} - SecurityContext SecurityContext `json:"securityContext"` - // Enable automatic pod replacements. - // +kubebuilder:default:=true - AutomaticReplacements bool `json:"automaticReplacements"` -} - -type Backup struct { - // Enable backups. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Retention policy for backups. - // +kubebuilder:default:="7d" - RetentionPolicy string `json:"retentionPolicy"` - // S3 configuration for backups. - // +kubebuilder:default:={} - S3 BackupS3 `json:"s3"` -} - -type BackupS3 struct { - // S3 bucket name. - // +kubebuilder:default:="" - Bucket string `json:"bucket"` - // S3 credentials. - // +kubebuilder:default:={} - Credentials BackupS3Credentials `json:"credentials"` - // S3 endpoint URL. - // +kubebuilder:default:="" - Endpoint string `json:"endpoint"` - // S3 region. - // +kubebuilder:default:="us-east-1" - Region string `json:"region"` -} - -type BackupS3Credentials struct { - // S3 access key ID. - // +kubebuilder:default:="" - AccessKeyId string `json:"accessKeyId"` - // S3 secret access key. - // +kubebuilder:default:="" - SecretAccessKey string `json:"secretAccessKey"` -} - -type Cluster struct { - // Fault domain configuration. - // +kubebuilder:default:={} - FaultDomain ClusterFaultDomain `json:"faultDomain"` - // Process counts for different roles. - // +kubebuilder:default:={} - ProcessCounts ClusterProcessCounts `json:"processCounts"` - // Database redundancy mode (single, double, triple, three_datacenter, three_datacenter_fallback). - // +kubebuilder:default:="double" - RedundancyMode string `json:"redundancyMode"` - // Storage engine (ssd-2, ssd-redwood-v1, ssd-rocksdb-v1, memory). - // +kubebuilder:default:="ssd-2" - StorageEngine string `json:"storageEngine"` - // Version of FoundationDB to use. - // +kubebuilder:default:="7.3.63" - Version string `json:"version"` -} - -type ClusterFaultDomain struct { - // Fault domain key. - // +kubebuilder:default:="kubernetes.io/hostname" - Key string `json:"key"` - // Fault domain value source. - // +kubebuilder:default:="spec.nodeName" - ValueFrom string `json:"valueFrom"` -} - -type ClusterProcessCounts struct { - // Number of cluster controller processes. - // +kubebuilder:default:=1 - ClusterController int `json:"cluster_controller"` - // Number of stateless processes (-1 for automatic). - // +kubebuilder:default:=-1 - Stateless int `json:"stateless"` - // Number of storage processes (determines cluster size). - // +kubebuilder:default:=3 - Storage int `json:"storage"` -} - -type Monitoring struct { - // Enable WorkloadMonitor integration. - // +kubebuilder:default:=true - Enabled bool `json:"enabled"` -} - -type Resources struct { - // CPU available to each instance. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each instance. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type SecurityContext struct { - // Group ID to run the container. - // +kubebuilder:default:=4059 - RunAsGroup int `json:"runAsGroup"` - // User ID to run the container. - // +kubebuilder:default:=4059 - RunAsUser int `json:"runAsUser"` -} - -type Storage struct { - // Size of persistent volumes for each instance. - // +kubebuilder:default:="16Gi" - Size resource.Quantity `json:"size"` - // Storage class (if not set, uses cluster default). - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` -} - -// +kubebuilder:validation:Enum="unified";"split" -type ImageType string - -// +kubebuilder:validation:Enum="small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/foundationdb/zz_generated.deepcopy.go b/api/apps/v1alpha1/foundationdb/zz_generated.deepcopy.go deleted file mode 100644 index 92d80421..00000000 --- a/api/apps/v1alpha1/foundationdb/zz_generated.deepcopy.go +++ /dev/null @@ -1,234 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package foundationdb - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Backup) DeepCopyInto(out *Backup) { - *out = *in - out.S3 = in.S3 -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup. -func (in *Backup) DeepCopy() *Backup { - if in == nil { - return nil - } - out := new(Backup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BackupS3) DeepCopyInto(out *BackupS3) { - *out = *in - out.Credentials = in.Credentials -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupS3. -func (in *BackupS3) DeepCopy() *BackupS3 { - if in == nil { - return nil - } - out := new(BackupS3) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BackupS3Credentials) DeepCopyInto(out *BackupS3Credentials) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupS3Credentials. -func (in *BackupS3Credentials) DeepCopy() *BackupS3Credentials { - if in == nil { - return nil - } - out := new(BackupS3Credentials) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Cluster) DeepCopyInto(out *Cluster) { - *out = *in - out.FaultDomain = in.FaultDomain - out.ProcessCounts = in.ProcessCounts -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster. -func (in *Cluster) DeepCopy() *Cluster { - if in == nil { - return nil - } - out := new(Cluster) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterFaultDomain) DeepCopyInto(out *ClusterFaultDomain) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterFaultDomain. -func (in *ClusterFaultDomain) DeepCopy() *ClusterFaultDomain { - if in == nil { - return nil - } - out := new(ClusterFaultDomain) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterProcessCounts) DeepCopyInto(out *ClusterProcessCounts) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProcessCounts. -func (in *ClusterProcessCounts) DeepCopy() *ClusterProcessCounts { - if in == nil { - return nil - } - out := new(ClusterProcessCounts) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - out.Cluster = in.Cluster - in.Storage.DeepCopyInto(&out.Storage) - in.Resources.DeepCopyInto(&out.Resources) - out.Backup = in.Backup - out.Monitoring = in.Monitoring - if in.CustomParameters != nil { - in, out := &in.CustomParameters, &out.CustomParameters - *out = make([]string, len(*in)) - copy(*out, *in) - } - out.SecurityContext = in.SecurityContext -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Monitoring) DeepCopyInto(out *Monitoring) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Monitoring. -func (in *Monitoring) DeepCopy() *Monitoring { - if in == nil { - return nil - } - out := new(Monitoring) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecurityContext) DeepCopyInto(out *SecurityContext) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityContext. -func (in *SecurityContext) DeepCopy() *SecurityContext { - if in == nil { - return nil - } - out := new(SecurityContext) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Storage) DeepCopyInto(out *Storage) { - *out = *in - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Storage. -func (in *Storage) DeepCopy() *Storage { - if in == nil { - return nil - } - out := new(Storage) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/go.mod b/api/apps/v1alpha1/go.mod deleted file mode 100644 index d5d57383..00000000 --- a/api/apps/v1alpha1/go.mod +++ /dev/null @@ -1,24 +0,0 @@ -module github.com/cozystack/cozystack/api/apps/v1alpha1 - -go 1.25.0 - -require k8s.io/apimachinery v0.35.2 - -require ( - github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect - github.com/x448/float16 v0.8.4 // indirect - go.yaml.in/yaml/v2 v2.4.3 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/text v0.31.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect - sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect - sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect -) diff --git a/api/apps/v1alpha1/go.sum b/api/apps/v1alpha1/go.sum deleted file mode 100644 index d9b1cf31..00000000 --- a/api/apps/v1alpha1/go.sum +++ /dev/null @@ -1,56 +0,0 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= -github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= -github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= -github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= -go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.35.2 h1:NqsM/mmZA7sHW02JZ9RTtk3wInRgbVxL8MPfzSANAK8= -k8s.io/apimachinery v0.35.2/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= -sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= -sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= -sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= -sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= -sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/api/apps/v1alpha1/harbor/types.go b/api/apps/v1alpha1/harbor/types.go deleted file mode 100644 index 974576b3..00000000 --- a/api/apps/v1alpha1/harbor/types.go +++ /dev/null @@ -1,114 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package harbor - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Hostname for external access to Harbor (defaults to 'harbor' subdomain for the tenant host). - // +kubebuilder:default:="" - Host string `json:"host,omitempty"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Core API server configuration. - // +kubebuilder:default:={} - Core Core `json:"core"` - // Container image registry configuration. - // +kubebuilder:default:={} - Registry Registry `json:"registry"` - // Background job service configuration. - // +kubebuilder:default:={} - Jobservice Jobservice `json:"jobservice"` - // Trivy vulnerability scanner configuration. - // +kubebuilder:default:={} - Trivy Trivy `json:"trivy"` - // PostgreSQL database configuration. - // +kubebuilder:default:={} - Database Database `json:"database"` - // Redis cache configuration. - // +kubebuilder:default:={} - Redis Redis `json:"redis"` -} - -type Core struct { - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset,omitempty"` -} - -type Database struct { - // Number of database instances. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Persistent Volume size for database storage. - // +kubebuilder:default:="5Gi" - Size resource.Quantity `json:"size"` -} - -type Jobservice struct { - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset,omitempty"` -} - -type Redis struct { - // Number of Redis replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Persistent Volume size for cache storage. - // +kubebuilder:default:="1Gi" - Size resource.Quantity `json:"size"` -} - -type Registry struct { - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset,omitempty"` -} - -type Resources struct { - // Number of CPU cores allocated. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Amount of memory allocated. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type Trivy struct { - // Enable or disable the vulnerability scanner. - // +kubebuilder:default:=true - Enabled bool `json:"enabled"` - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset,omitempty"` - // Persistent Volume size for vulnerability database cache. - // +kubebuilder:default:="5Gi" - Size resource.Quantity `json:"size"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/harbor/zz_generated.deepcopy.go b/api/apps/v1alpha1/harbor/zz_generated.deepcopy.go deleted file mode 100644 index 3e7338ad..00000000 --- a/api/apps/v1alpha1/harbor/zz_generated.deepcopy.go +++ /dev/null @@ -1,186 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package harbor - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Core.DeepCopyInto(&out.Core) - in.Registry.DeepCopyInto(&out.Registry) - in.Jobservice.DeepCopyInto(&out.Jobservice) - in.Trivy.DeepCopyInto(&out.Trivy) - in.Database.DeepCopyInto(&out.Database) - in.Redis.DeepCopyInto(&out.Redis) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Core) DeepCopyInto(out *Core) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Core. -func (in *Core) DeepCopy() *Core { - if in == nil { - return nil - } - out := new(Core) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Database) DeepCopyInto(out *Database) { - *out = *in - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database. -func (in *Database) DeepCopy() *Database { - if in == nil { - return nil - } - out := new(Database) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Jobservice) DeepCopyInto(out *Jobservice) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Jobservice. -func (in *Jobservice) DeepCopy() *Jobservice { - if in == nil { - return nil - } - out := new(Jobservice) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Redis) DeepCopyInto(out *Redis) { - *out = *in - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Redis. -func (in *Redis) DeepCopy() *Redis { - if in == nil { - return nil - } - out := new(Redis) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Registry) DeepCopyInto(out *Registry) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Registry. -func (in *Registry) DeepCopy() *Registry { - if in == nil { - return nil - } - out := new(Registry) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Trivy) DeepCopyInto(out *Trivy) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Trivy. -func (in *Trivy) DeepCopy() *Trivy { - if in == nil { - return nil - } - out := new(Trivy) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/httpcache/types.go b/api/apps/v1alpha1/httpcache/types.go deleted file mode 100644 index 30bb10ba..00000000 --- a/api/apps/v1alpha1/httpcache/types.go +++ /dev/null @@ -1,72 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package httpcache - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // Endpoints configuration, as a list of . - // +kubebuilder:default:={} - Endpoints []string `json:"endpoints,omitempty"` - // HAProxy configuration. - // +kubebuilder:default:={} - Haproxy HAProxy `json:"haproxy"` - // Nginx configuration. - // +kubebuilder:default:={} - Nginx Nginx `json:"nginx"` -} - -type HAProxy struct { - // Number of HAProxy replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` -} - -type Nginx struct { - // Number of Nginx replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/httpcache/zz_generated.deepcopy.go b/api/apps/v1alpha1/httpcache/zz_generated.deepcopy.go deleted file mode 100644 index 47da2baa..00000000 --- a/api/apps/v1alpha1/httpcache/zz_generated.deepcopy.go +++ /dev/null @@ -1,123 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package httpcache - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - out.Size = in.Size.DeepCopy() - if in.Endpoints != nil { - in, out := &in.Endpoints, &out.Endpoints - *out = make([]string, len(*in)) - copy(*out, *in) - } - in.Haproxy.DeepCopyInto(&out.Haproxy) - in.Nginx.DeepCopyInto(&out.Nginx) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HAProxy) DeepCopyInto(out *HAProxy) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HAProxy. -func (in *HAProxy) DeepCopy() *HAProxy { - if in == nil { - return nil - } - out := new(HAProxy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Nginx) DeepCopyInto(out *Nginx) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Nginx. -func (in *Nginx) DeepCopy() *Nginx { - if in == nil { - return nil - } - out := new(Nginx) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/kafka/types.go b/api/apps/v1alpha1/kafka/types.go deleted file mode 100644 index 485f34ee..00000000 --- a/api/apps/v1alpha1/kafka/types.go +++ /dev/null @@ -1,90 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package kafka - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" - k8sRuntime "k8s.io/apimachinery/pkg/runtime" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // Topics configuration. - // +kubebuilder:default:={} - Topics []Topic `json:"topics,omitempty"` - // Kafka configuration. - // +kubebuilder:default:={} - Kafka Kafka `json:"kafka"` - // ZooKeeper configuration. - // +kubebuilder:default:={} - Zookeeper ZooKeeper `json:"zookeeper"` -} - -type Kafka struct { - // Number of Kafka replicas. - // +kubebuilder:default:=3 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume size for Kafka. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the Kafka data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type Topic struct { - // Topic configuration. - Config k8sRuntime.RawExtension `json:"config"` - // Topic name. - Name string `json:"name"` - // Number of partitions. - Partitions int `json:"partitions"` - // Number of replicas. - Replicas int `json:"replicas"` -} - -type ZooKeeper struct { - // Number of ZooKeeper replicas. - // +kubebuilder:default:=3 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume size for ZooKeeper. - // +kubebuilder:default:="5Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the ZooKeeper data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/kafka/zz_generated.deepcopy.go b/api/apps/v1alpha1/kafka/zz_generated.deepcopy.go deleted file mode 100644 index c2d39077..00000000 --- a/api/apps/v1alpha1/kafka/zz_generated.deepcopy.go +++ /dev/null @@ -1,142 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package kafka - -import ( - "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - if in.Topics != nil { - in, out := &in.Topics, &out.Topics - *out = make([]Topic, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.Kafka.DeepCopyInto(&out.Kafka) - in.Zookeeper.DeepCopyInto(&out.Zookeeper) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Kafka) DeepCopyInto(out *Kafka) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Kafka. -func (in *Kafka) DeepCopy() *Kafka { - if in == nil { - return nil - } - out := new(Kafka) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Topic) DeepCopyInto(out *Topic) { - *out = *in - in.Config.DeepCopyInto(&out.Config) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Topic. -func (in *Topic) DeepCopy() *Topic { - if in == nil { - return nil - } - out := new(Topic) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ZooKeeper) DeepCopyInto(out *ZooKeeper) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZooKeeper. -func (in *ZooKeeper) DeepCopy() *ZooKeeper { - if in == nil { - return nil - } - out := new(ZooKeeper) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/kubernetes/types.go b/api/apps/v1alpha1/kubernetes/types.go deleted file mode 100644 index 88a3c97e..00000000 --- a/api/apps/v1alpha1/kubernetes/types.go +++ /dev/null @@ -1,279 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package kubernetes - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" - k8sRuntime "k8s.io/apimachinery/pkg/runtime" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // StorageClass used to store the data. - // +kubebuilder:default:="replicated" - StorageClass string `json:"storageClass"` - // Worker nodes configuration map. - // +kubebuilder:default:={"md0":{"ephemeralStorage":"20Gi","gpus":{},"instanceType":"u1.medium","maxReplicas":10,"minReplicas":0,"resources":{},"roles":{"ingress-nginx"}}} - NodeGroups map[string]NodeGroup `json:"nodeGroups,omitempty"` - // Kubernetes major.minor version to deploy - // +kubebuilder:default:="v1.35" - Version Version `json:"version"` - // External hostname for Kubernetes cluster. Defaults to `.` if empty. - // +kubebuilder:default:="" - Host string `json:"host"` - // Cluster addons configuration. - // +kubebuilder:default:={} - Addons Addons `json:"addons"` - // Kubernetes control-plane configuration. - // +kubebuilder:default:={} - ControlPlane ControlPlane `json:"controlPlane"` - // Optional image overrides for air-gapped or rate-limited registries. - // +kubebuilder:default:={} - Images Images `json:"images"` -} - -type APIServer struct { - // CPU and memory resources for API Server. - // +kubebuilder:default:={} - Resources Resources `json:"resources"` - // Preset if `resources` omitted. - // +kubebuilder:default:="large" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` -} - -type Addons struct { - // Cert-manager addon. - // +kubebuilder:default:={} - CertManager CertManagerAddon `json:"certManager"` - // Cilium CNI plugin. - // +kubebuilder:default:={} - Cilium CiliumAddon `json:"cilium"` - // CoreDNS addon. - // +kubebuilder:default:={} - Coredns CoreDNSAddon `json:"coredns"` - // FluxCD GitOps operator. - // +kubebuilder:default:={} - Fluxcd FluxCDAddon `json:"fluxcd"` - // Gateway API addon. - // +kubebuilder:default:={} - GatewayAPI GatewayAPIAddon `json:"gatewayAPI"` - // NVIDIA GPU Operator. - // +kubebuilder:default:={} - GpuOperator GPUOperatorAddon `json:"gpuOperator"` - // HAMi GPU virtualization middleware. - // +kubebuilder:default:={} - Hami HAMiAddon `json:"hami"` - // Ingress-NGINX controller. - // +kubebuilder:default:={} - IngressNginx IngressNginxAddon `json:"ingressNginx"` - // Monitoring agents. - // +kubebuilder:default:={} - MonitoringAgents MonitoringAgentsAddon `json:"monitoringAgents"` - // Velero backup/restore addon. - // +kubebuilder:default:={} - Velero VeleroAddon `json:"velero"` - // Vertical Pod Autoscaler. - // +kubebuilder:default:={} - VerticalPodAutoscaler VerticalPodAutoscalerAddon `json:"verticalPodAutoscaler"` -} - -type CertManagerAddon struct { - // Enable cert-manager. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type CiliumAddon struct { - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type ControlPlane struct { - // API Server configuration. - // +kubebuilder:default:={} - ApiServer APIServer `json:"apiServer"` - // Controller Manager configuration. - // +kubebuilder:default:={} - ControllerManager ControllerManager `json:"controllerManager"` - // Konnectivity configuration. - // +kubebuilder:default:={} - Konnectivity Konnectivity `json:"konnectivity"` - // Number of control-plane replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Scheduler configuration. - // +kubebuilder:default:={} - Scheduler Scheduler `json:"scheduler"` -} - -type ControllerManager struct { - // CPU and memory resources for Controller Manager. - // +kubebuilder:default:={} - Resources Resources `json:"resources"` - // Preset if `resources` omitted. - // +kubebuilder:default:="micro" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` -} - -type CoreDNSAddon struct { - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type FluxCDAddon struct { - // Enable FluxCD. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type GPU struct { - // Name of GPU, such as "nvidia.com/AD102GL_L40S". - Name string `json:"name"` -} - -type GPUOperatorAddon struct { - // Enable GPU Operator. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type GatewayAPIAddon struct { - // Enable Gateway API. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` -} - -type HAMiAddon struct { - // Enable HAMi (requires GPU Operator). - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type Images struct { - // Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag. - // +kubebuilder:default:="" - WaitForKubeconfig string `json:"waitForKubeconfig,omitempty"` -} - -type IngressNginxAddon struct { - // Enable the controller (requires nodes labeled `ingress-nginx`). - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`. - // +kubebuilder:default:="Proxied" - ExposeMethod IngressNginxExposeMethod `json:"exposeMethod"` - // Domains routed to this tenant cluster when `exposeMethod` is `Proxied`. - // +kubebuilder:default:={} - Hosts []string `json:"hosts,omitempty"` - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type Konnectivity struct { - // Konnectivity Server configuration. - // +kubebuilder:default:={} - Server KonnectivityServer `json:"server"` -} - -type KonnectivityServer struct { - // CPU and memory resources for Konnectivity. - // +kubebuilder:default:={} - Resources Resources `json:"resources"` - // Preset if `resources` omitted. - // +kubebuilder:default:="micro" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` -} - -type MonitoringAgentsAddon struct { - // Enable monitoring agents. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type NodeGroup struct { - // Ephemeral storage size. - // +kubebuilder:default:="20Gi" - EphemeralStorage resource.Quantity `json:"ephemeralStorage"` - // List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). - Gpus []GPU `json:"gpus,omitempty"` - // Virtual machine instance type. - // +kubebuilder:default:="u1.medium" - InstanceType string `json:"instanceType"` - // Maximum number of replicas. - // +kubebuilder:default:=10 - MaxReplicas int `json:"maxReplicas"` - // Minimum number of replicas. - // +kubebuilder:default:=0 - MinReplicas int `json:"minReplicas"` - // CPU and memory resources for each worker node. - Resources Resources `json:"resources"` - // List of node roles. - Roles []string `json:"roles,omitempty"` -} - -type Resources struct { - // CPU available. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type Scheduler struct { - // CPU and memory resources for Scheduler. - // +kubebuilder:default:={} - Resources Resources `json:"resources"` - // Preset if `resources` omitted. - // +kubebuilder:default:="micro" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` -} - -type VeleroAddon struct { - // Enable Velero. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -type VerticalPodAutoscalerAddon struct { - // Custom Helm values overrides. - // +kubebuilder:default:={} - ValuesOverride k8sRuntime.RawExtension `json:"valuesOverride"` -} - -// +kubebuilder:validation:Enum="Proxied";"LoadBalancer" -type IngressNginxExposeMethod string - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string - -// +kubebuilder:validation:Enum="v1.35";"v1.34";"v1.33";"v1.32";"v1.31";"v1.30" -type Version string diff --git a/api/apps/v1alpha1/kubernetes/zz_generated.deepcopy.go b/api/apps/v1alpha1/kubernetes/zz_generated.deepcopy.go deleted file mode 100644 index e021fbaa..00000000 --- a/api/apps/v1alpha1/kubernetes/zz_generated.deepcopy.go +++ /dev/null @@ -1,455 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package kubernetes - -import ( - "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *APIServer) DeepCopyInto(out *APIServer) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServer. -func (in *APIServer) DeepCopy() *APIServer { - if in == nil { - return nil - } - out := new(APIServer) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Addons) DeepCopyInto(out *Addons) { - *out = *in - in.CertManager.DeepCopyInto(&out.CertManager) - in.Cilium.DeepCopyInto(&out.Cilium) - in.Coredns.DeepCopyInto(&out.Coredns) - in.Fluxcd.DeepCopyInto(&out.Fluxcd) - out.GatewayAPI = in.GatewayAPI - in.GpuOperator.DeepCopyInto(&out.GpuOperator) - in.Hami.DeepCopyInto(&out.Hami) - in.IngressNginx.DeepCopyInto(&out.IngressNginx) - in.MonitoringAgents.DeepCopyInto(&out.MonitoringAgents) - in.Velero.DeepCopyInto(&out.Velero) - in.VerticalPodAutoscaler.DeepCopyInto(&out.VerticalPodAutoscaler) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Addons. -func (in *Addons) DeepCopy() *Addons { - if in == nil { - return nil - } - out := new(Addons) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CertManagerAddon) DeepCopyInto(out *CertManagerAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertManagerAddon. -func (in *CertManagerAddon) DeepCopy() *CertManagerAddon { - if in == nil { - return nil - } - out := new(CertManagerAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CiliumAddon) DeepCopyInto(out *CiliumAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CiliumAddon. -func (in *CiliumAddon) DeepCopy() *CiliumAddon { - if in == nil { - return nil - } - out := new(CiliumAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - if in.NodeGroups != nil { - in, out := &in.NodeGroups, &out.NodeGroups - *out = make(map[string]NodeGroup, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } - in.Addons.DeepCopyInto(&out.Addons) - in.ControlPlane.DeepCopyInto(&out.ControlPlane) - out.Images = in.Images -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ControlPlane) DeepCopyInto(out *ControlPlane) { - *out = *in - in.ApiServer.DeepCopyInto(&out.ApiServer) - in.ControllerManager.DeepCopyInto(&out.ControllerManager) - in.Konnectivity.DeepCopyInto(&out.Konnectivity) - in.Scheduler.DeepCopyInto(&out.Scheduler) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlane. -func (in *ControlPlane) DeepCopy() *ControlPlane { - if in == nil { - return nil - } - out := new(ControlPlane) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ControllerManager) DeepCopyInto(out *ControllerManager) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerManager. -func (in *ControllerManager) DeepCopy() *ControllerManager { - if in == nil { - return nil - } - out := new(ControllerManager) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CoreDNSAddon) DeepCopyInto(out *CoreDNSAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CoreDNSAddon. -func (in *CoreDNSAddon) DeepCopy() *CoreDNSAddon { - if in == nil { - return nil - } - out := new(CoreDNSAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluxCDAddon) DeepCopyInto(out *FluxCDAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluxCDAddon. -func (in *FluxCDAddon) DeepCopy() *FluxCDAddon { - if in == nil { - return nil - } - out := new(FluxCDAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GPU) DeepCopyInto(out *GPU) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GPU. -func (in *GPU) DeepCopy() *GPU { - if in == nil { - return nil - } - out := new(GPU) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GPUOperatorAddon) DeepCopyInto(out *GPUOperatorAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GPUOperatorAddon. -func (in *GPUOperatorAddon) DeepCopy() *GPUOperatorAddon { - if in == nil { - return nil - } - out := new(GPUOperatorAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GatewayAPIAddon) DeepCopyInto(out *GatewayAPIAddon) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayAPIAddon. -func (in *GatewayAPIAddon) DeepCopy() *GatewayAPIAddon { - if in == nil { - return nil - } - out := new(GatewayAPIAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HAMiAddon) DeepCopyInto(out *HAMiAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HAMiAddon. -func (in *HAMiAddon) DeepCopy() *HAMiAddon { - if in == nil { - return nil - } - out := new(HAMiAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Images) DeepCopyInto(out *Images) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Images. -func (in *Images) DeepCopy() *Images { - if in == nil { - return nil - } - out := new(Images) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *IngressNginxAddon) DeepCopyInto(out *IngressNginxAddon) { - *out = *in - if in.Hosts != nil { - in, out := &in.Hosts, &out.Hosts - *out = make([]string, len(*in)) - copy(*out, *in) - } - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressNginxAddon. -func (in *IngressNginxAddon) DeepCopy() *IngressNginxAddon { - if in == nil { - return nil - } - out := new(IngressNginxAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Konnectivity) DeepCopyInto(out *Konnectivity) { - *out = *in - in.Server.DeepCopyInto(&out.Server) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Konnectivity. -func (in *Konnectivity) DeepCopy() *Konnectivity { - if in == nil { - return nil - } - out := new(Konnectivity) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KonnectivityServer) DeepCopyInto(out *KonnectivityServer) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KonnectivityServer. -func (in *KonnectivityServer) DeepCopy() *KonnectivityServer { - if in == nil { - return nil - } - out := new(KonnectivityServer) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MonitoringAgentsAddon) DeepCopyInto(out *MonitoringAgentsAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonitoringAgentsAddon. -func (in *MonitoringAgentsAddon) DeepCopy() *MonitoringAgentsAddon { - if in == nil { - return nil - } - out := new(MonitoringAgentsAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NodeGroup) DeepCopyInto(out *NodeGroup) { - *out = *in - out.EphemeralStorage = in.EphemeralStorage.DeepCopy() - if in.Gpus != nil { - in, out := &in.Gpus, &out.Gpus - *out = make([]GPU, len(*in)) - copy(*out, *in) - } - in.Resources.DeepCopyInto(&out.Resources) - if in.Roles != nil { - in, out := &in.Roles, &out.Roles - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeGroup. -func (in *NodeGroup) DeepCopy() *NodeGroup { - if in == nil { - return nil - } - out := new(NodeGroup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Scheduler) DeepCopyInto(out *Scheduler) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Scheduler. -func (in *Scheduler) DeepCopy() *Scheduler { - if in == nil { - return nil - } - out := new(Scheduler) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VeleroAddon) DeepCopyInto(out *VeleroAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroAddon. -func (in *VeleroAddon) DeepCopy() *VeleroAddon { - if in == nil { - return nil - } - out := new(VeleroAddon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *VerticalPodAutoscalerAddon) DeepCopyInto(out *VerticalPodAutoscalerAddon) { - *out = *in - in.ValuesOverride.DeepCopyInto(&out.ValuesOverride) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerAddon. -func (in *VerticalPodAutoscalerAddon) DeepCopy() *VerticalPodAutoscalerAddon { - if in == nil { - return nil - } - out := new(VerticalPodAutoscalerAddon) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/mariadb/types.go b/api/apps/v1alpha1/mariadb/types.go deleted file mode 100644 index b3b6c414..00000000 --- a/api/apps/v1alpha1/mariadb/types.go +++ /dev/null @@ -1,109 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package mariadb - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of MariaDB replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each MariaDB replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // MariaDB major.minor version to deploy - // +kubebuilder:default:="v11.8" - Version Version `json:"version"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // Databases configuration map. - // +kubebuilder:default:={} - Databases map[string]Database `json:"databases,omitempty"` - // Backup configuration. - // +kubebuilder:default:={} - Backup Backup `json:"backup"` -} - -type Backup struct { - // Retention strategy for cleaning up old backups. - // +kubebuilder:default:="--keep-last=3 --keep-daily=3 --keep-within-weekly=1m" - CleanupStrategy string `json:"cleanupStrategy"` - // Enable regular backups (default: false). - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Password for Restic backup encryption. - // +kubebuilder:default:="" - ResticPassword string `json:"resticPassword"` - // Access key for S3 authentication. - // +kubebuilder:default:="" - S3AccessKey string `json:"s3AccessKey"` - // S3 bucket used for storing backups. - // +kubebuilder:default:="s3.example.org/mariadb-backups" - S3Bucket string `json:"s3Bucket"` - // AWS S3 region where backups are stored. - // +kubebuilder:default:="us-east-1" - S3Region string `json:"s3Region"` - // Secret key for S3 authentication. - // +kubebuilder:default:="" - S3SecretKey string `json:"s3SecretKey"` - // Cron schedule for automated backups. - // +kubebuilder:default:="0 2 * * *" - Schedule string `json:"schedule"` -} - -type Database struct { - // Roles assigned to users. - Roles DatabaseRoles `json:"roles,omitempty"` -} - -type DatabaseRoles struct { - // List of users with admin privileges. - Admin []string `json:"admin,omitempty"` - // List of users with read-only privileges. - Readonly []string `json:"readonly,omitempty"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type User struct { - // Maximum number of connections. - MaxUserConnections int `json:"maxUserConnections"` - // Password for the user. - Password string `json:"password"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string - -// +kubebuilder:validation:Enum="v11.8";"v11.4";"v10.11";"v10.6" -type Version string diff --git a/api/apps/v1alpha1/mariadb/zz_generated.deepcopy.go b/api/apps/v1alpha1/mariadb/zz_generated.deepcopy.go deleted file mode 100644 index 4cc5a94f..00000000 --- a/api/apps/v1alpha1/mariadb/zz_generated.deepcopy.go +++ /dev/null @@ -1,171 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package mariadb - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Backup) DeepCopyInto(out *Backup) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup. -func (in *Backup) DeepCopy() *Backup { - if in == nil { - return nil - } - out := new(Backup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Databases != nil { - in, out := &in.Databases, &out.Databases - *out = make(map[string]Database, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } - out.Backup = in.Backup -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Database) DeepCopyInto(out *Database) { - *out = *in - in.Roles.DeepCopyInto(&out.Roles) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database. -func (in *Database) DeepCopy() *Database { - if in == nil { - return nil - } - out := new(Database) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DatabaseRoles) DeepCopyInto(out *DatabaseRoles) { - *out = *in - if in.Admin != nil { - in, out := &in.Admin, &out.Admin - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Readonly != nil { - in, out := &in.Readonly, &out.Readonly - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseRoles. -func (in *DatabaseRoles) DeepCopy() *DatabaseRoles { - if in == nil { - return nil - } - out := new(DatabaseRoles) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/mongodb/types.go b/api/apps/v1alpha1/mongodb/types.go deleted file mode 100644 index 886b716c..00000000 --- a/api/apps/v1alpha1/mongodb/types.go +++ /dev/null @@ -1,149 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package mongodb - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of MongoDB replicas in replica set. - // +kubebuilder:default:=3 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each MongoDB replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // MongoDB major version to deploy. - // +kubebuilder:default:="v8" - Version Version `json:"version"` - // Enable sharded cluster mode. When disabled, deploys a replica set. - // +kubebuilder:default:=false - Sharding bool `json:"sharding"` - // Configuration for sharded cluster mode. - // +kubebuilder:default:={} - ShardingConfig ShardingConfig `json:"shardingConfig"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // Databases configuration map. - // +kubebuilder:default:={} - Databases map[string]Database `json:"databases,omitempty"` - // Backup configuration. - // +kubebuilder:default:={} - Backup Backup `json:"backup"` - // Bootstrap configuration. - // +kubebuilder:default:={} - Bootstrap Bootstrap `json:"bootstrap"` -} - -type Backup struct { - // Destination path for backups (e.g. s3://bucket/path/). - // +kubebuilder:default:="s3://bucket/path/to/folder/" - DestinationPath string `json:"destinationPath,omitempty"` - // Enable regular backups. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // S3 endpoint URL for uploads. - // +kubebuilder:default:="http://minio-gateway-service:9000" - EndpointURL string `json:"endpointURL,omitempty"` - // Retention policy (e.g. "30d"). - // +kubebuilder:default:="30d" - RetentionPolicy string `json:"retentionPolicy,omitempty"` - // Access key for S3 authentication. - // +kubebuilder:default:="" - S3AccessKey string `json:"s3AccessKey,omitempty"` - // Secret key for S3 authentication. - // +kubebuilder:default:="" - S3SecretKey string `json:"s3SecretKey,omitempty"` - // Cron schedule for automated backups. - // +kubebuilder:default:="0 2 * * *" - Schedule string `json:"schedule,omitempty"` -} - -type Bootstrap struct { - // Name of backup to restore from. - // +kubebuilder:default:="" - BackupName string `json:"backupName"` - // Whether to restore from a backup. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Timestamp for point-in-time recovery; empty means latest. - // +kubebuilder:default:="" - RecoveryTime string `json:"recoveryTime,omitempty"` -} - -type Database struct { - // Roles assigned to users. - Roles DatabaseRoles `json:"roles,omitempty"` -} - -type DatabaseRoles struct { - // List of users with admin privileges (readWrite + dbAdmin). - Admin []string `json:"admin,omitempty"` - // List of users with read-only privileges. - Readonly []string `json:"readonly,omitempty"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type Shard struct { - // Shard name. - Name string `json:"name"` - // Number of replicas in this shard. - Replicas int `json:"replicas"` - // PVC size for this shard. - Size resource.Quantity `json:"size"` -} - -type ShardingConfig struct { - // PVC size for config servers. - // +kubebuilder:default:="3Gi" - ConfigServerSize resource.Quantity `json:"configServerSize"` - // Number of config server replicas. - // +kubebuilder:default:=3 - ConfigServers int `json:"configServers"` - // Number of mongos router replicas. - // +kubebuilder:default:=2 - Mongos int `json:"mongos"` - // List of shard configurations. - // +kubebuilder:default:={{"name":"rs0","replicas":3,"size":"10Gi"}} - Shards []Shard `json:"shards,omitempty"` -} - -type User struct { - // Password for the user (auto-generated if omitted). - Password string `json:"password,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string - -// +kubebuilder:validation:Enum="v8";"v7";"v6" -type Version string diff --git a/api/apps/v1alpha1/mongodb/zz_generated.deepcopy.go b/api/apps/v1alpha1/mongodb/zz_generated.deepcopy.go deleted file mode 100644 index 694009f4..00000000 --- a/api/apps/v1alpha1/mongodb/zz_generated.deepcopy.go +++ /dev/null @@ -1,227 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package mongodb - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Backup) DeepCopyInto(out *Backup) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup. -func (in *Backup) DeepCopy() *Backup { - if in == nil { - return nil - } - out := new(Backup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Bootstrap) DeepCopyInto(out *Bootstrap) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Bootstrap. -func (in *Bootstrap) DeepCopy() *Bootstrap { - if in == nil { - return nil - } - out := new(Bootstrap) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() - in.ShardingConfig.DeepCopyInto(&out.ShardingConfig) - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Databases != nil { - in, out := &in.Databases, &out.Databases - *out = make(map[string]Database, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } - out.Backup = in.Backup - out.Bootstrap = in.Bootstrap -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Database) DeepCopyInto(out *Database) { - *out = *in - in.Roles.DeepCopyInto(&out.Roles) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database. -func (in *Database) DeepCopy() *Database { - if in == nil { - return nil - } - out := new(Database) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DatabaseRoles) DeepCopyInto(out *DatabaseRoles) { - *out = *in - if in.Admin != nil { - in, out := &in.Admin, &out.Admin - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Readonly != nil { - in, out := &in.Readonly, &out.Readonly - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseRoles. -func (in *DatabaseRoles) DeepCopy() *DatabaseRoles { - if in == nil { - return nil - } - out := new(DatabaseRoles) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Shard) DeepCopyInto(out *Shard) { - *out = *in - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Shard. -func (in *Shard) DeepCopy() *Shard { - if in == nil { - return nil - } - out := new(Shard) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ShardingConfig) DeepCopyInto(out *ShardingConfig) { - *out = *in - out.ConfigServerSize = in.ConfigServerSize.DeepCopy() - if in.Shards != nil { - in, out := &in.Shards, &out.Shards - *out = make([]Shard, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ShardingConfig. -func (in *ShardingConfig) DeepCopy() *ShardingConfig { - if in == nil { - return nil - } - out := new(ShardingConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/nats/types.go b/api/apps/v1alpha1/nats/types.go deleted file mode 100644 index 5437355d..00000000 --- a/api/apps/v1alpha1/nats/types.go +++ /dev/null @@ -1,78 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package nats - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" - k8sRuntime "k8s.io/apimachinery/pkg/runtime" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each NATS replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // Jetstream configuration. - // +kubebuilder:default:={} - Jetstream Jetstream `json:"jetstream"` - // NATS configuration. - // +kubebuilder:default:={} - Config ValuesConfig `json:"config"` -} - -type ValuesConfig struct { - // Additional configuration to merge into NATS config. - // +kubebuilder:default:={} - Merge *k8sRuntime.RawExtension `json:"merge,omitempty"` - // Additional resolver configuration to merge into NATS config. - // +kubebuilder:default:={} - Resolver *k8sRuntime.RawExtension `json:"resolver,omitempty"` -} - -type Jetstream struct { - // Enable or disable Jetstream for persistent messaging in NATS. - // +kubebuilder:default:=true - Enabled bool `json:"enabled"` - // Jetstream persistent storage size. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type User struct { - // Password for the user. - Password string `json:"password,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/nats/zz_generated.deepcopy.go b/api/apps/v1alpha1/nats/zz_generated.deepcopy.go deleted file mode 100644 index f6c23cb1..00000000 --- a/api/apps/v1alpha1/nats/zz_generated.deepcopy.go +++ /dev/null @@ -1,149 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package nats - -import ( - "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - in.Jetstream.DeepCopyInto(&out.Jetstream) - in.Config.DeepCopyInto(&out.Config) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Jetstream) DeepCopyInto(out *Jetstream) { - *out = *in - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Jetstream. -func (in *Jetstream) DeepCopy() *Jetstream { - if in == nil { - return nil - } - out := new(Jetstream) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ValuesConfig) DeepCopyInto(out *ValuesConfig) { - *out = *in - if in.Merge != nil { - in, out := &in.Merge, &out.Merge - *out = new(runtime.RawExtension) - (*in).DeepCopyInto(*out) - } - if in.Resolver != nil { - in, out := &in.Resolver, &out.Resolver - *out = new(runtime.RawExtension) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValuesConfig. -func (in *ValuesConfig) DeepCopy() *ValuesConfig { - if in == nil { - return nil - } - out := new(ValuesConfig) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/openbao/types.go b/api/apps/v1alpha1/openbao/types.go deleted file mode 100644 index bb5d12d9..00000000 --- a/api/apps/v1alpha1/openbao/types.go +++ /dev/null @@ -1,51 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package openbao - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of OpenBAO replicas. HA with Raft is automatically enabled when replicas > 1. Switching between standalone (file storage) and HA (Raft storage) modes requires data migration. - // +kubebuilder:default:=1 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each OpenBAO replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size for data storage. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // Enable the OpenBAO web UI. - // +kubebuilder:default:=true - Ui bool `json:"ui"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/openbao/zz_generated.deepcopy.go b/api/apps/v1alpha1/openbao/zz_generated.deepcopy.go deleted file mode 100644 index baa1258b..00000000 --- a/api/apps/v1alpha1/openbao/zz_generated.deepcopy.go +++ /dev/null @@ -1,85 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package openbao - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/opensearch/types.go b/api/apps/v1alpha1/opensearch/types.go deleted file mode 100644 index b188cdfa..00000000 --- a/api/apps/v1alpha1/opensearch/types.go +++ /dev/null @@ -1,115 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package opensearch - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of OpenSearch nodes in the cluster. - // +kubebuilder:default:=3 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each OpenSearch node. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. OpenSearch requires minimum 2Gi memory. - // +kubebuilder:default:="large" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // How strictly to enforce pod distribution across nodes and zones. - // +kubebuilder:default:="soft" - TopologySpreadPolicy TopologySpreadPolicy `json:"topologySpreadPolicy"` - // OpenSearch major version to deploy. - // +kubebuilder:default:="v2" - Version Version `json:"version"` - // Container images used by the operator. - // +kubebuilder:default:={} - Images Images `json:"images"` - // Node roles configuration. - // +kubebuilder:default:={} - NodeRoles NodeRoles `json:"nodeRoles"` - // Custom OpenSearch users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // OpenSearch Dashboards configuration. - // +kubebuilder:default:={} - Dashboards Dashboards `json:"dashboards"` -} - -type Dashboards struct { - // Enable OpenSearch Dashboards deployment. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Number of Dashboards replicas. - // +kubebuilder:default:=1 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for Dashboards. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset for Dashboards. - // +kubebuilder:default:="medium" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` -} - -type Images struct { - // OpenSearch image. - // +kubebuilder:default:="" - Opensearch string `json:"opensearch"` -} - -type NodeRoles struct { - // Enable data role. - // +kubebuilder:default:=true - Data bool `json:"data"` - // Enable ingest role. - // +kubebuilder:default:=true - Ingest bool `json:"ingest"` - // Enable cluster_manager role. - // +kubebuilder:default:=true - Master bool `json:"master"` - // Enable machine learning role. - // +kubebuilder:default:=false - Ml bool `json:"ml"` -} - -type Resources struct { - // CPU available to each node. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each node. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type User struct { - // Password for the user (auto-generated if omitted). - Password string `json:"password,omitempty"` - // List of OpenSearch roles. - Roles []string `json:"roles,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string - -// +kubebuilder:validation:Enum="soft";"hard" -type TopologySpreadPolicy string - -// +kubebuilder:validation:Enum="v3";"v2";"v1" -type Version string diff --git a/api/apps/v1alpha1/opensearch/zz_generated.deepcopy.go b/api/apps/v1alpha1/opensearch/zz_generated.deepcopy.go deleted file mode 100644 index f7f2daef..00000000 --- a/api/apps/v1alpha1/opensearch/zz_generated.deepcopy.go +++ /dev/null @@ -1,161 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package opensearch - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() - out.Images = in.Images - out.NodeRoles = in.NodeRoles - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } - in.Dashboards.DeepCopyInto(&out.Dashboards) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Dashboards) DeepCopyInto(out *Dashboards) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Dashboards. -func (in *Dashboards) DeepCopy() *Dashboards { - if in == nil { - return nil - } - out := new(Dashboards) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Images) DeepCopyInto(out *Images) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Images. -func (in *Images) DeepCopy() *Images { - if in == nil { - return nil - } - out := new(Images) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NodeRoles) DeepCopyInto(out *NodeRoles) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRoles. -func (in *NodeRoles) DeepCopy() *NodeRoles { - if in == nil { - return nil - } - out := new(NodeRoles) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in - if in.Roles != nil { - in, out := &in.Roles, &out.Roles - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/postgresql/types.go b/api/apps/v1alpha1/postgresql/types.go deleted file mode 100644 index a2ff77a8..00000000 --- a/api/apps/v1alpha1/postgresql/types.go +++ /dev/null @@ -1,153 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package postgresql - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of Postgres replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each PostgreSQL replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="micro" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // PostgreSQL major version to deploy - // +kubebuilder:default:="v18" - Version Version `json:"version"` - // PostgreSQL server configuration. - // +kubebuilder:default:={} - Postgresql PostgreSQL `json:"postgresql"` - // Quorum configuration for synchronous replication. - // +kubebuilder:default:={} - Quorum Quorum `json:"quorum"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // Databases configuration map. - // +kubebuilder:default:={} - Databases map[string]Database `json:"databases,omitempty"` - // Backup configuration. - // +kubebuilder:default:={} - Backup Backup `json:"backup"` - // Bootstrap configuration. - // +kubebuilder:default:={} - Bootstrap Bootstrap `json:"bootstrap"` -} - -type Backup struct { - // Destination path for backups (e.g. s3://bucket/path/). - // +kubebuilder:default:="s3://bucket/path/to/folder/" - DestinationPath string `json:"destinationPath,omitempty"` - // Enable regular backups. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // S3 endpoint URL for uploads. - // +kubebuilder:default:="http://minio-gateway-service:9000" - EndpointURL string `json:"endpointURL,omitempty"` - // Retention policy (e.g. "30d"). - // +kubebuilder:default:="30d" - RetentionPolicy string `json:"retentionPolicy,omitempty"` - // Access key for S3 authentication. - // +kubebuilder:default:="" - S3AccessKey string `json:"s3AccessKey,omitempty"` - // Secret key for S3 authentication. - // +kubebuilder:default:="" - S3SecretKey string `json:"s3SecretKey,omitempty"` - // Cron schedule for automated backups. - // +kubebuilder:default:="0 2 * * * *" - Schedule string `json:"schedule,omitempty"` -} - -type Bootstrap struct { - // Whether to restore from a backup. - // +kubebuilder:default:=false - Enabled bool `json:"enabled"` - // Previous cluster name before deletion. - // +kubebuilder:default:="" - OldName string `json:"oldName"` - // Timestamp (RFC3339) for point-in-time recovery; empty means latest. - // +kubebuilder:default:="" - RecoveryTime string `json:"recoveryTime,omitempty"` - // Barman server name (S3 path prefix) used by the original cluster when writing backups. Set this only when the original cluster had an explicit barmanObjectStore.serverName that differed from its Kubernetes resource name. - // +kubebuilder:default:="" - ServerName string `json:"serverName,omitempty"` -} - -type Database struct { - // List of enabled PostgreSQL extensions. - Extensions []string `json:"extensions,omitempty"` - // Roles assigned to users. - Roles DatabaseRoles `json:"roles,omitempty"` -} - -type DatabaseRoles struct { - // List of users with admin privileges. - Admin []string `json:"admin,omitempty"` - // List of users with read-only privileges. - Readonly []string `json:"readonly,omitempty"` -} - -type PostgreSQL struct { - // PostgreSQL server parameters. - // +kubebuilder:default:={} - Parameters PostgreSQLParameters `json:"parameters,omitempty"` -} - -type PostgreSQLParameters struct { - // Maximum number of concurrent connections to the database server. - // +kubebuilder:default:=100 - MaxConnections int `json:"max_connections,omitempty"` -} - -type Quorum struct { - // Maximum number of synchronous replicas allowed (must be less than total replicas). - // +kubebuilder:default:=0 - MaxSyncReplicas int `json:"maxSyncReplicas"` - // Minimum number of synchronous replicas required for commit. - // +kubebuilder:default:=0 - MinSyncReplicas int `json:"minSyncReplicas"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type User struct { - // Password for the user. - Password string `json:"password,omitempty"` - // Whether the user has replication privileges. - Replication bool `json:"replication,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string - -// +kubebuilder:validation:Enum="v18";"v17";"v16";"v15";"v14";"v13" -type Version string diff --git a/api/apps/v1alpha1/postgresql/zz_generated.deepcopy.go b/api/apps/v1alpha1/postgresql/zz_generated.deepcopy.go deleted file mode 100644 index 5fba855e..00000000 --- a/api/apps/v1alpha1/postgresql/zz_generated.deepcopy.go +++ /dev/null @@ -1,240 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package postgresql - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Backup) DeepCopyInto(out *Backup) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backup. -func (in *Backup) DeepCopy() *Backup { - if in == nil { - return nil - } - out := new(Backup) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Bootstrap) DeepCopyInto(out *Bootstrap) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Bootstrap. -func (in *Bootstrap) DeepCopy() *Bootstrap { - if in == nil { - return nil - } - out := new(Bootstrap) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() - out.Postgresql = in.Postgresql - out.Quorum = in.Quorum - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Databases != nil { - in, out := &in.Databases, &out.Databases - *out = make(map[string]Database, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } - out.Backup = in.Backup - out.Bootstrap = in.Bootstrap -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Database) DeepCopyInto(out *Database) { - *out = *in - if in.Extensions != nil { - in, out := &in.Extensions, &out.Extensions - *out = make([]string, len(*in)) - copy(*out, *in) - } - in.Roles.DeepCopyInto(&out.Roles) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database. -func (in *Database) DeepCopy() *Database { - if in == nil { - return nil - } - out := new(Database) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DatabaseRoles) DeepCopyInto(out *DatabaseRoles) { - *out = *in - if in.Admin != nil { - in, out := &in.Admin, &out.Admin - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Readonly != nil { - in, out := &in.Readonly, &out.Readonly - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseRoles. -func (in *DatabaseRoles) DeepCopy() *DatabaseRoles { - if in == nil { - return nil - } - out := new(DatabaseRoles) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PostgreSQL) DeepCopyInto(out *PostgreSQL) { - *out = *in - out.Parameters = in.Parameters -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQL. -func (in *PostgreSQL) DeepCopy() *PostgreSQL { - if in == nil { - return nil - } - out := new(PostgreSQL) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PostgreSQLParameters) DeepCopyInto(out *PostgreSQLParameters) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLParameters. -func (in *PostgreSQLParameters) DeepCopy() *PostgreSQLParameters { - if in == nil { - return nil - } - out := new(PostgreSQLParameters) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Quorum) DeepCopyInto(out *Quorum) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Quorum. -func (in *Quorum) DeepCopy() *Quorum { - if in == nil { - return nil - } - out := new(Quorum) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/qdrant/types.go b/api/apps/v1alpha1/qdrant/types.go deleted file mode 100644 index 203e9a97..00000000 --- a/api/apps/v1alpha1/qdrant/types.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package qdrant - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of Qdrant replicas. Cluster mode is automatically enabled when replicas > 1. - // +kubebuilder:default:=1 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each Qdrant replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="small" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for vector data storage. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/qdrant/zz_generated.deepcopy.go b/api/apps/v1alpha1/qdrant/zz_generated.deepcopy.go deleted file mode 100644 index 2abfd37e..00000000 --- a/api/apps/v1alpha1/qdrant/zz_generated.deepcopy.go +++ /dev/null @@ -1,85 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package qdrant - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/rabbitmq/types.go b/api/apps/v1alpha1/rabbitmq/types.go deleted file mode 100644 index f67c4402..00000000 --- a/api/apps/v1alpha1/rabbitmq/types.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package rabbitmq - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of RabbitMQ replicas. - // +kubebuilder:default:=3 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each RabbitMQ replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="10Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // RabbitMQ major.minor version to deploy - // +kubebuilder:default:="v4.2" - Version Version `json:"version"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // Virtual hosts configuration map. - // +kubebuilder:default:={} - Vhosts map[string]Vhost `json:"vhosts,omitempty"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type Roles struct { - // List of admin users. - Admin []string `json:"admin,omitempty"` - // List of readonly users. - Readonly []string `json:"readonly,omitempty"` -} - -type User struct { - // Password for the user. - Password string `json:"password,omitempty"` -} - -type Vhost struct { - // Virtual host roles list. - Roles Roles `json:"roles"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string - -// +kubebuilder:validation:Enum="v4.2";"v4.1";"v4.0";"v3.13" -type Version string diff --git a/api/apps/v1alpha1/rabbitmq/zz_generated.deepcopy.go b/api/apps/v1alpha1/rabbitmq/zz_generated.deepcopy.go deleted file mode 100644 index a1d55f89..00000000 --- a/api/apps/v1alpha1/rabbitmq/zz_generated.deepcopy.go +++ /dev/null @@ -1,155 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package rabbitmq - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Vhosts != nil { - in, out := &in.Vhosts, &out.Vhosts - *out = make(map[string]Vhost, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Roles) DeepCopyInto(out *Roles) { - *out = *in - if in.Admin != nil { - in, out := &in.Admin, &out.Admin - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Readonly != nil { - in, out := &in.Readonly, &out.Readonly - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Roles. -func (in *Roles) DeepCopy() *Roles { - if in == nil { - return nil - } - out := new(Roles) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Vhost) DeepCopyInto(out *Vhost) { - *out = *in - in.Roles.DeepCopyInto(&out.Roles) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Vhost. -func (in *Vhost) DeepCopy() *Vhost { - if in == nil { - return nil - } - out := new(Vhost) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/redis/types.go b/api/apps/v1alpha1/redis/types.go deleted file mode 100644 index e9a02c72..00000000 --- a/api/apps/v1alpha1/redis/types.go +++ /dev/null @@ -1,57 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package redis - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of Redis replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each Redis replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Persistent Volume Claim size available for application data. - // +kubebuilder:default:="1Gi" - Size resource.Quantity `json:"size"` - // StorageClass used to store the data. - // +kubebuilder:default:="" - StorageClass string `json:"storageClass"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // Redis major version to deploy - // +kubebuilder:default:="v8" - Version Version `json:"version"` - // Enable password generation. - // +kubebuilder:default:=true - AuthEnabled bool `json:"authEnabled"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string - -// +kubebuilder:validation:Enum="v8";"v7" -type Version string diff --git a/api/apps/v1alpha1/redis/zz_generated.deepcopy.go b/api/apps/v1alpha1/redis/zz_generated.deepcopy.go deleted file mode 100644 index 6390200c..00000000 --- a/api/apps/v1alpha1/redis/zz_generated.deepcopy.go +++ /dev/null @@ -1,85 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package redis - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - out.Size = in.Size.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/tcpbalancer/types.go b/api/apps/v1alpha1/tcpbalancer/types.go deleted file mode 100644 index aa99cd6d..00000000 --- a/api/apps/v1alpha1/tcpbalancer/types.go +++ /dev/null @@ -1,75 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package tcpbalancer - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of HAProxy replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each TCP Balancer replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // HTTP and HTTPS configuration. - // +kubebuilder:default:={} - HttpAndHttps HttpAndHttps `json:"httpAndHttps"` - // Secure HTTP by whitelisting client networks (default: false). - // +kubebuilder:default:=false - WhitelistHTTP bool `json:"whitelistHTTP"` - // List of allowed client networks. - // +kubebuilder:default:={} - Whitelist []string `json:"whitelist,omitempty"` -} - -type HttpAndHttps struct { - // Endpoint addresses list. - // +kubebuilder:default:={} - Endpoints []string `json:"endpoints,omitempty"` - // Mode for balancer. - // +kubebuilder:default:="tcp" - Mode Mode `json:"mode"` - // Target ports configuration. - // +kubebuilder:default:={} - TargetPorts TargetPorts `json:"targetPorts"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type TargetPorts struct { - // HTTP port number. - // +kubebuilder:default:=80 - Http int `json:"http"` - // HTTPS port number. - // +kubebuilder:default:=443 - Https int `json:"https"` -} - -// +kubebuilder:validation:Enum="tcp";"tcp-with-proxy" -type Mode string - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/tcpbalancer/zz_generated.deepcopy.go b/api/apps/v1alpha1/tcpbalancer/zz_generated.deepcopy.go deleted file mode 100644 index 1c63eafc..00000000 --- a/api/apps/v1alpha1/tcpbalancer/zz_generated.deepcopy.go +++ /dev/null @@ -1,126 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package tcpbalancer - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - in.HttpAndHttps.DeepCopyInto(&out.HttpAndHttps) - if in.Whitelist != nil { - in, out := &in.Whitelist, &out.Whitelist - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HttpAndHttps) DeepCopyInto(out *HttpAndHttps) { - *out = *in - if in.Endpoints != nil { - in, out := &in.Endpoints, &out.Endpoints - *out = make([]string, len(*in)) - copy(*out, *in) - } - out.TargetPorts = in.TargetPorts -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HttpAndHttps. -func (in *HttpAndHttps) DeepCopy() *HttpAndHttps { - if in == nil { - return nil - } - out := new(HttpAndHttps) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TargetPorts) DeepCopyInto(out *TargetPorts) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetPorts. -func (in *TargetPorts) DeepCopy() *TargetPorts { - if in == nil { - return nil - } - out := new(TargetPorts) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/tenant/types.go b/api/apps/v1alpha1/tenant/types.go deleted file mode 100644 index 60f8bb22..00000000 --- a/api/apps/v1alpha1/tenant/types.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package tenant - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host). - // +kubebuilder:default:="" - Host string `json:"host,omitempty"` - // Deploy own Etcd cluster. - // +kubebuilder:default:=false - Etcd bool `json:"etcd"` - // Deploy own Monitoring Stack. - // +kubebuilder:default:=false - Monitoring bool `json:"monitoring"` - // Deploy own Ingress Controller. - // +kubebuilder:default:=false - Ingress bool `json:"ingress"` - // Deploy own SeaweedFS. - // +kubebuilder:default:=false - Seaweedfs bool `json:"seaweedfs"` - // The name of a SchedulingClass CR to apply scheduling constraints for this tenant's workloads. - // +kubebuilder:default:="" - SchedulingClass string `json:"schedulingClass,omitempty"` - // Define resource quotas for the tenant. - // +kubebuilder:default:={} - ResourceQuotas map[string]resource.Quantity `json:"resourceQuotas,omitempty"` -} diff --git a/api/apps/v1alpha1/tenant/zz_generated.deepcopy.go b/api/apps/v1alpha1/tenant/zz_generated.deepcopy.go deleted file mode 100644 index 784a8f25..00000000 --- a/api/apps/v1alpha1/tenant/zz_generated.deepcopy.go +++ /dev/null @@ -1,74 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package tenant - -import ( - "k8s.io/apimachinery/pkg/api/resource" - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - if in.ResourceQuotas != nil { - in, out := &in.ResourceQuotas, &out.ResourceQuotas - *out = make(map[string]resource.Quantity, len(*in)) - for key, val := range *in { - (*out)[key] = val.DeepCopy() - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/vmdisk/types.go b/api/apps/v1alpha1/vmdisk/types.go deleted file mode 100644 index c493f49c..00000000 --- a/api/apps/v1alpha1/vmdisk/types.go +++ /dev/null @@ -1,61 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package vmdisk - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // The source image location used to create a disk. - // +kubebuilder:default:={} - Source Source `json:"source"` - // Defines if disk should be considered optical. - // +kubebuilder:default:=false - Optical bool `json:"optical"` - // The size of the disk allocated for the virtual machine. - // +kubebuilder:default:="5Gi" - Storage resource.Quantity `json:"storage"` - // StorageClass used to store the data. - // +kubebuilder:default:="replicated" - StorageClass string `json:"storageClass"` -} - -type Source struct { - // Clone an existing vm-disk. - Disk *SourceDisk `json:"disk,omitempty"` - // Download image from an HTTP source. - Http *SourceHTTP `json:"http,omitempty"` - // Use image by name from default collection. - Image *SourceImage `json:"image,omitempty"` - // Upload local image. - Upload *SourceUpload `json:"upload,omitempty"` -} - -type SourceDisk struct { - // Name of the vm-disk to clone. - Name string `json:"name"` -} - -type SourceHTTP struct { - // URL to download the image. - Url string `json:"url"` -} - -type SourceImage struct { - // Name of the image to use. - Name string `json:"name"` -} - -type SourceUpload struct { -} diff --git a/api/apps/v1alpha1/vmdisk/zz_generated.deepcopy.go b/api/apps/v1alpha1/vmdisk/zz_generated.deepcopy.go deleted file mode 100644 index 301bb1d9..00000000 --- a/api/apps/v1alpha1/vmdisk/zz_generated.deepcopy.go +++ /dev/null @@ -1,163 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package vmdisk - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Source.DeepCopyInto(&out.Source) - out.Storage = in.Storage.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Source) DeepCopyInto(out *Source) { - *out = *in - if in.Disk != nil { - in, out := &in.Disk, &out.Disk - *out = new(SourceDisk) - **out = **in - } - if in.Http != nil { - in, out := &in.Http, &out.Http - *out = new(SourceHTTP) - **out = **in - } - if in.Image != nil { - in, out := &in.Image, &out.Image - *out = new(SourceImage) - **out = **in - } - if in.Upload != nil { - in, out := &in.Upload, &out.Upload - *out = new(SourceUpload) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Source. -func (in *Source) DeepCopy() *Source { - if in == nil { - return nil - } - out := new(Source) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SourceDisk) DeepCopyInto(out *SourceDisk) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceDisk. -func (in *SourceDisk) DeepCopy() *SourceDisk { - if in == nil { - return nil - } - out := new(SourceDisk) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SourceHTTP) DeepCopyInto(out *SourceHTTP) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceHTTP. -func (in *SourceHTTP) DeepCopy() *SourceHTTP { - if in == nil { - return nil - } - out := new(SourceHTTP) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SourceImage) DeepCopyInto(out *SourceImage) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceImage. -func (in *SourceImage) DeepCopy() *SourceImage { - if in == nil { - return nil - } - out := new(SourceImage) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SourceUpload) DeepCopyInto(out *SourceUpload) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceUpload. -func (in *SourceUpload) DeepCopy() *SourceUpload { - if in == nil { - return nil - } - out := new(SourceUpload) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/vminstance/types.go b/api/apps/v1alpha1/vminstance/types.go deleted file mode 100644 index 9c48724a..00000000 --- a/api/apps/v1alpha1/vminstance/types.go +++ /dev/null @@ -1,100 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package vminstance - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // Method to pass through traffic to the VM. - // +kubebuilder:default:="PortList" - ExternalMethod ExternalMethod `json:"externalMethod"` - // Ports to forward from outside the cluster. - // +kubebuilder:default:={22} - ExternalPorts []int `json:"externalPorts,omitempty"` - // Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect. - // +kubebuilder:default:=true - ExternalAllowICMP bool `json:"externalAllowICMP"` - // Requested running state of the VirtualMachineInstance - // +kubebuilder:default:="Always" - RunStrategy RunStrategy `json:"runStrategy"` - // Virtual Machine instance type. - // +kubebuilder:default:="u1.medium" - InstanceType string `json:"instanceType"` - // Virtual Machine preferences profile. - // +kubebuilder:default:="ubuntu" - InstanceProfile string `json:"instanceProfile"` - // List of disks to attach. - // +kubebuilder:default:={} - Disks []Disk `json:"disks,omitempty"` - // Networks to attach the VM to. - // +kubebuilder:default:={} - Networks []Network `json:"networks,omitempty"` - // Deprecated: use networks instead. - // +kubebuilder:default:={} - Subnets []Network `json:"subnets,omitempty"` - // List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). - // +kubebuilder:default:={} - Gpus []GPU `json:"gpus,omitempty"` - // Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map - // +kubebuilder:default:="" - CpuModel string `json:"cpuModel"` - // Resource configuration for the virtual machine. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // List of SSH public keys for authentication. - // +kubebuilder:default:={} - SshKeys []string `json:"sshKeys,omitempty"` - // Cloud-init user data. - // +kubebuilder:default:="" - CloudInit string `json:"cloudInit"` - // Seed string to generate SMBIOS UUID for the VM. - // +kubebuilder:default:="" - CloudInitSeed string `json:"cloudInitSeed"` -} - -type Disk struct { - // Disk bus type (e.g. "sata"). - Bus string `json:"bus,omitempty"` - // Disk name. - Name string `json:"name"` -} - -type GPU struct { - // The name of the GPU resource to attach. - Name string `json:"name"` -} - -type Network struct { - // Network attachment name. - Name string `json:"name,omitempty"` -} - -type Resources struct { - // Number of CPU cores allocated. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Amount of memory allocated. - Memory resource.Quantity `json:"memory,omitempty"` - // Number of CPU sockets (vCPU topology). - Sockets resource.Quantity `json:"sockets,omitempty"` -} - -// +kubebuilder:validation:Enum="PortList";"WholeIP" -type ExternalMethod string - -// +kubebuilder:validation:Enum="Always";"Halted";"Manual";"RerunOnFailure";"Once" -type RunStrategy string diff --git a/api/apps/v1alpha1/vminstance/zz_generated.deepcopy.go b/api/apps/v1alpha1/vminstance/zz_generated.deepcopy.go deleted file mode 100644 index 86d5ddfc..00000000 --- a/api/apps/v1alpha1/vminstance/zz_generated.deepcopy.go +++ /dev/null @@ -1,160 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package vminstance - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - if in.ExternalPorts != nil { - in, out := &in.ExternalPorts, &out.ExternalPorts - *out = make([]int, len(*in)) - copy(*out, *in) - } - if in.Disks != nil { - in, out := &in.Disks, &out.Disks - *out = make([]Disk, len(*in)) - copy(*out, *in) - } - if in.Networks != nil { - in, out := &in.Networks, &out.Networks - *out = make([]Network, len(*in)) - copy(*out, *in) - } - if in.Subnets != nil { - in, out := &in.Subnets, &out.Subnets - *out = make([]Network, len(*in)) - copy(*out, *in) - } - if in.Gpus != nil { - in, out := &in.Gpus, &out.Gpus - *out = make([]GPU, len(*in)) - copy(*out, *in) - } - in.Resources.DeepCopyInto(&out.Resources) - if in.SshKeys != nil { - in, out := &in.SshKeys, &out.SshKeys - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Disk) DeepCopyInto(out *Disk) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Disk. -func (in *Disk) DeepCopy() *Disk { - if in == nil { - return nil - } - out := new(Disk) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GPU) DeepCopyInto(out *GPU) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GPU. -func (in *GPU) DeepCopy() *GPU { - if in == nil { - return nil - } - out := new(GPU) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Network) DeepCopyInto(out *Network) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Network. -func (in *Network) DeepCopy() *Network { - if in == nil { - return nil - } - out := new(Network) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() - out.Sockets = in.Sockets.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/vpc/types.go b/api/apps/v1alpha1/vpc/types.go deleted file mode 100644 index fed72f58..00000000 --- a/api/apps/v1alpha1/vpc/types.go +++ /dev/null @@ -1,49 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package vpc - -import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Subnets of a VPC - // +kubebuilder:default:={} - Subnets []Subnet `json:"subnets,omitempty"` - // VPC peering connections (bidirectional declaration required) - // +kubebuilder:default:={} - Peers []Peer `json:"peers,omitempty"` - // Static routes for the VPC - // +kubebuilder:default:={} - Routes []Route `json:"routes,omitempty"` -} - -type Peer struct { - // Namespace of the remote tenant - TenantNamespace string `json:"tenantNamespace"` - // Logical name of the remote VPC (without "virtualprivatecloud-" prefix) - VpcName string `json:"vpcName"` -} - -type Route struct { - // Destination CIDR - Cidr string `json:"cidr"` - // Next hop IP address - NextHopIP string `json:"nextHopIP"` -} - -type Subnet struct { - // IP address range - Cidr string `json:"cidr,omitempty"` - // Subnet name - Name string `json:"name"` -} diff --git a/api/apps/v1alpha1/vpc/zz_generated.deepcopy.go b/api/apps/v1alpha1/vpc/zz_generated.deepcopy.go deleted file mode 100644 index 3cda29c4..00000000 --- a/api/apps/v1alpha1/vpc/zz_generated.deepcopy.go +++ /dev/null @@ -1,126 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package vpc - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - if in.Subnets != nil { - in, out := &in.Subnets, &out.Subnets - *out = make([]Subnet, len(*in)) - copy(*out, *in) - } - if in.Peers != nil { - in, out := &in.Peers, &out.Peers - *out = make([]Peer, len(*in)) - copy(*out, *in) - } - if in.Routes != nil { - in, out := &in.Routes, &out.Routes - *out = make([]Route, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Peer) DeepCopyInto(out *Peer) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Peer. -func (in *Peer) DeepCopy() *Peer { - if in == nil { - return nil - } - out := new(Peer) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Route) DeepCopyInto(out *Route) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route. -func (in *Route) DeepCopy() *Route { - if in == nil { - return nil - } - out := new(Route) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Subnet) DeepCopyInto(out *Subnet) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subnet. -func (in *Subnet) DeepCopy() *Subnet { - if in == nil { - return nil - } - out := new(Subnet) - in.DeepCopyInto(out) - return out -} diff --git a/api/apps/v1alpha1/vpn/types.go b/api/apps/v1alpha1/vpn/types.go deleted file mode 100644 index 7ec0b0e3..00000000 --- a/api/apps/v1alpha1/vpn/types.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by values-gen. DO NOT EDIT. -// +kubebuilder:object:generate=true -// +groupName=apps.cozystack.io -// +versionName=v1alpha1 -package vpn - -import ( - resource "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +kubebuilder:object:root=true -type Config struct { - v1.TypeMeta `json:",inline"` - v1.ObjectMeta `json:"metadata,omitempty"` - Spec ConfigSpec `json:"spec,omitempty"` -} - -type ConfigSpec struct { - // Number of VPN server replicas. - // +kubebuilder:default:=2 - Replicas int `json:"replicas"` - // Explicit CPU and memory configuration for each VPN server replica. When omitted, the preset defined in `resourcesPreset` is applied. - // +kubebuilder:default:={} - Resources Resources `json:"resources,omitempty"` - // Default sizing preset used when `resources` is omitted. - // +kubebuilder:default:="nano" - ResourcesPreset ResourcesPreset `json:"resourcesPreset"` - // Enable external access from outside the cluster. - // +kubebuilder:default:=false - External bool `json:"external"` - // Host used to substitute into generated URLs. - // +kubebuilder:default:="" - Host string `json:"host"` - // Users configuration map. - // +kubebuilder:default:={} - Users map[string]User `json:"users,omitempty"` - // List of externalIPs for service. Optional. If not specified, will use LoadBalancer service by default. - // +kubebuilder:default:={} - ExternalIPs []string `json:"externalIPs,omitempty"` -} - -type Resources struct { - // CPU available to each replica. - Cpu resource.Quantity `json:"cpu,omitempty"` - // Memory (RAM) available to each replica. - Memory resource.Quantity `json:"memory,omitempty"` -} - -type User struct { - // Password for the user (autogenerated if not provided). - Password string `json:"password,omitempty"` -} - -// +kubebuilder:validation:Enum="nano";"micro";"small";"medium";"large";"xlarge";"2xlarge" -type ResourcesPreset string diff --git a/api/apps/v1alpha1/vpn/zz_generated.deepcopy.go b/api/apps/v1alpha1/vpn/zz_generated.deepcopy.go deleted file mode 100644 index a3595bb0..00000000 --- a/api/apps/v1alpha1/vpn/zz_generated.deepcopy.go +++ /dev/null @@ -1,111 +0,0 @@ -//go:build !ignore_autogenerated - -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen. DO NOT EDIT. - -package vpn - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigSpec) DeepCopyInto(out *ConfigSpec) { - *out = *in - in.Resources.DeepCopyInto(&out.Resources) - if in.Users != nil { - in, out := &in.Users, &out.Users - *out = make(map[string]User, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.ExternalIPs != nil { - in, out := &in.ExternalIPs, &out.ExternalIPs - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigSpec. -func (in *ConfigSpec) DeepCopy() *ConfigSpec { - if in == nil { - return nil - } - out := new(ConfigSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Resources) DeepCopyInto(out *Resources) { - *out = *in - out.Cpu = in.Cpu.DeepCopy() - out.Memory = in.Memory.DeepCopy() -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. -func (in *Resources) DeepCopy() *Resources { - if in == nil { - return nil - } - out := new(Resources) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *User) DeepCopyInto(out *User) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new User. -func (in *User) DeepCopy() *User { - if in == nil { - return nil - } - out := new(User) - in.DeepCopyInto(out) - return out -} diff --git a/api/backups/strategy/v1alpha1/velero_types.go b/api/backups/strategy/v1alpha1/velero_types.go index 2bfeabb7..9461c753 100644 --- a/api/backups/strategy/v1alpha1/velero_types.go +++ b/api/backups/strategy/v1alpha1/velero_types.go @@ -56,8 +56,6 @@ type VeleroSpec struct { // templated from a Velero backup strategy. type VeleroTemplate struct { Spec velerov1.BackupSpec `json:"spec"` - // +optional - RestoreSpec *velerov1.RestoreSpec `json:"restoreSpec,omitempty"` } type VeleroStatus struct { diff --git a/api/backups/strategy/v1alpha1/zz_generated.deepcopy.go b/api/backups/strategy/v1alpha1/zz_generated.deepcopy.go index 7f109878..c1989ac9 100644 --- a/api/backups/strategy/v1alpha1/zz_generated.deepcopy.go +++ b/api/backups/strategy/v1alpha1/zz_generated.deepcopy.go @@ -21,7 +21,6 @@ limitations under the License. package v1alpha1 import ( - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -224,11 +223,6 @@ func (in *VeleroStatus) DeepCopy() *VeleroStatus { func (in *VeleroTemplate) DeepCopyInto(out *VeleroTemplate) { *out = *in in.Spec.DeepCopyInto(&out.Spec) - if in.RestoreSpec != nil { - in, out := &in.RestoreSpec, &out.RestoreSpec - *out = new(velerov1.RestoreSpec) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VeleroTemplate. diff --git a/api/backups/v1alpha1/DESIGN.md b/api/backups/v1alpha1/DESIGN.md index 7ba06fae..bab753b2 100644 --- a/api/backups/v1alpha1/DESIGN.md +++ b/api/backups/v1alpha1/DESIGN.md @@ -196,7 +196,7 @@ type ApplicationSelector struct { // +optional APIGroup *string `json:"apiGroup,omitempty"` - // Kind is the kind of the application (e.g., VirtualMachine, MariaDB). + // Kind is the kind of the application (e.g., VirtualMachine, MySQL). Kind string `json:"kind"` } ``` diff --git a/api/backups/v1alpha1/backup_types.go b/api/backups/v1alpha1/backup_types.go index e46212f6..9371c27f 100644 --- a/api/backups/v1alpha1/backup_types.go +++ b/api/backups/v1alpha1/backup_types.go @@ -72,15 +72,6 @@ type BackupSpec struct { DriverMetadata map[string]string `json:"driverMetadata,omitempty"` } -// DataVolumeResource describes a dataVolume associated with the backed-up application. -type DataVolumeResource struct { - // DataVolumeName is the name of the dataVolume/PVC (e.g., "vm-disk-ubuntu-source"). - DataVolumeName string `json:"dataVolumeName"` - - // ApplicationName is the cozystack application name for this disk (e.g., "ubuntu-source"). - ApplicationName string `json:"applicationName"` -} - // BackupStatus represents the observed state of a Backup. type BackupStatus struct { // Phase is a simple, high-level summary of the backup's state. @@ -92,15 +83,6 @@ type BackupStatus struct { // +optional Artifact *BackupArtifact `json:"artifact,omitempty"` - // UnderlyingResources holds application-specific resource metadata discovered - // during backup (e.g., VM disks, network configuration). The payload is a - // self-typed JSON object carrying an inlined TypeMeta (kind/apiVersion) so - // the consuming controller can dispatch on the application kind. - // +optional - // +kubebuilder:pruning:PreserveUnknownFields - // +kubebuilder:validation:Type=object - UnderlyingResources *runtime.RawExtension `json:"underlyingResources,omitempty"` - // Conditions represents the latest available observations of a Backup's state. // +optional Conditions []metav1.Condition `json:"conditions,omitempty"` diff --git a/api/backups/v1alpha1/backupclass_types.go b/api/backups/v1alpha1/backupclass_types.go index 2b2dc7ff..19bcfd52 100644 --- a/api/backups/v1alpha1/backupclass_types.go +++ b/api/backups/v1alpha1/backupclass_types.go @@ -73,7 +73,7 @@ type ApplicationSelector struct { // +optional APIGroup *string `json:"apiGroup,omitempty"` - // Kind is the kind of the application (e.g., VirtualMachine, MariaDB). + // Kind is the kind of the application (e.g., VirtualMachine, MySQL). Kind string `json:"kind"` } diff --git a/api/backups/v1alpha1/backupjob_types.go b/api/backups/v1alpha1/backupjob_types.go index 111b5f1d..7b251ceb 100644 --- a/api/backups/v1alpha1/backupjob_types.go +++ b/api/backups/v1alpha1/backupjob_types.go @@ -57,7 +57,6 @@ type BackupJobSpec struct { // The BackupClass will be resolved to determine the appropriate strategy and storage // based on the ApplicationRef. // This field is immutable once the BackupJob is created. - // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="backupClassName is immutable" BackupClassName string `json:"backupClassName"` } diff --git a/api/backups/v1alpha1/backupjob_webhook.go b/api/backups/v1alpha1/backupjob_webhook.go new file mode 100644 index 00000000..064605c2 --- /dev/null +++ b/api/backups/v1alpha1/backupjob_webhook.go @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 +package v1alpha1 + +import ( + "context" + "fmt" + "strings" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// SetupWebhookWithManager registers the BackupJob webhook with the manager. +func SetupBackupJobWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&BackupJob{}). + Complete() +} + +// +kubebuilder:webhook:path=/mutate-backups-cozystack-io-v1alpha1-backupjob,mutating=true,failurePolicy=fail,sideEffects=None,groups=backups.cozystack.io,resources=backupjobs,verbs=create;update,versions=v1alpha1,name=mbackupjob.kb.io,admissionReviewVersions=v1 + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (j *BackupJob) Default() { + j.Spec.ApplicationRef = NormalizeApplicationRef(j.Spec.ApplicationRef) +} + +// +kubebuilder:webhook:path=/validate-backups-cozystack-io-v1alpha1-backupjob,mutating=false,failurePolicy=fail,sideEffects=None,groups=backups.cozystack.io,resources=backupjobs,verbs=create;update,versions=v1alpha1,name=vbackupjob.kb.io,admissionReviewVersions=v1 + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (j *BackupJob) ValidateCreate() (admission.Warnings, error) { + logger := log.FromContext(context.Background()) + logger.Info("validating BackupJob creation", "name", j.Name, "namespace", j.Namespace) + + // Validate that backupClassName is set + if strings.TrimSpace(j.Spec.BackupClassName) == "" { + return nil, fmt.Errorf("backupClassName is required and cannot be empty") + } + + return nil, nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (j *BackupJob) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + logger := log.FromContext(context.Background()) + logger.Info("validating BackupJob update", "name", j.Name, "namespace", j.Namespace) + + oldJob, ok := old.(*BackupJob) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a BackupJob but got a %T", old)) + } + + // Enforce immutability of backupClassName + if oldJob.Spec.BackupClassName != j.Spec.BackupClassName { + return nil, fmt.Errorf("backupClassName is immutable and cannot be changed from %q to %q", oldJob.Spec.BackupClassName, j.Spec.BackupClassName) + } + + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (j *BackupJob) ValidateDelete() (admission.Warnings, error) { + // No validation needed for deletion + return nil, nil +} diff --git a/api/backups/v1alpha1/backupjob_webhook_test.go b/api/backups/v1alpha1/backupjob_webhook_test.go new file mode 100644 index 00000000..d143c5be --- /dev/null +++ b/api/backups/v1alpha1/backupjob_webhook_test.go @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: Apache-2.0 +package v1alpha1 + +import ( + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestBackupJob_ValidateCreate(t *testing.T) { + tests := []struct { + name string + job *BackupJob + wantErr bool + errMsg string + }{ + { + name: "valid BackupJob with backupClassName", + job: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + }, + wantErr: false, + }, + { + name: "BackupJob with empty backupClassName should be rejected", + job: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "", + }, + }, + wantErr: true, + errMsg: "backupClassName is required and cannot be empty", + }, + { + name: "BackupJob with whitespace-only backupClassName should be rejected", + job: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: " ", + }, + }, + wantErr: true, + errMsg: "backupClassName is required and cannot be empty", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + warnings, err := tt.job.ValidateCreate() + if (err != nil) != tt.wantErr { + t.Errorf("ValidateCreate() error = %v, wantErr %v", err, tt.wantErr) + return + } + if tt.wantErr && err != nil { + if tt.errMsg != "" && err.Error() != tt.errMsg { + t.Errorf("ValidateCreate() error message = %v, want %v", err.Error(), tt.errMsg) + } + } + if warnings != nil && len(warnings) > 0 { + t.Logf("ValidateCreate() warnings = %v", warnings) + } + }) + } +} + +func TestBackupJob_ValidateUpdate(t *testing.T) { + baseJob := &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + } + + tests := []struct { + name string + old runtime.Object + new *BackupJob + wantErr bool + errMsg string + }{ + { + name: "update with same backupClassName should succeed", + old: baseJob, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", // Same as old + }, + }, + wantErr: false, + }, + { + name: "update changing backupClassName should be rejected", + old: baseJob, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "different-class", // Changed! + }, + }, + wantErr: true, + errMsg: "backupClassName is immutable and cannot be changed from \"velero\" to \"different-class\"", + }, + { + name: "update changing other fields but keeping backupClassName should succeed", + old: baseJob, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + Labels: map[string]string{ + "new-label": "value", + }, + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm2", // Changed application + }, + BackupClassName: "velero", // Same as old + }, + }, + wantErr: false, + }, + { + name: "update when old backupClassName is empty should be rejected", + old: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "", // Empty in old + }, + }, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", // Setting it for the first time + }, + }, + wantErr: true, + errMsg: "backupClassName is immutable", + }, + { + name: "update changing from non-empty to different non-empty should be rejected", + old: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "class-a", + }, + }, + new: &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "class-b", // Changed from class-a + }, + }, + wantErr: true, + errMsg: "backupClassName is immutable and cannot be changed from \"class-a\" to \"class-b\"", + }, + { + name: "update with invalid old object type should be rejected", + old: &corev1.Pod{ // Wrong type - will be cast to runtime.Object in test + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + }, + new: baseJob, + wantErr: true, + errMsg: "expected a BackupJob but got a", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + warnings, err := tt.new.ValidateUpdate(tt.old) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateUpdate() error = %v, wantErr %v", err, tt.wantErr) + if err != nil { + t.Logf("Error message: %v", err.Error()) + } + return + } + if tt.wantErr && err != nil { + if tt.errMsg != "" { + if tt.errMsg != "" && !contains(err.Error(), tt.errMsg) { + t.Errorf("ValidateUpdate() error message = %v, want contains %v", err.Error(), tt.errMsg) + } + } + } + if warnings != nil && len(warnings) > 0 { + t.Logf("ValidateUpdate() warnings = %v", warnings) + } + }) + } +} + +func TestBackupJob_ValidateDelete(t *testing.T) { + job := &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + } + + warnings, err := job.ValidateDelete() + if err != nil { + t.Errorf("ValidateDelete() should never return an error, got %v", err) + } + if warnings != nil && len(warnings) > 0 { + t.Logf("ValidateDelete() warnings = %v", warnings) + } +} + +func TestBackupJob_Default(t *testing.T) { + job := &BackupJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-job", + Namespace: "default", + }, + Spec: BackupJobSpec{ + ApplicationRef: corev1.TypedLocalObjectReference{ + Kind: "VirtualMachine", + Name: "vm1", + }, + BackupClassName: "velero", + }, + } + + // Default() should not panic and should not modify the object + originalClassName := job.Spec.BackupClassName + job.Default() + if job.Spec.BackupClassName != originalClassName { + t.Errorf("Default() should not modify backupClassName, got %v, want %v", job.Spec.BackupClassName, originalClassName) + } +} + +// Helper function to check if a string contains a substring +func contains(s, substr string) bool { + if len(substr) == 0 { + return true + } + if len(s) < len(substr) { + return false + } + for i := 0; i <= len(s)-len(substr); i++ { + if s[i:i+len(substr)] == substr { + return true + } + } + return false +} diff --git a/api/backups/v1alpha1/restorejob_types.go b/api/backups/v1alpha1/restorejob_types.go index 9817e8c1..0a64b7cf 100644 --- a/api/backups/v1alpha1/restorejob_types.go +++ b/api/backups/v1alpha1/restorejob_types.go @@ -42,12 +42,6 @@ type RestoreJobSpec struct { // application as referenced by backup.spec.applicationRef. // +optional TargetApplicationRef *corev1.TypedLocalObjectReference `json:"targetApplicationRef,omitempty"` - - // Options is a driver-specific blob of restore options, typed based on - // targetApplicationRef and the current controller implementation. - // +optional - // +kubebuilder:pruning:PreserveUnknownFields - Options *runtime.RawExtension `json:"options,omitempty"` } // RestoreJobStatus represents the observed state of a RestoreJob. @@ -77,8 +71,6 @@ type RestoreJobStatus struct { } // +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",priority=0 // RestoreJob represents a single execution of a restore from a Backup. type RestoreJob struct { diff --git a/api/backups/v1alpha1/zz_generated.deepcopy.go b/api/backups/v1alpha1/zz_generated.deepcopy.go index 61b8f839..b2e4a680 100644 --- a/api/backups/v1alpha1/zz_generated.deepcopy.go +++ b/api/backups/v1alpha1/zz_generated.deepcopy.go @@ -400,11 +400,6 @@ func (in *BackupStatus) DeepCopyInto(out *BackupStatus) { *out = new(BackupArtifact) **out = **in } - if in.UnderlyingResources != nil { - in, out := &in.UnderlyingResources, &out.UnderlyingResources - *out = new(runtime.RawExtension) - (*in).DeepCopyInto(*out) - } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]metav1.Condition, len(*in)) @@ -424,21 +419,6 @@ func (in *BackupStatus) DeepCopy() *BackupStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataVolumeResource) DeepCopyInto(out *DataVolumeResource) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataVolumeResource. -func (in *DataVolumeResource) DeepCopy() *DataVolumeResource { - if in == nil { - return nil - } - out := new(DataVolumeResource) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Plan) DeepCopyInto(out *Plan) { *out = *in @@ -620,11 +600,6 @@ func (in *RestoreJobSpec) DeepCopyInto(out *RestoreJobSpec) { *out = new(v1.TypedLocalObjectReference) (*in).DeepCopyInto(*out) } - if in.Options != nil { - in, out := &in.Options, &out.Options - *out = new(runtime.RawExtension) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestoreJobSpec. diff --git a/api/dashboard/v1alpha1/dashboard_resources.go b/api/dashboard/v1alpha1/dashboard_resources.go index afac0b05..5af3b359 100644 --- a/api/dashboard/v1alpha1/dashboard_resources.go +++ b/api/dashboard/v1alpha1/dashboard_resources.go @@ -253,25 +253,3 @@ type FactoryList struct { metav1.ListMeta `json:"metadata,omitempty"` Items []Factory `json:"items"` } - -// ----------------------------------------------------------------------------- -// CustomFormsOverrideMapping -// ----------------------------------------------------------------------------- - -// +kubebuilder:object:root=true -// +kubebuilder:resource:path=cfomappings,scope=Cluster -// +kubebuilder:subresource:status -type CFOMapping struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ArbitrarySpec `json:"spec"` - Status CommonStatus `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true -type CFOMappingList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []CFOMapping `json:"items"` -} diff --git a/api/dashboard/v1alpha1/groupversion_info.go b/api/dashboard/v1alpha1/groupversion_info.go index 659401a7..b3c38e00 100644 --- a/api/dashboard/v1alpha1/groupversion_info.go +++ b/api/dashboard/v1alpha1/groupversion_info.go @@ -69,9 +69,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { &Factory{}, &FactoryList{}, - - &CFOMapping{}, - &CFOMappingList{}, ) metav1.AddToGroupVersion(scheme, GroupVersion) return nil diff --git a/api/dashboard/v1alpha1/zz_generated.deepcopy.go b/api/dashboard/v1alpha1/zz_generated.deepcopy.go index 25d97a79..45b1d9d7 100644 --- a/api/dashboard/v1alpha1/zz_generated.deepcopy.go +++ b/api/dashboard/v1alpha1/zz_generated.deepcopy.go @@ -159,65 +159,6 @@ func (in *BreadcrumbList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CFOMapping) DeepCopyInto(out *CFOMapping) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CFOMapping. -func (in *CFOMapping) DeepCopy() *CFOMapping { - if in == nil { - return nil - } - out := new(CFOMapping) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *CFOMapping) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CFOMappingList) DeepCopyInto(out *CFOMappingList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]CFOMapping, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CFOMappingList. -func (in *CFOMappingList) DeepCopy() *CFOMappingList { - if in == nil { - return nil - } - out := new(CFOMappingList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *CFOMappingList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CommonStatus) DeepCopyInto(out *CommonStatus) { *out = *in diff --git a/api/v1alpha1/packagesource_types.go b/api/v1alpha1/packagesource_types.go index 75bf217b..c0b943e8 100644 --- a/api/v1alpha1/packagesource_types.go +++ b/api/v1alpha1/packagesource_types.go @@ -132,16 +132,6 @@ type ComponentInstall struct { // DependsOn is a list of component names that must be installed before this component // +optional DependsOn []string `json:"dependsOn,omitempty"` - - // UpgradeCRDs controls how CRDs from the chart's crds/ directory are - // handled on HelmRelease upgrades. Maps to HelmRelease.Spec.Upgrade.CRDs. - // Empty string (default) preserves the helm-controller default (Skip). - // Use "CreateReplace" for operators that evolve their CRD set between - // versions. Warning: CreateReplace overwrites CRDs and may cause data - // loss if upstream drops fields from a CRD with live objects. - // +optional - // +kubebuilder:validation:Enum=Skip;Create;CreateReplace - UpgradeCRDs string `json:"upgradeCRDs,omitempty"` } // Component defines a single Helm release component within a package source diff --git a/cmd/backup-controller/main.go b/cmd/backup-controller/main.go index 16dfc44c..bbb92790 100644 --- a/cmd/backup-controller/main.go +++ b/cmd/backup-controller/main.go @@ -37,8 +37,10 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" + strategyv1alpha1 "github.com/cozystack/cozystack/api/backups/strategy/v1alpha1" backupsv1alpha1 "github.com/cozystack/cozystack/api/backups/v1alpha1" "github.com/cozystack/cozystack/internal/backupcontroller" + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" // +kubebuilder:scaffold:imports ) @@ -51,6 +53,8 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(backupsv1alpha1.AddToScheme(scheme)) + utilruntime.Must(strategyv1alpha1.AddToScheme(scheme)) + utilruntime.Must(velerov1.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -162,6 +166,21 @@ func main() { os.Exit(1) } + if err = (&backupcontroller.BackupJobReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("backup-controller"), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "BackupJob") + os.Exit(1) + } + + // Register BackupJob webhook for validation (immutability of backupClassName) + if err = backupsv1alpha1.SetupBackupJobWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "BackupJob") + os.Exit(1) + } + // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/cmd/backupstrategy-controller/main.go b/cmd/backupstrategy-controller/main.go index 03396979..68b33902 100644 --- a/cmd/backupstrategy-controller/main.go +++ b/cmd/backupstrategy-controller/main.go @@ -37,10 +37,8 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - strategyv1alpha1 "github.com/cozystack/cozystack/api/backups/strategy/v1alpha1" backupsv1alpha1 "github.com/cozystack/cozystack/api/backups/v1alpha1" "github.com/cozystack/cozystack/internal/backupcontroller" - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" // +kubebuilder:scaffold:imports ) @@ -53,8 +51,6 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(backupsv1alpha1.AddToScheme(scheme)) - utilruntime.Must(strategyv1alpha1.AddToScheme(scheme)) - utilruntime.Must(velerov1.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -159,29 +155,10 @@ func main() { } if err = (&backupcontroller.BackupJobReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Recorder: mgr.GetEventRecorderFor("backup-controller"), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "BackupJob") - os.Exit(1) - } - - if err = (&backupcontroller.RestoreJobReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Recorder: mgr.GetEventRecorderFor("restore-controller"), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "RestoreJob") - os.Exit(1) - } - - if err = (&backupcontroller.BackupReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Recorder: mgr.GetEventRecorderFor("backup-controller"), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Backup") + setupLog.Error(err, "unable to create controller", "controller", "Job") os.Exit(1) } diff --git a/cmd/cozystack-controller/main.go b/cmd/cozystack-controller/main.go index bcaca9c9..82fc673c 100644 --- a/cmd/cozystack-controller/main.go +++ b/cmd/cozystack-controller/main.go @@ -42,7 +42,6 @@ import ( "github.com/cozystack/cozystack/internal/telemetry" helmv2 "github.com/fluxcd/helm-controller/api/v2" - cosiv1alpha1 "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage/v1alpha1" // +kubebuilder:scaffold:imports ) @@ -57,7 +56,6 @@ func init() { utilruntime.Must(cozystackiov1alpha1.AddToScheme(scheme)) utilruntime.Must(dashboard.AddToScheme(scheme)) utilruntime.Must(helmv2.AddToScheme(scheme)) - utilruntime.Must(cosiv1alpha1.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -70,6 +68,7 @@ func main() { var disableTelemetry bool var telemetryEndpoint string var telemetryInterval string + var reconcileDeployment bool var tlsOpts []func(*tls.Config) flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") @@ -87,6 +86,8 @@ func main() { "Endpoint for sending telemetry data") flag.StringVar(&telemetryInterval, "telemetry-interval", "15m", "Interval between telemetry data collection (e.g. 15m, 1h)") + flag.BoolVar(&reconcileDeployment, "reconcile-deployment", false, + "If set, the Cozystack API server is assumed to run as a Deployment, else as a DaemonSet.") opts := zap.Options{ Development: false, } @@ -195,9 +196,14 @@ func main() { os.Exit(1) } + cozyAPIKind := "DaemonSet" + if reconcileDeployment { + cozyAPIKind = "Deployment" + } if err = (&controller.ApplicationDefinitionReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + CozystackAPIKind: cozyAPIKind, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "ApplicationDefinitionReconciler") os.Exit(1) diff --git a/cmd/cozystack-operator/main.go b/cmd/cozystack-operator/main.go index e215b779..188ce160 100644 --- a/cmd/cozystack-operator/main.go +++ b/cmd/cozystack-operator/main.go @@ -50,7 +50,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "github.com/cozystack/cozystack/internal/cozyvaluesreplicator" - "github.com/cozystack/cozystack/internal/crdinstall" "github.com/cozystack/cozystack/internal/fluxinstall" "github.com/cozystack/cozystack/internal/operator" "github.com/cozystack/cozystack/internal/telemetry" @@ -78,7 +77,6 @@ func main() { var probeAddr string var secureMetrics bool var enableHTTP2 bool - var installCRDs bool var installFlux bool var disableTelemetry bool var telemetryEndpoint string @@ -99,7 +97,6 @@ func main() { "If set the metrics endpoint is served securely") flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") - flag.BoolVar(&installCRDs, "install-crds", false, "Install Cozystack CRDs before starting reconcile loop") flag.BoolVar(&installFlux, "install-flux", false, "Install Flux components before starting reconcile loop") flag.BoolVar(&disableTelemetry, "disable-telemetry", false, "Disable telemetry collection") @@ -108,7 +105,7 @@ func main() { flag.StringVar(&telemetryInterval, "telemetry-interval", "15m", "Interval between telemetry data collection (e.g. 15m, 1h)") flag.StringVar(&platformSourceURL, "platform-source-url", "", "Platform source URL (oci:// or https://). If specified, generates OCIRepository or GitRepository resource.") - flag.StringVar(&platformSourceName, "platform-source-name", "cozystack-platform", "Name for the generated platform source resource and PackageSource") + flag.StringVar(&platformSourceName, "platform-source-name", "cozystack-packages", "Name for the generated platform source resource (default: cozystack-packages)") flag.StringVar(&platformSourceRef, "platform-source-ref", "", "Reference specification as key=value pairs (e.g., 'branch=main' or 'digest=sha256:...,tag=v1.0'). For OCI: digest, semver, semverFilter, tag. For Git: branch, tag, semver, name, commit.") flag.StringVar(&cozyValuesSecretName, "cozy-values-secret-name", "cozystack-values", "The name of the secret containing cluster-wide configuration values.") flag.StringVar(&cozyValuesSecretNamespace, "cozy-values-secret-namespace", "cozy-system", "The namespace of the secret containing cluster-wide configuration values.") @@ -137,7 +134,8 @@ func main() { os.Exit(1) } - // Initialize the controller manager + // Start the controller manager + setupLog.Info("Starting controller manager") mgr, err := ctrl.NewManager(config, ctrl.Options{ Scheme: scheme, Cache: cache.Options{ @@ -179,26 +177,10 @@ func main() { os.Exit(1) } - // Set up signal handler early so install phases respect SIGTERM - mgrCtx := ctrl.SetupSignalHandler() - - // Install Cozystack CRDs before starting reconcile loop - if installCRDs { - setupLog.Info("Installing Cozystack CRDs before starting reconcile loop") - installCtx, installCancel := context.WithTimeout(mgrCtx, 2*time.Minute) - defer installCancel() - - if err := crdinstall.Install(installCtx, directClient, crdinstall.WriteEmbeddedManifests); err != nil { - setupLog.Error(err, "failed to install CRDs") - os.Exit(1) - } - setupLog.Info("CRD installation completed successfully") - } - // Install Flux before starting reconcile loop if installFlux { setupLog.Info("Installing Flux components before starting reconcile loop") - installCtx, installCancel := context.WithTimeout(mgrCtx, 5*time.Minute) + installCtx, installCancel := context.WithTimeout(context.Background(), 5*time.Minute) defer installCancel() // Use direct client for pre-start operations (cache is not ready yet) @@ -212,7 +194,7 @@ func main() { // Generate and install platform source resource if specified if platformSourceURL != "" { setupLog.Info("Generating platform source resource", "url", platformSourceURL, "name", platformSourceName, "ref", platformSourceRef) - installCtx, installCancel := context.WithTimeout(mgrCtx, 2*time.Minute) + installCtx, installCancel := context.WithTimeout(context.Background(), 2*time.Minute) defer installCancel() // Use direct client for pre-start operations (cache is not ready yet) @@ -224,29 +206,6 @@ func main() { } } - // Create platform PackageSource when CRDs are managed by the operator and - // a platform source URL is configured. Without a URL there is no Flux source - // resource to reference, so creating a PackageSource would leave a dangling SourceRef. - if installCRDs && platformSourceURL != "" { - sourceRefKind := "OCIRepository" - sourceType, _, err := parsePlatformSourceURL(platformSourceURL) - if err != nil { - setupLog.Error(err, "failed to parse platform source URL for PackageSource") - os.Exit(1) - } - if sourceType == "git" { - sourceRefKind = "GitRepository" - } - setupLog.Info("Creating platform PackageSource", "platformSourceName", platformSourceName) - psCtx, psCancel := context.WithTimeout(mgrCtx, 2*time.Minute) - defer psCancel() - if err := installPlatformPackageSource(psCtx, directClient, platformSourceName, sourceRefKind); err != nil { - setupLog.Error(err, "failed to create platform PackageSource") - os.Exit(1) - } - setupLog.Info("Platform PackageSource creation completed successfully") - } - // Setup PackageSource reconciler if err := (&operator.PackageSourceReconciler{ Client: mgr.GetClient(), @@ -317,6 +276,7 @@ func main() { } setupLog.Info("Starting controller manager") + mgrCtx := ctrl.SetupSignalHandler() if err := mgr.Start(mgrCtx); err != nil { setupLog.Error(err, "problem running manager") os.Exit(1) @@ -575,79 +535,3 @@ func generateGitRepository(name, repoURL string, refMap map[string]string) (*sou return obj, nil } - -// installPlatformPackageSource creates the platform PackageSource resource -// that references the Flux source resource (OCIRepository or GitRepository). -// -// The variant list is intentionally hardcoded here. These are platform-defined -// deployment profiles (not user-extensible), matching what was previously in -// the Helm template. Changes require a new operator build and release. -func installPlatformPackageSource(ctx context.Context, k8sClient client.Client, platformSourceName, sourceRefKind string) error { - logger := log.FromContext(ctx) - - packageSourceName := "cozystack." + platformSourceName - - ps := &cozyv1alpha1.PackageSource{ - TypeMeta: metav1.TypeMeta{ - APIVersion: cozyv1alpha1.GroupVersion.String(), - Kind: "PackageSource", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: packageSourceName, - Annotations: map[string]string{ - "operator.cozystack.io/skip-cozystack-values": "true", - }, - }, - Spec: cozyv1alpha1.PackageSourceSpec{ - SourceRef: &cozyv1alpha1.PackageSourceRef{ - Kind: sourceRefKind, - Name: platformSourceName, - Namespace: "cozy-system", - Path: "/", - }, - }, - } - - variantData := []struct { - name string - valuesFiles []string - }{ - {"default", []string{"values.yaml"}}, - {"isp-full", []string{"values.yaml", "values-isp-full.yaml"}}, - {"isp-hosted", []string{"values.yaml", "values-isp-hosted.yaml"}}, - {"isp-full-generic", []string{"values.yaml", "values-isp-full-generic.yaml"}}, - } - - variants := make([]cozyv1alpha1.Variant, len(variantData)) - for i, v := range variantData { - variants[i] = cozyv1alpha1.Variant{ - Name: v.name, - Components: []cozyv1alpha1.Component{ - { - Name: "platform", - Path: "core/platform", - Install: &cozyv1alpha1.ComponentInstall{ - Namespace: "cozy-system", - ReleaseName: "cozystack-platform", - }, - ValuesFiles: v.valuesFiles, - }, - }, - } - } - ps.Spec.Variants = variants - - logger.Info("Applying platform PackageSource", "name", packageSourceName) - - patchOptions := &client.PatchOptions{ - FieldManager: "cozystack-operator", - Force: func() *bool { b := true; return &b }(), - } - - if err := k8sClient.Patch(ctx, ps, client.Apply, patchOptions); err != nil { - return fmt.Errorf("failed to apply PackageSource %s: %w", packageSourceName, err) - } - - logger.Info("Applied platform PackageSource", "name", packageSourceName) - return nil -} diff --git a/cmd/cozystack-operator/main_test.go b/cmd/cozystack-operator/main_test.go deleted file mode 100644 index a69bc9b5..00000000 --- a/cmd/cozystack-operator/main_test.go +++ /dev/null @@ -1,574 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "context" - "testing" - - cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" -) - -func newTestScheme() *runtime.Scheme { - s := runtime.NewScheme() - _ = cozyv1alpha1.AddToScheme(s) - return s -} - -func TestInstallPlatformPackageSource_Creates(t *testing.T) { - s := newTestScheme() - k8sClient := fake.NewClientBuilder().WithScheme(s).Build() - - err := installPlatformPackageSource(context.Background(), k8sClient, "cozystack-platform", "OCIRepository") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - ps := &cozyv1alpha1.PackageSource{} - if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: "cozystack.cozystack-platform"}, ps); err != nil { - t.Fatalf("PackageSource not found: %v", err) - } - - // Verify name - if ps.Name != "cozystack.cozystack-platform" { - t.Errorf("expected name %q, got %q", "cozystack.cozystack-platform", ps.Name) - } - - // Verify annotation - if ps.Annotations["operator.cozystack.io/skip-cozystack-values"] != "true" { - t.Errorf("expected skip-cozystack-values annotation to be 'true', got %q", ps.Annotations["operator.cozystack.io/skip-cozystack-values"]) - } - - // Verify sourceRef - if ps.Spec.SourceRef == nil { - t.Fatal("expected SourceRef to be set") - } - if ps.Spec.SourceRef.Kind != "OCIRepository" { - t.Errorf("expected sourceRef.kind %q, got %q", "OCIRepository", ps.Spec.SourceRef.Kind) - } - if ps.Spec.SourceRef.Name != "cozystack-platform" { - t.Errorf("expected sourceRef.name %q, got %q", "cozystack-platform", ps.Spec.SourceRef.Name) - } - if ps.Spec.SourceRef.Namespace != "cozy-system" { - t.Errorf("expected sourceRef.namespace %q, got %q", "cozy-system", ps.Spec.SourceRef.Namespace) - } - if ps.Spec.SourceRef.Path != "/" { - t.Errorf("expected sourceRef.path %q, got %q", "/", ps.Spec.SourceRef.Path) - } - - // Verify variants - expectedVariants := []string{"default", "isp-full", "isp-hosted", "isp-full-generic"} - if len(ps.Spec.Variants) != len(expectedVariants) { - t.Fatalf("expected %d variants, got %d", len(expectedVariants), len(ps.Spec.Variants)) - } - for i, name := range expectedVariants { - if ps.Spec.Variants[i].Name != name { - t.Errorf("expected variant[%d].name %q, got %q", i, name, ps.Spec.Variants[i].Name) - } - if len(ps.Spec.Variants[i].Components) != 1 { - t.Errorf("expected variant[%d] to have 1 component, got %d", i, len(ps.Spec.Variants[i].Components)) - } - } -} - -func TestInstallPlatformPackageSource_Updates(t *testing.T) { - s := newTestScheme() - - existing := &cozyv1alpha1.PackageSource{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cozystack.cozystack-platform", - ResourceVersion: "1", - Labels: map[string]string{ - "custom-label": "should-be-preserved", - }, - }, - Spec: cozyv1alpha1.PackageSourceSpec{ - SourceRef: &cozyv1alpha1.PackageSourceRef{ - Kind: "OCIRepository", - Name: "old-name", - Namespace: "cozy-system", - }, - }, - } - - k8sClient := fake.NewClientBuilder().WithScheme(s).WithObjects(existing).Build() - - err := installPlatformPackageSource(context.Background(), k8sClient, "cozystack-platform", "OCIRepository") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - ps := &cozyv1alpha1.PackageSource{} - if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: "cozystack.cozystack-platform"}, ps); err != nil { - t.Fatalf("PackageSource not found: %v", err) - } - - // Verify sourceRef was updated - if ps.Spec.SourceRef.Name != "cozystack-platform" { - t.Errorf("expected updated sourceRef.name %q, got %q", "cozystack-platform", ps.Spec.SourceRef.Name) - } - - // Verify all 4 variants are present after update - if len(ps.Spec.Variants) != 4 { - t.Errorf("expected 4 variants after update, got %d", len(ps.Spec.Variants)) - } - - // Verify that labels set by other controllers are preserved (SSA does not overwrite unmanaged fields) - if ps.Labels["custom-label"] != "should-be-preserved" { - t.Errorf("expected custom-label to be preserved, got %q", ps.Labels["custom-label"]) - } -} - -func TestParsePlatformSourceURL(t *testing.T) { - tests := []struct { - name string - url string - wantType string - wantURL string - wantErr bool - }{ - { - name: "OCI URL", - url: "oci://ghcr.io/cozystack/cozystack/cozystack-packages", - wantType: "oci", - wantURL: "oci://ghcr.io/cozystack/cozystack/cozystack-packages", - }, - { - name: "HTTPS URL", - url: "https://github.com/cozystack/cozystack", - wantType: "git", - wantURL: "https://github.com/cozystack/cozystack", - }, - { - name: "SSH URL", - url: "ssh://git@github.com/cozystack/cozystack", - wantType: "git", - wantURL: "ssh://git@github.com/cozystack/cozystack", - }, - { - name: "empty URL", - url: "", - wantErr: true, - }, - { - name: "unsupported scheme", - url: "ftp://example.com/repo", - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - sourceType, repoURL, err := parsePlatformSourceURL(tt.url) - if tt.wantErr { - if err == nil { - t.Fatalf("expected error for URL %q, got nil", tt.url) - } - return - } - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if sourceType != tt.wantType { - t.Errorf("expected type %q, got %q", tt.wantType, sourceType) - } - if repoURL != tt.wantURL { - t.Errorf("expected URL %q, got %q", tt.wantURL, repoURL) - } - }) - } -} - -func TestInstallPlatformPackageSource_VariantValuesFiles(t *testing.T) { - s := newTestScheme() - k8sClient := fake.NewClientBuilder().WithScheme(s).Build() - - err := installPlatformPackageSource(context.Background(), k8sClient, "cozystack-platform", "OCIRepository") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - ps := &cozyv1alpha1.PackageSource{} - if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: "cozystack.cozystack-platform"}, ps); err != nil { - t.Fatalf("PackageSource not found: %v", err) - } - - expectedValuesFiles := map[string][]string{ - "default": {"values.yaml"}, - "isp-full": {"values.yaml", "values-isp-full.yaml"}, - "isp-hosted": {"values.yaml", "values-isp-hosted.yaml"}, - "isp-full-generic": {"values.yaml", "values-isp-full-generic.yaml"}, - } - - for _, v := range ps.Spec.Variants { - expected, ok := expectedValuesFiles[v.Name] - if !ok { - t.Errorf("unexpected variant %q", v.Name) - continue - } - - if len(v.Components) != 1 { - t.Errorf("variant %q: expected 1 component, got %d", v.Name, len(v.Components)) - continue - } - - comp := v.Components[0] - if comp.Name != "platform" { - t.Errorf("variant %q: expected component name %q, got %q", v.Name, "platform", comp.Name) - } - if comp.Path != "core/platform" { - t.Errorf("variant %q: expected component path %q, got %q", v.Name, "core/platform", comp.Path) - } - if comp.Install == nil { - t.Errorf("variant %q: expected Install to be set", v.Name) - } else { - if comp.Install.Namespace != "cozy-system" { - t.Errorf("variant %q: expected install namespace %q, got %q", v.Name, "cozy-system", comp.Install.Namespace) - } - if comp.Install.ReleaseName != "cozystack-platform" { - t.Errorf("variant %q: expected install releaseName %q, got %q", v.Name, "cozystack-platform", comp.Install.ReleaseName) - } - } - - if len(comp.ValuesFiles) != len(expected) { - t.Errorf("variant %q: expected %d valuesFiles, got %d", v.Name, len(expected), len(comp.ValuesFiles)) - continue - } - for i, f := range expected { - if comp.ValuesFiles[i] != f { - t.Errorf("variant %q: expected valuesFiles[%d] %q, got %q", v.Name, i, f, comp.ValuesFiles[i]) - } - } - } -} - -func TestInstallPlatformPackageSource_CustomName(t *testing.T) { - s := newTestScheme() - k8sClient := fake.NewClientBuilder().WithScheme(s).Build() - - err := installPlatformPackageSource(context.Background(), k8sClient, "custom-source", "OCIRepository") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - ps := &cozyv1alpha1.PackageSource{} - if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: "cozystack.custom-source"}, ps); err != nil { - t.Fatalf("PackageSource not found: %v", err) - } - - if ps.Name != "cozystack.custom-source" { - t.Errorf("expected name %q, got %q", "cozystack.custom-source", ps.Name) - } - if ps.Spec.SourceRef.Name != "custom-source" { - t.Errorf("expected sourceRef.name %q, got %q", "custom-source", ps.Spec.SourceRef.Name) - } -} - -func TestInstallPlatformPackageSource_GitRepository(t *testing.T) { - s := newTestScheme() - k8sClient := fake.NewClientBuilder().WithScheme(s).Build() - - err := installPlatformPackageSource(context.Background(), k8sClient, "my-source", "GitRepository") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - ps := &cozyv1alpha1.PackageSource{} - if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: "cozystack.my-source"}, ps); err != nil { - t.Fatalf("PackageSource not found: %v", err) - } - - if ps.Spec.SourceRef.Kind != "GitRepository" { - t.Errorf("expected sourceRef.kind %q, got %q", "GitRepository", ps.Spec.SourceRef.Kind) - } - if ps.Spec.SourceRef.Name != "my-source" { - t.Errorf("expected sourceRef.name %q, got %q", "my-source", ps.Spec.SourceRef.Name) - } -} - -func TestParseRefSpec(t *testing.T) { - tests := []struct { - name string - input string - want map[string]string - wantErr bool - }{ - { - name: "empty string", - input: "", - want: map[string]string{}, - }, - { - name: "single key-value", - input: "tag=v1.0", - want: map[string]string{"tag": "v1.0"}, - }, - { - name: "multiple key-values", - input: "digest=sha256:abc123,tag=v1.0", - want: map[string]string{"digest": "sha256:abc123", "tag": "v1.0"}, - }, - { - name: "whitespace around pairs", - input: " tag=v1.0 , branch=main ", - want: map[string]string{"tag": "v1.0", "branch": "main"}, - }, - { - name: "equals sign in value", - input: "digest=sha256:abc=123", - want: map[string]string{"digest": "sha256:abc=123"}, - }, - { - name: "missing equals sign", - input: "tag", - wantErr: true, - }, - { - name: "empty key", - input: "=value", - wantErr: true, - }, - { - name: "empty value", - input: "tag=", - wantErr: true, - }, - { - name: "trailing comma", - input: "tag=v1.0,", - want: map[string]string{"tag": "v1.0"}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := parseRefSpec(tt.input) - if tt.wantErr { - if err == nil { - t.Fatalf("expected error for input %q, got nil", tt.input) - } - return - } - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if len(got) != len(tt.want) { - t.Fatalf("expected %d entries, got %d: %v", len(tt.want), len(got), got) - } - for k, v := range tt.want { - if got[k] != v { - t.Errorf("expected %q=%q, got %q=%q", k, v, k, got[k]) - } - } - }) - } -} - -func TestValidateOCIRef(t *testing.T) { - tests := []struct { - name string - refMap map[string]string - wantErr bool - }{ - { - name: "valid tag", - refMap: map[string]string{"tag": "v1.0"}, - }, - { - name: "valid digest", - refMap: map[string]string{"digest": "sha256:abc123def456"}, - }, - { - name: "valid semver", - refMap: map[string]string{"semver": ">=1.0.0"}, - }, - { - name: "multiple valid keys", - refMap: map[string]string{"tag": "v1.0", "digest": "sha256:abc"}, - }, - { - name: "empty map", - refMap: map[string]string{}, - }, - { - name: "invalid key", - refMap: map[string]string{"branch": "main"}, - wantErr: true, - }, - { - name: "invalid digest format", - refMap: map[string]string{"digest": "md5:abc"}, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := validateOCIRef(tt.refMap) - if tt.wantErr && err == nil { - t.Fatal("expected error, got nil") - } - if !tt.wantErr && err != nil { - t.Fatalf("unexpected error: %v", err) - } - }) - } -} - -func TestValidateGitRef(t *testing.T) { - tests := []struct { - name string - refMap map[string]string - wantErr bool - }{ - { - name: "valid branch", - refMap: map[string]string{"branch": "main"}, - }, - { - name: "valid commit", - refMap: map[string]string{"commit": "abc1234"}, - }, - { - name: "valid tag and branch", - refMap: map[string]string{"tag": "v1.0", "branch": "release"}, - }, - { - name: "empty map", - refMap: map[string]string{}, - }, - { - name: "invalid key", - refMap: map[string]string{"digest": "sha256:abc"}, - wantErr: true, - }, - { - name: "commit too short", - refMap: map[string]string{"commit": "abc"}, - wantErr: true, - }, - { - name: "commit not hex", - refMap: map[string]string{"commit": "zzzzzzz"}, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := validateGitRef(tt.refMap) - if tt.wantErr && err == nil { - t.Fatal("expected error, got nil") - } - if !tt.wantErr && err != nil { - t.Fatalf("unexpected error: %v", err) - } - }) - } -} - -func TestGenerateOCIRepository(t *testing.T) { - refMap := map[string]string{"tag": "v1.0", "digest": "sha256:abc123"} - obj, err := generateOCIRepository("my-repo", "oci://registry.example.com/repo", refMap) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if obj.Name != "my-repo" { - t.Errorf("expected name %q, got %q", "my-repo", obj.Name) - } - if obj.Namespace != "cozy-system" { - t.Errorf("expected namespace %q, got %q", "cozy-system", obj.Namespace) - } - if obj.Spec.URL != "oci://registry.example.com/repo" { - t.Errorf("expected URL %q, got %q", "oci://registry.example.com/repo", obj.Spec.URL) - } - if obj.Spec.Reference == nil { - t.Fatal("expected Reference to be set") - } - if obj.Spec.Reference.Tag != "v1.0" { - t.Errorf("expected tag %q, got %q", "v1.0", obj.Spec.Reference.Tag) - } - if obj.Spec.Reference.Digest != "sha256:abc123" { - t.Errorf("expected digest %q, got %q", "sha256:abc123", obj.Spec.Reference.Digest) - } -} - -func TestGenerateOCIRepository_NoRef(t *testing.T) { - obj, err := generateOCIRepository("my-repo", "oci://registry.example.com/repo", map[string]string{}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if obj.Spec.Reference != nil { - t.Error("expected Reference to be nil for empty refMap") - } -} - -func TestGenerateOCIRepository_InvalidRef(t *testing.T) { - _, err := generateOCIRepository("my-repo", "oci://registry.example.com/repo", map[string]string{"branch": "main"}) - if err == nil { - t.Fatal("expected error for invalid OCI ref key, got nil") - } -} - -func TestGenerateGitRepository(t *testing.T) { - refMap := map[string]string{"branch": "main", "commit": "abc1234def5678"} - obj, err := generateGitRepository("my-repo", "https://github.com/user/repo", refMap) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if obj.Name != "my-repo" { - t.Errorf("expected name %q, got %q", "my-repo", obj.Name) - } - if obj.Namespace != "cozy-system" { - t.Errorf("expected namespace %q, got %q", "cozy-system", obj.Namespace) - } - if obj.Spec.URL != "https://github.com/user/repo" { - t.Errorf("expected URL %q, got %q", "https://github.com/user/repo", obj.Spec.URL) - } - if obj.Spec.Reference == nil { - t.Fatal("expected Reference to be set") - } - if obj.Spec.Reference.Branch != "main" { - t.Errorf("expected branch %q, got %q", "main", obj.Spec.Reference.Branch) - } - if obj.Spec.Reference.Commit != "abc1234def5678" { - t.Errorf("expected commit %q, got %q", "abc1234def5678", obj.Spec.Reference.Commit) - } -} - -func TestGenerateGitRepository_NoRef(t *testing.T) { - obj, err := generateGitRepository("my-repo", "https://github.com/user/repo", map[string]string{}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if obj.Spec.Reference != nil { - t.Error("expected Reference to be nil for empty refMap") - } -} - -func TestGenerateGitRepository_InvalidRef(t *testing.T) { - _, err := generateGitRepository("my-repo", "https://github.com/user/repo", map[string]string{"digest": "sha256:abc"}) - if err == nil { - t.Fatal("expected error for invalid Git ref key, got nil") - } -} diff --git a/cmd/kubeovn-plunger/main.go b/cmd/kubeovn-plunger/main.go index 611d030b..210405ce 100644 --- a/cmd/kubeovn-plunger/main.go +++ b/cmd/kubeovn-plunger/main.go @@ -29,7 +29,6 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/metrics" @@ -132,11 +131,6 @@ func main() { HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "29a0338b.cozystack.io", - Cache: cache.Options{ - DefaultNamespaces: map[string]cache.Config{ - kubeOVNNamespace: {}, - }, - }, // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily // when the Manager ends. This requires the binary to immediately end when the // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly diff --git a/dashboards/gpu/gpu-efficiency.json b/dashboards/gpu/gpu-efficiency.json deleted file mode 100644 index 28a24568..00000000 --- a/dashboards/gpu/gpu-efficiency.json +++ /dev/null @@ -1,819 +0,0 @@ -{ - "uid": "gpu-efficiency", - "title": "GPU Efficiency Score", - "description": "Tensor saturation, util/watt and throttling — reveals inefficient GPU workloads", - "tags": [ - "gpu", - "efficiency", - "finops" - ], - "timezone": "browser", - "editable": true, - "graphTooltip": 1, - "time": { - "from": "now-1h", - "to": "now" - }, - "fiscalYearStartMonth": 0, - "schemaVersion": 42, - "panels": [ - { - "type": "row", - "collapsed": false, - "title": "Overall efficiency metrics", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 1, - "panels": [] - }, - { - "type": "stat", - "id": 2, - "targets": [ - { - "expr": "avg(gpu:tensor_saturation:avg5m) * 100", - "refId": "A" - } - ], - "title": "Avg Tensor Saturation", - "description": "Mean tensor core saturation across all GPUs. \u003c10% means GPUs are used inefficiently (workloads could move to CPU or optimize their code). Cluster-wide — DCGM metrics cannot be attributed to workload namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 8, - "x": 0, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "red" - }, - { - "value": 10, - "color": "orange" - }, - { - "value": 30, - "color": "yellow" - }, - { - "value": 60, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 3, - "targets": [ - { - "expr": "avg(gpu:util_per_watt:avg5m)", - "refId": "A" - } - ], - "title": "Avg Utilization per Watt", - "description": "NVML utilization % per watt across all GPUs. Higher value = more efficient workload. Cluster-wide — DCGM metrics cannot be attributed to workload namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 8, - "x": 8, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "none", - "decimals": 3, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "red" - }, - { - "value": 0.5, - "color": "yellow" - }, - { - "value": 1, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 4, - "targets": [ - { - "expr": "avg(gpu:power_throttle_fraction:rate5m)", - "refId": "A" - } - ], - "title": "Avg Power Throttling", - "description": "Fraction of time GPUs hit the TDP cap and lose performance. \u003e5% means tenants underutilize billed FLOPS. Cluster-wide — rule aggregates by (Hostname, gpu, UUID) and drops namespace label.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 8, - "x": 16, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "decimals": 2, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 0.05, - "color": "yellow" - }, - { - "value": 0.2, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "NVML vs Tensor (mismatch detector)", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 10, - "panels": [] - }, - { - "type": "timeseries", - "id": 11, - "targets": [ - { - "expr": "DCGM_FI_DEV_GPU_UTIL", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "NVML GPU Utilization", - "description": "Classic utilization metric. Shows activity of any engine (SM, copy, encoder). Cluster-wide — DCGM namespace is the exporter's own namespace, not the workload namespace.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 7 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 12, - "targets": [ - { - "expr": "DCGM_FI_PROF_PIPE_TENSOR_ACTIVE * 100", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "Tensor Pipe Active", - "description": "Real tensor core load (HMMA). For AI/LLM inference it should be ≥20%, otherwise the workload is unoptimized. Cluster-wide — DCGM namespace is the exporter's own namespace, not the workload namespace.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 7 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Per-GPU ranking", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 15 - }, - "id": 20, - "panels": [] - }, - { - "type": "table", - "id": 21, - "targets": [ - { - "expr": "topk(20, gpu:tensor_saturation:avg5m * 100)", - "instant": true, - "range": false, - "format": "table", - "refId": "A" - } - ], - "title": "Tensor Saturation per GPU (5m avg)", - "description": "Which GPUs are exercising tensor cores and which are not. Sorted descending. Grouped by Hostname/gpu/UUID — DCGM metrics cannot be attributed to workload namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 16 - }, - "repeatDirection": "h", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "DCGM_FI_DRIVER_VERSION": true, - "Time": true, - "__name__": true, - "cluster": true, - "container": true, - "device": true, - "endpoint": true, - "gpu_driver_version": true, - "instance": true, - "job": true, - "modelName": true, - "namespace": true, - "pci_bus_id": true, - "pod": true, - "prometheus": true, - "service": true, - "tenant": true, - "tier": true, - "uid": true, - "unit": true - }, - "indexByName": { - "Hostname": 0, - "UUID": 2, - "Value": 3, - "gpu": 1 - }, - "renameByName": { - "Hostname": "Node", - "UUID": "UUID", - "Value": "Saturation", - "gpu": "GPU" - } - } - } - ], - "options": { - "frameIndex": 0, - "showHeader": true, - "showTypeIcons": false, - "sortBy": [ - { - "displayName": "Saturation", - "desc": true - } - ], - "footer": { - "show": false, - "reducer": [] - }, - "cellHeight": "sm" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Saturation" - }, - "properties": [ - { - "id": "unit", - "value": "percent" - }, - { - "id": "min", - "value": 0 - }, - { - "id": "max", - "value": 100 - }, - { - "id": "custom.cellOptions", - "value": { - "mode": "gradient", - "type": "gauge" - } - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "red" - }, - { - "color": "orange", - "value": 10 - }, - { - "color": "yellow", - "value": 30 - }, - { - "color": "green", - "value": 60 - } - ] - } - } - ] - } - ] - } - }, - { - "type": "table", - "id": 22, - "targets": [ - { - "expr": "topk(20, gpu:util_per_watt:avg5m)", - "instant": true, - "range": false, - "format": "table", - "refId": "A" - } - ], - "title": "Utilization / Watt per GPU (5m avg)", - "description": "How efficiently each GPU spends watts. Low value = poor optimization. Grouped by Hostname/gpu/UUID — DCGM metrics cannot be attributed to workload namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 16 - }, - "repeatDirection": "h", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "DCGM_FI_DRIVER_VERSION": true, - "Time": true, - "__name__": true, - "cluster": true, - "container": true, - "device": true, - "endpoint": true, - "gpu_driver_version": true, - "instance": true, - "job": true, - "modelName": true, - "namespace": true, - "pci_bus_id": true, - "pod": true, - "prometheus": true, - "service": true, - "tenant": true, - "tier": true, - "uid": true, - "unit": true - }, - "indexByName": { - "Hostname": 0, - "UUID": 2, - "Value": 3, - "gpu": 1 - }, - "renameByName": { - "Hostname": "Node", - "UUID": "UUID", - "Value": "Util/Watt", - "gpu": "GPU" - } - } - } - ], - "options": { - "frameIndex": 0, - "showHeader": true, - "showTypeIcons": false, - "sortBy": [ - { - "displayName": "Util/Watt", - "desc": true - } - ], - "footer": { - "show": false, - "reducer": [] - }, - "cellHeight": "sm" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Util/Watt" - }, - "properties": [ - { - "id": "unit", - "value": "none" - }, - { - "id": "decimals", - "value": 3 - }, - { - "id": "min", - "value": 0 - }, - { - "id": "max", - "value": 1.5 - }, - { - "id": "custom.cellOptions", - "value": { - "mode": "gradient", - "type": "gauge" - } - }, - { - "id": "thresholds", - "value": { - "mode": "absolute", - "steps": [ - { - "color": "red" - }, - { - "color": "yellow", - "value": 0.5 - }, - { - "color": "green", - "value": 1 - } - ] - } - } - ] - } - ] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Throttling", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 24 - }, - "id": 30, - "panels": [] - }, - { - "type": "timeseries", - "id": 31, - "targets": [ - { - "expr": "gpu:power_throttle_fraction:rate5m", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "Power throttle fraction per GPU", - "description": "Fraction of time the GPU was power-throttled. 1.0 = always throttled. Cluster-wide — rule aggregates by (Hostname, gpu, UUID) and drops namespace label.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 25 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "min": 0, - "max": 1, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 0.05, - "color": "yellow" - }, - { - "value": 0.2, - "color": "red" - } - ] - }, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 25, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 32, - "targets": [ - { - "expr": "gpu:thermal_throttle_fraction:rate5m", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "Thermal throttle fraction per GPU", - "description": "Fraction of time the GPU was thermal-throttled. Cluster-wide — rule aggregates by (Hostname, gpu, UUID) and drops namespace label.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 25 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "min": 0, - "max": 1, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 0.05, - "color": "yellow" - }, - { - "value": 0.2, - "color": "red" - } - ] - }, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 25, - "showPoints": "never" - } - }, - "overrides": [] - } - } - ], - "templating": { - "list": [ - { - "type": "datasource", - "name": "ds_prometheus", - "label": "Prometheus", - "skipUrlSync": false, - "query": "prometheus", - "current": { - "selected": false, - "text": "default", - "value": "default" - }, - "multi": false, - "allowCustomValue": true, - "includeAll": false, - "regex": "", - "auto": false, - "auto_min": "10s", - "auto_count": 30 - } - ] - }, - "annotations": {} -} diff --git a/dashboards/gpu/gpu-fleet.json b/dashboards/gpu/gpu-fleet.json deleted file mode 100644 index 60c12bfb..00000000 --- a/dashboards/gpu/gpu-fleet.json +++ /dev/null @@ -1,1157 +0,0 @@ -{ - "uid": "gpu-fleet", - "title": "GPU Fleet Overview", - "description": "Cluster-wide GPU inventory, capacity, utilization and health — admin view across the whole fleet.", - "tags": [ - "gpu", - "fleet", - "admin" - ], - "timezone": "browser", - "editable": true, - "graphTooltip": 1, - "time": { - "from": "now-6h", - "to": "now" - }, - "fiscalYearStartMonth": 0, - "schemaVersion": 42, - "panels": [ - { - "type": "row", - "collapsed": false, - "title": "Cluster snapshot", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 1, - "panels": [] - }, - { - "type": "stat", - "id": 2, - "targets": [ - { - "expr": "cluster:gpu_count:total", - "refId": "A" - } - ], - "title": "Total GPUs", - "description": "Physical GPUs discovered by DCGM across all nodes.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 0, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 3, - "targets": [ - { - "expr": "cluster:gpu_count:allocated", - "refId": "A" - } - ], - "title": "Allocated", - "description": "Sum of kube GPU requests across all pods. Billable view — includes Pending pods.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 4, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - }, - { - "value": 1, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 4, - "targets": [ - { - "expr": "cluster:gpu_count:free", - "refId": "A" - } - ], - "title": "Free", - "description": "Unallocated capacity available for new tenants.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 8, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "red" - }, - { - "value": 1, - "color": "yellow" - }, - { - "value": 2, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 5, - "targets": [ - { - "expr": "count(count by (Hostname) (DCGM_FI_DEV_GPU_UTIL))", - "refId": "A" - } - ], - "title": "Nodes with GPU", - "description": "Nodes reporting at least one GPU to DCGM. Counted via DCGM_FI_DEV_GPU_UTIL because kube-state-metrics does not expose node labels by default.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 12, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 6, - "targets": [ - { - "expr": "cluster:gpu_util:avg", - "refId": "A" - } - ], - "title": "Average utilization", - "description": "Legacy NVML utilization across all tenant GPUs.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 16, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - }, - { - "value": 30, - "color": "green" - }, - { - "value": 80, - "color": "orange" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 7, - "targets": [ - { - "expr": "cluster:gpu_power_watts:sum", - "refId": "A" - } - ], - "title": "Total power", - "description": "Live power draw summed across the fleet.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 20, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "watt", - "decimals": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Per-node GPU activity", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 10, - "panels": [] - }, - { - "type": "bargauge", - "id": 11, - "targets": [ - { - "expr": "avg by (Hostname) (DCGM_FI_DEV_GPU_UTIL)", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "GPU utilization per node", - "description": "Average NVML utilization per node — spot idle or saturated hosts at a glance.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "displayMode": "gradient", - "valueMode": "color", - "namePlacement": "auto", - "showUnfilled": true, - "sizing": "auto", - "minVizWidth": 8, - "minVizHeight": 16, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "maxVizHeight": 300, - "orientation": "horizontal" - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - }, - { - "value": 30, - "color": "green" - }, - { - "value": 80, - "color": "orange" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "bargauge", - "id": 12, - "targets": [ - { - "expr": "sum by (Hostname) (DCGM_FI_DEV_POWER_USAGE) / clamp_min(sum by (Hostname) (DCGM_FI_DEV_POWER_MGMT_LIMIT), 1) * 100", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "Power draw per node (% of TDP)", - "description": "GPU power usage as a fraction of the node's combined TDP cap. Works across GPU SKUs without per-model thresholds. Requires DCGM_FI_DEV_POWER_MGMT_LIMIT from custom DCGM CSV (see packages/system/gpu-operator/examples/dcgm-custom-metrics.yaml).", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "displayMode": "gradient", - "valueMode": "color", - "namePlacement": "auto", - "showUnfilled": true, - "sizing": "auto", - "minVizWidth": 8, - "minVizHeight": 16, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "maxVizHeight": 300, - "orientation": "horizontal" - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 60, - "color": "yellow" - }, - { - "value": 80, - "color": "orange" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Usage trends", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 20, - "panels": [] - }, - { - "type": "timeseries", - "id": 21, - "targets": [ - { - "expr": "avg by (Hostname) (DCGM_FI_DEV_GPU_UTIL)", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "GPU utilization per node (trend)", - "description": "Per-node NVML utilization over time — shows shifting workload across hosts.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 15 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 20, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 22, - "targets": [ - { - "expr": "sum by (Hostname) (DCGM_FI_DEV_POWER_USAGE)", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "Power draw per node (trend)", - "description": "Per-node GPU power consumption over time.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 15 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "watt", - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 20, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Health", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 23 - }, - "id": 30, - "panels": [] - }, - { - "type": "stat", - "id": 31, - "targets": [ - { - "expr": "count((max by (Hostname, gpu) (DCGM_FI_DEV_XID_ERRORS)) \u003e 0) or vector(0)", - "refId": "A" - } - ], - "title": "GPUs with XID errors", - "description": "Count of GPUs reporting a non-zero XID code. XID = NVIDIA hardware/driver error — any non-zero value needs investigation.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 6, - "x": 0, - "y": 24 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 1, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 32, - "targets": [ - { - "expr": "avg(gpu:power_throttle_fraction:rate5m)", - "refId": "A" - } - ], - "title": "Power throttling (cluster avg)", - "description": "Fraction of time the fleet spent power-throttled. \u003e5% = billed FLOPS are being underdelivered.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 6, - "x": 6, - "y": 24 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "decimals": 2, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 0.05, - "color": "yellow" - }, - { - "value": 0.2, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 33, - "targets": [ - { - "expr": "avg(gpu:thermal_throttle_fraction:rate5m)", - "refId": "A" - } - ], - "title": "Thermal throttling (cluster avg)", - "description": "Fraction of time the fleet spent thermal-throttled. Indicates cooling/datacenter issues.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 6, - "x": 12, - "y": 24 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "decimals": 2, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 0.05, - "color": "yellow" - }, - { - "value": 0.2, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 34, - "targets": [ - { - "expr": "max(DCGM_FI_DEV_GPU_TEMP)", - "refId": "A" - } - ], - "title": "Max GPU temperature", - "description": "Hottest GPU in the fleet right now. Adjust thresholds to match your GPU model specifications.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 6, - "x": 18, - "y": 24 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "celsius", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 75, - "color": "yellow" - }, - { - "value": 85, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 35, - "targets": [ - { - "expr": "DCGM_FI_DEV_GPU_TEMP", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "Temperature per GPU", - "description": "Per-GPU temperature trace. Sustained red zone = cooling issue or aggressive workload.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 29 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "celsius", - "min": 20, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 75, - "color": "yellow" - }, - { - "value": 85, - "color": "red" - } - ] - }, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 36, - "targets": [ - { - "expr": "gpu:power_throttle_fraction:rate5m", - "legendFormat": "power {{Hostname}}/{{gpu}}", - "refId": "A" - }, - { - "expr": "gpu:thermal_throttle_fraction:rate5m", - "legendFormat": "thermal {{Hostname}}/{{gpu}}", - "refId": "B" - } - ], - "title": "Throttle fraction per GPU", - "description": "Red = power throttle, blue = thermal throttle. Both on same chart to compare causes.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 29 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percentunit", - "min": 0, - "max": 1, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 25, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Hardware inventory", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 37 - }, - "id": 40, - "panels": [] - }, - { - "type": "table", - "id": 41, - "targets": [ - { - "expr": "group by (Hostname, modelName, gpu, UUID) (DCGM_FI_DEV_GPU_UTIL)", - "instant": true, - "range": false, - "format": "table", - "refId": "A" - } - ], - "title": "GPU inventory", - "description": "One row per physical GPU. Model / index / UUID sourced from DCGM labels.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 6, - "w": 24, - "x": 0, - "y": 38 - }, - "repeatDirection": "h", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Value": true, - "__name__": true, - "cluster": true, - "container": true, - "device": true, - "endpoint": true, - "instance": true, - "job": true, - "pci_bus_id": true, - "prometheus": true, - "service": true, - "tenant": true, - "tier": true, - "uid": true, - "unit": true - }, - "indexByName": { - "Hostname": 0, - "UUID": 3, - "gpu": 2, - "modelName": 1 - }, - "renameByName": { - "Hostname": "Node", - "UUID": "UUID", - "gpu": "Index", - "modelName": "GPU Model" - } - } - } - ], - "options": { - "frameIndex": 0, - "showHeader": true, - "showTypeIcons": false, - "footer": { - "show": false, - "reducer": [] - }, - "cellHeight": "sm" - } - } - ], - "templating": { - "list": [ - { - "type": "datasource", - "name": "ds_prometheus", - "label": "Prometheus", - "skipUrlSync": false, - "query": "prometheus", - "current": { - "selected": false, - "text": "default", - "value": "default" - }, - "multi": false, - "allowCustomValue": true, - "includeAll": false, - "regex": "", - "auto": false, - "auto_min": "10s", - "auto_count": 30 - } - ] - }, - "annotations": {} -} diff --git a/dashboards/gpu/gpu-performance.json b/dashboards/gpu/gpu-performance.json deleted file mode 100644 index aed9c69a..00000000 --- a/dashboards/gpu/gpu-performance.json +++ /dev/null @@ -1,957 +0,0 @@ -{ - "uid": "gpu-performance", - "title": "GPU Performance", - "tags": [ - "gpu", - "dcgm" - ], - "timezone": "browser", - "editable": true, - "graphTooltip": 1, - "time": { - "from": "now-1h", - "to": "now" - }, - "fiscalYearStartMonth": 0, - "schemaVersion": 42, - "panels": [ - { - "type": "row", - "collapsed": false, - "title": "Overview", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 1, - "panels": [] - }, - { - "type": "stat", - "id": 2, - "targets": [ - { - "expr": "cluster:gpu_count:total", - "refId": "A" - } - ], - "title": "Total GPUs", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 3, - "targets": [ - { - "expr": "cluster:gpu_count:allocated", - "refId": "A" - } - ], - "title": "Allocated", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 6, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 1, - "color": "yellow" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 4, - "targets": [ - { - "expr": "cluster:gpu_util:avg", - "refId": "A" - } - ], - "title": "Average utilization", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 12, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - }, - { - "value": 30, - "color": "green" - }, - { - "value": 80, - "color": "orange" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 5, - "targets": [ - { - "expr": "cluster:gpu_power_watts:sum", - "refId": "A" - } - ], - "title": "Power draw", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 18, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "watt", - "decimals": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Utilization", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 10, - "panels": [] - }, - { - "type": "timeseries", - "id": 11, - "targets": [ - { - "expr": "DCGM_FI_DEV_GPU_UTIL{Hostname=~\"$Hostname\"}", - "legendFormat": "{{Hostname}}/{{gpu}} {{pod}}", - "refId": "A" - } - ], - "title": "GPU Utilization (NVML)", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never", - "spanNulls": false - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 12, - "targets": [ - { - "expr": "DCGM_FI_PROF_PIPE_TENSOR_ACTIVE{Hostname=~\"$Hostname\"} * 100", - "legendFormat": "{{Hostname}}/{{gpu}} {{pod}}", - "refId": "A" - } - ], - "title": "Tensor Pipe Active (realistic load for LLM/AI)", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never", - "spanNulls": false - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 13, - "targets": [ - { - "expr": "DCGM_FI_PROF_GR_ENGINE_ACTIVE{Hostname=~\"$Hostname\"} * 100", - "legendFormat": "{{Hostname}}/{{gpu}} {{pod}}", - "refId": "A" - } - ], - "title": "Graphics Engine Active", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 14 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never", - "spanNulls": false - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 14, - "targets": [ - { - "expr": "DCGM_FI_DEV_MEM_COPY_UTIL{Hostname=~\"$Hostname\"}", - "legendFormat": "{{Hostname}}/{{gpu}} {{pod}}", - "refId": "A" - } - ], - "title": "Memory Copy Utilization", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 14 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never", - "spanNulls": false - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Memory", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 22 - }, - "id": 20, - "panels": [] - }, - { - "type": "timeseries", - "id": 21, - "targets": [ - { - "expr": "DCGM_FI_DEV_FB_USED{Hostname=~\"$Hostname\"} * 1048576", - "legendFormat": "{{Hostname}}/{{gpu}} {{pod}}", - "refId": "A" - } - ], - "title": "VRAM Used", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 23 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "bytes", - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 25, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 22, - "targets": [ - { - "expr": "DCGM_FI_DEV_FB_FREE{Hostname=~\"$Hostname\"} * 1048576", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "VRAM Free", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 23 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "min" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "bytes", - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Power \u0026 Temperature", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 31 - }, - "id": 30, - "panels": [] - }, - { - "type": "timeseries", - "id": 31, - "targets": [ - { - "expr": "DCGM_FI_DEV_POWER_USAGE{Hostname=~\"$Hostname\"}", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "Power Usage per GPU", - "description": "Hardware-level metric — shown cluster-wide regardless of namespace filter.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 32 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "watt", - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 32, - "targets": [ - { - "expr": "DCGM_FI_DEV_GPU_TEMP{Hostname=~\"$Hostname\"}", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "GPU Temperature", - "description": "Hardware-level metric — shown cluster-wide regardless of namespace filter.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 32 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "celsius", - "min": 20, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 75, - "color": "yellow" - }, - { - "value": 85, - "color": "red" - } - ] - }, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Health", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 40 - }, - "id": 40, - "panels": [] - }, - { - "type": "stat", - "id": 41, - "targets": [ - { - "expr": "max by (Hostname, gpu) (DCGM_FI_DEV_XID_ERRORS{Hostname=~\"$Hostname\"})", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "XID errors (latest)", - "description": "Hardware-level metric — shown cluster-wide regardless of namespace filter.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 8, - "x": 0, - "y": 41 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value_and_name", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 1, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 42, - "targets": [ - { - "expr": "rate(DCGM_FI_DEV_POWER_VIOLATION{Hostname=~\"$Hostname\"}[5m])", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "Power Violation (µs/s throttled due to power)", - "description": "Hardware-level metric — shown cluster-wide regardless of namespace filter.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 8, - "x": 8, - "y": 41 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "µs", - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 43, - "targets": [ - { - "expr": "rate(DCGM_FI_DEV_THERMAL_VIOLATION{Hostname=~\"$Hostname\"}[5m])", - "legendFormat": "{{Hostname}}/{{gpu}}", - "refId": "A" - } - ], - "title": "Thermal Violation (µs/s throttled due to thermals)", - "description": "Hardware-level metric — shown cluster-wide regardless of namespace filter.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 5, - "w": 8, - "x": 16, - "y": 41 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "µs", - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [] - } - } - ], - "templating": { - "list": [ - { - "type": "datasource", - "name": "ds_prometheus", - "label": "Prometheus", - "skipUrlSync": false, - "query": "prometheus", - "current": { - "selected": false, - "text": "default", - "value": "default" - }, - "multi": false, - "allowCustomValue": true, - "includeAll": false, - "regex": "", - "auto": false, - "auto_min": "10s", - "auto_count": 30 - }, - { - "type": "query", - "name": "Hostname", - "label": "Host", - "skipUrlSync": false, - "query": "label_values(DCGM_FI_DEV_GPU_UTIL, Hostname)", - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "multi": true, - "allowCustomValue": true, - "refresh": 2, - "sort": 1, - "includeAll": true, - "auto": false, - "auto_min": "10s", - "auto_count": 30 - } - ] - }, - "annotations": {} -} diff --git a/dashboards/gpu/gpu-quotas.json b/dashboards/gpu/gpu-quotas.json deleted file mode 100644 index 865fb95c..00000000 --- a/dashboards/gpu/gpu-quotas.json +++ /dev/null @@ -1,637 +0,0 @@ -{ - "uid": "gpu-quotas", - "title": "GPU Quotas \u0026 Allocation", - "tags": [ - "gpu", - "quotas" - ], - "timezone": "browser", - "editable": true, - "graphTooltip": 1, - "time": { - "from": "now-6h", - "to": "now" - }, - "fiscalYearStartMonth": 0, - "schemaVersion": 42, - "panels": [ - { - "type": "row", - "collapsed": false, - "title": "Allocation overview", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 1, - "panels": [] - }, - { - "type": "stat", - "id": 2, - "targets": [ - { - "expr": "sum(kube_node_status_allocatable{resource=\"nvidia_com_gpu\"})", - "refId": "A" - } - ], - "title": "GPU allocatable", - "description": "Total GPU capacity the cluster can schedule to pods.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 0, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 3, - "targets": [ - { - "expr": "cluster:gpu_count:allocated", - "refId": "A" - } - ], - "title": "GPU requested", - "description": "Sum of GPU requests across all pods cluster-wide, including system namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 6, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 1, - "color": "yellow" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "gauge", - "id": 4, - "targets": [ - { - "expr": "cluster:gpu_count:allocated / sum(kube_node_status_allocatable{resource=\"nvidia_com_gpu\"}) * 100", - "refId": "A" - } - ], - "title": "Allocation ratio", - "description": "Percentage of allocatable GPUs currently requested by pods.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 12, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "showThresholdLabels": false, - "showThresholdMarkers": true, - "sizing": "auto", - "minVizWidth": 75, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "minVizHeight": 75, - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - }, - { - "value": 40, - "color": "green" - }, - { - "value": 80, - "color": "yellow" - }, - { - "value": 95, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 5, - "targets": [ - { - "expr": "count((sum by (namespace, pod) (kube_pod_container_resource_requests{resource=\"nvidia_com_gpu\"}) \u003e 0) * on(namespace, pod) group_left() (kube_pod_status_phase{phase=\"Pending\"} == 1)) or vector(0)", - "refId": "A" - } - ], - "title": "Pending pods (GPU)", - "description": "Pods requesting GPUs that are stuck in Pending state — indicates capacity shortage.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 6, - "x": 18, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 1, - "color": "red" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Per namespace", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 10, - "panels": [] - }, - { - "type": "bargauge", - "id": 11, - "targets": [ - { - "expr": "sum by (namespace) (namespace:gpu_count:allocated{namespace=~\"$namespace\"})", - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "title": "GPU requested per namespace", - "description": "GPU allocation breakdown by namespace — spot top consumers at a glance.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "displayMode": "gradient", - "valueMode": "color", - "namePlacement": "auto", - "showUnfilled": true, - "sizing": "auto", - "minVizWidth": 8, - "minVizHeight": 16, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "maxVizHeight": 300, - "orientation": "horizontal" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "min": 0, - "max": 8, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 12, - "targets": [ - { - "expr": "sum(kube_node_status_allocatable{resource=\"nvidia_com_gpu\"})", - "legendFormat": "Allocatable (total)", - "refId": "A" - }, - { - "expr": "sum(namespace:gpu_count:allocated{namespace=~\"$namespace\"})", - "legendFormat": "Requested", - "refId": "B" - } - ], - "title": "GPU allocated over time", - "description": "Requested vs allocatable GPUs over time — shows allocation pressure trends.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "custom": { - "drawStyle": "line", - "lineInterpolation": "stepAfter", - "fillOpacity": 10, - "showPoints": "never" - } - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Allocatable (total)" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "blue", - "mode": "fixed" - } - } - ] - } - ] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Pods with GPU", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 20, - "panels": [] - }, - { - "type": "table", - "id": 21, - "targets": [ - { - "expr": "kube_pod_container_resource_requests{resource=\"nvidia_com_gpu\", namespace=~\"$namespace\"} * on(namespace, pod) group_left(phase) (kube_pod_status_phase{phase=~\"Running|Pending\"} == 1)", - "instant": true, - "range": false, - "format": "table", - "refId": "requested" - }, - { - "expr": "kube_pod_container_resource_limits{resource=\"nvidia_com_gpu\", namespace=~\"$namespace\"} * on(namespace, pod) group_left() (kube_pod_status_phase{phase=~\"Running|Pending\"} == 1)", - "instant": true, - "range": false, - "format": "table", - "refId": "limits" - } - ], - "title": "Pods requesting GPU", - "description": "Per-pod GPU requests and limits with scheduling status — Running or Pending.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 15 - }, - "repeatDirection": "h", - "transformations": [ - { - "id": "joinByField", - "options": { - "byField": "pod", - "mode": "outer" - } - }, - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Time 1": true, - "Time 2": true, - "__name__": true, - "__name__ 1": true, - "__name__ 2": true, - "cluster": true, - "cluster 1": true, - "cluster 2": true, - "container 2": true, - "endpoint": true, - "endpoint 1": true, - "endpoint 2": true, - "instance": true, - "instance 1": true, - "instance 2": true, - "job": true, - "job 1": true, - "job 2": true, - "namespace 2": true, - "node 2": true, - "prometheus": true, - "prometheus 1": true, - "prometheus 2": true, - "resource": true, - "resource 1": true, - "resource 2": true, - "service": true, - "service 1": true, - "service 2": true, - "tenant": true, - "tenant 1": true, - "tenant 2": true, - "tier": true, - "tier 1": true, - "tier 2": true, - "uid": true, - "uid 1": true, - "uid 2": true, - "unit": true, - "unit 1": true, - "unit 2": true - }, - "indexByName": { - "Value #limits": 5, - "Value #requested": 4, - "container 1": 2, - "namespace 1": 0, - "node 1": 3, - "phase": 6, - "pod": 1 - }, - "renameByName": { - "Value #limits": "Limit", - "Value #requested": "Req", - "container 1": "Container", - "namespace 1": "Namespace", - "node 1": "Node", - "phase": "Status" - } - } - } - ], - "options": { - "frameIndex": 0, - "showHeader": true, - "showTypeIcons": false, - "footer": { - "show": false, - "reducer": [] - }, - "cellHeight": "sm" - }, - "fieldConfig": { - "defaults": {}, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Status" - }, - "properties": [ - { - "id": "custom.cellOptions", - "value": { - "mode": "basic", - "type": "color-background" - } - }, - { - "id": "mappings", - "value": [ - { - "options": { - "Failed": { - "color": "red", - "index": 2 - }, - "Pending": { - "color": "orange", - "index": 1 - }, - "Running": { - "color": "green", - "index": 0 - } - }, - "type": "value" - } - ] - } - ] - } - ] - } - } - ], - "templating": { - "list": [ - { - "type": "datasource", - "name": "ds_prometheus", - "label": "Prometheus", - "skipUrlSync": false, - "query": "prometheus", - "current": { - "selected": false, - "text": "default", - "value": "default" - }, - "multi": false, - "allowCustomValue": true, - "includeAll": false, - "regex": "", - "auto": false, - "auto_min": "10s", - "auto_count": 30 - }, - { - "type": "query", - "name": "namespace", - "label": "Namespace", - "skipUrlSync": false, - "query": "label_values(kube_pod_container_resource_requests{resource=\"nvidia_com_gpu\"}, namespace)", - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "multi": true, - "allowCustomValue": true, - "refresh": 2, - "sort": 1, - "includeAll": true, - "auto": false, - "auto_min": "10s", - "auto_count": 30 - } - ] - }, - "annotations": {} -} diff --git a/dashboards/gpu/gpu-tenants.json b/dashboards/gpu/gpu-tenants.json deleted file mode 100644 index 7fef321d..00000000 --- a/dashboards/gpu/gpu-tenants.json +++ /dev/null @@ -1,1098 +0,0 @@ -{ - "uid": "gpu-tenants", - "title": "GPU Tenant Usage", - "description": "Per-tenant GPU consumption: live allocation, utilization, tensor saturation, power, and 24h GPU-hours / kWh — admin view across all namespaces.", - "tags": [ - "gpu", - "tenants", - "admin" - ], - "timezone": "browser", - "editable": true, - "graphTooltip": 1, - "time": { - "from": "now-24h", - "to": "now" - }, - "fiscalYearStartMonth": 0, - "schemaVersion": 42, - "panels": [ - { - "type": "row", - "collapsed": false, - "title": "Tenant fleet snapshot", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 1, - "panels": [] - }, - { - "type": "stat", - "id": 2, - "targets": [ - { - "expr": "count(namespace:gpu_count:allocated{namespace=~\"$namespace\"} \u003e 0)", - "refId": "A" - } - ], - "title": "Active tenants", - "description": "Namespaces with at least one GPU request (Pending + Running).", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 0, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 3, - "targets": [ - { - "expr": "sum(namespace:gpu_count:allocated{namespace=~\"$namespace\"})", - "refId": "A" - } - ], - "title": "Allocated GPUs", - "description": "Sum of kube GPU requests across tenants. Billable view — includes Pending pods.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 4, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "background", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - }, - { - "value": 1, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 4, - "targets": [ - { - "expr": "cluster:gpu_util:avg", - "refId": "A" - } - ], - "title": "Avg cluster GPU util", - "description": "Average NVML utilization across all GPUs in the cluster. Cluster-wide — DCGM hardware metrics cannot be attributed to workload namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 8, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - }, - { - "value": 30, - "color": "green" - }, - { - "value": 80, - "color": "orange" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 5, - "targets": [ - { - "expr": "cluster:gpu_power_watts:sum", - "refId": "A" - } - ], - "title": "Total GPU power", - "description": "Live power draw summed across all GPUs in the cluster. Cluster-wide — DCGM hardware metrics cannot be attributed to workload namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 12, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "area", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "watt", - "decimals": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 6, - "targets": [ - { - "expr": "sum(sum_over_time(node:power_watts:sum[24h:1m])) / 60 / 1000", - "refId": "A" - } - ], - "title": "Energy (last 24h)", - "description": "Integrated cluster-wide GPU power draw over 24h. Cluster-wide — DCGM hardware metrics cannot be attributed to workload namespaces.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 16, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "kwatth", - "decimals": 1, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "stat", - "id": 7, - "targets": [ - { - "expr": "sum(sum_over_time(namespace:gpu_count:allocated{namespace=~\"$namespace\"}[24h:1m])) / 60", - "refId": "A" - } - ], - "title": "GPU-hours (last 24h)", - "description": "Sum of (GPU count × time requested) across all tenants over the last 24h. Integrated from kube requests, so Pending pods count.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 20, - "y": 1 - }, - "repeatDirection": "h", - "options": { - "graphMode": "none", - "colorMode": "value", - "justifyMode": "auto", - "textMode": "value", - "wideLayout": true, - "showPercentChange": false, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "percentChangeColorMode": "standard", - "orientation": "" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "decimals": 1, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Current allocation", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 10, - "panels": [] - }, - { - "type": "bargauge", - "id": 11, - "targets": [ - { - "expr": "namespace:gpu_count:allocated{namespace=~\"$namespace\"}", - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "title": "GPUs per namespace", - "description": "Kube GPU requests per tenant (billable). Includes Pending pods.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "displayMode": "gradient", - "valueMode": "color", - "namePlacement": "auto", - "showUnfilled": true, - "sizing": "auto", - "minVizWidth": 8, - "minVizHeight": 16, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "maxVizHeight": 300, - "orientation": "horizontal" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "bargauge", - "id": 12, - "targets": [ - { - "expr": "node:fb_used_bytes:sum", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "VRAM used per node", - "description": "FB memory actively used per node. DCGM hardware metrics cannot be attributed to workload namespaces — shown per-node instead.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 6 - }, - "repeatDirection": "h", - "options": { - "displayMode": "gradient", - "valueMode": "color", - "namePlacement": "auto", - "showUnfilled": true, - "sizing": "auto", - "minVizWidth": 8, - "minVizHeight": 16, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "maxVizHeight": 300, - "orientation": "horizontal" - }, - "fieldConfig": { - "defaults": { - "unit": "bytes", - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Utilization (per-node)", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 20, - "panels": [] - }, - { - "type": "timeseries", - "id": 21, - "targets": [ - { - "expr": "node:gpu_util:avg", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "NVML utilization per node", - "description": "Per-node NVML utilization. Stacked to show fleet-wide pressure over time. DCGM hardware metrics cannot be attributed to workload namespaces — shown per-node instead.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 15 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 40, - "showPoints": "never", - "stacking": { - "mode": "normal" - } - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 22, - "targets": [ - { - "expr": "node:tensor_active:avg * 100", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "Tensor saturation per node", - "description": "Real tensor core load per node. Useful to spot nodes with idle tensor cores. DCGM hardware metrics cannot be attributed to workload namespaces — shown per-node instead.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 15 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "percent", - "min": 0, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 40, - "showPoints": "never", - "stacking": { - "mode": "normal" - } - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Power \u0026 allocation trend", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 23 - }, - "id": 30, - "panels": [] - }, - { - "type": "timeseries", - "id": 31, - "targets": [ - { - "expr": "node:power_watts:sum", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "Power draw per node", - "description": "Per-node GPU power draw. Stacked to see cluster-wide energy burn over time. DCGM hardware metrics cannot be attributed to workload namespaces — shown per-node instead.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 24 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "watt", - "min": 0, - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "fillOpacity": 40, - "showPoints": "never", - "stacking": { - "mode": "normal" - } - } - }, - "overrides": [] - } - }, - { - "type": "timeseries", - "id": 32, - "targets": [ - { - "expr": "namespace:gpu_count:allocated{namespace=~\"$namespace\"}", - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "title": "Allocated GPUs per namespace", - "description": "Kube-requested GPU count per tenant over time. Step-after interpolation reflects discrete allocation changes.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 24 - }, - "repeatDirection": "h", - "options": { - "legend": { - "displayMode": "table", - "placement": "bottom", - "showLegend": false, - "calcs": [ - "mean", - "max" - ] - }, - "tooltip": { - "mode": "multi", - "sort": "" - } - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "min": 0, - "custom": { - "drawStyle": "line", - "lineInterpolation": "stepAfter", - "fillOpacity": 40, - "showPoints": "never", - "stacking": { - "mode": "normal" - } - } - }, - "overrides": [] - } - }, - { - "type": "row", - "collapsed": false, - "title": "Top consumers (live)", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 32 - }, - "id": 40, - "panels": [] - }, - { - "type": "table", - "id": 41, - "targets": [ - { - "expr": "namespace:gpu_count:allocated{namespace=~\"$namespace\"}", - "instant": true, - "range": false, - "format": "table", - "refId": "gpus" - } - ], - "title": "Top consumers (allocation)", - "description": "Live ranking of tenants by GPU allocation. Hardware metrics (util, tensor, power, VRAM) cannot be attributed to workload namespaces — see Fleet and Performance dashboards for per-node/per-GPU hardware views.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 10, - "w": 24, - "x": 0, - "y": 33 - }, - "repeatDirection": "h", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": { - "Time": true, - "Time 1": true, - "Time 2": true, - "Time 3": true, - "Time 4": true, - "Time 5": true, - "__name__": true, - "__name__ 1": true, - "__name__ 2": true, - "__name__ 3": true, - "__name__ 4": true, - "__name__ 5": true, - "cluster": true, - "cluster 1": true, - "cluster 2": true, - "cluster 3": true, - "cluster 4": true, - "cluster 5": true, - "endpoint": true, - "endpoint 1": true, - "endpoint 2": true, - "endpoint 3": true, - "endpoint 4": true, - "endpoint 5": true, - "instance": true, - "instance 1": true, - "instance 2": true, - "instance 3": true, - "instance 4": true, - "instance 5": true, - "job": true, - "job 1": true, - "job 2": true, - "job 3": true, - "job 4": true, - "job 5": true, - "prometheus": true, - "prometheus 1": true, - "prometheus 2": true, - "prometheus 3": true, - "prometheus 4": true, - "prometheus 5": true, - "service": true, - "service 1": true, - "service 2": true, - "service 3": true, - "service 4": true, - "service 5": true, - "tenant": true, - "tenant 1": true, - "tenant 2": true, - "tenant 3": true, - "tenant 4": true, - "tenant 5": true, - "tier": true, - "tier 1": true, - "tier 2": true, - "tier 3": true, - "tier 4": true, - "tier 5": true, - "uid": true, - "uid 1": true, - "uid 2": true, - "uid 3": true, - "uid 4": true, - "uid 5": true, - "unit": true, - "unit 1": true, - "unit 2": true, - "unit 3": true, - "unit 4": true, - "unit 5": true - }, - "indexByName": { - "Value #gpus": 1, - "namespace": 0 - }, - "renameByName": { - "Value #gpus": "GPUs", - "namespace": "Namespace" - } - } - } - ], - "options": { - "frameIndex": 0, - "showHeader": true, - "showTypeIcons": false, - "sortBy": [ - { - "displayName": "GPUs", - "desc": true - } - ], - "footer": { - "show": false, - "reducer": [] - }, - "cellHeight": "sm" - } - }, - { - "type": "row", - "collapsed": false, - "title": "Historical usage (last 24h)", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 43 - }, - "id": 50, - "panels": [] - }, - { - "type": "bargauge", - "id": 51, - "targets": [ - { - "expr": "sum_over_time(namespace:gpu_count:allocated{namespace=~\"$namespace\"}[24h:1m]) / 60", - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "title": "GPU-hours per namespace (last 24h)", - "description": "Billable GPU-hours per tenant over the last 24h window.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 44 - }, - "repeatDirection": "h", - "options": { - "displayMode": "gradient", - "valueMode": "color", - "namePlacement": "auto", - "showUnfilled": true, - "sizing": "auto", - "minVizWidth": 8, - "minVizHeight": 16, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "maxVizHeight": 300, - "orientation": "horizontal" - }, - "fieldConfig": { - "defaults": { - "unit": "short", - "decimals": 1, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "blue" - } - ] - } - }, - "overrides": [] - } - }, - { - "type": "bargauge", - "id": 52, - "targets": [ - { - "expr": "sum_over_time(node:power_watts:sum[24h:1m]) / 60 / 1000", - "legendFormat": "{{Hostname}}", - "refId": "A" - } - ], - "title": "Energy per node (last 24h)", - "description": "kWh consumed per node over the last 24h. Integrated from 1-minute power samples. DCGM hardware metrics cannot be attributed to workload namespaces — shown per-node instead.", - "transparent": false, - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 44 - }, - "repeatDirection": "h", - "options": { - "displayMode": "gradient", - "valueMode": "color", - "namePlacement": "auto", - "showUnfilled": true, - "sizing": "auto", - "minVizWidth": 8, - "minVizHeight": 16, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false, - "calcs": [] - }, - "reduceOptions": { - "calcs": [ - "lastNotNull" - ] - }, - "maxVizHeight": 300, - "orientation": "horizontal" - }, - "fieldConfig": { - "defaults": { - "unit": "kwatth", - "decimals": 2, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - } - ] - } - }, - "overrides": [] - } - } - ], - "templating": { - "list": [ - { - "type": "datasource", - "name": "ds_prometheus", - "label": "Prometheus", - "skipUrlSync": false, - "query": "prometheus", - "current": { - "selected": false, - "text": "default", - "value": "default" - }, - "multi": false, - "allowCustomValue": true, - "includeAll": false, - "regex": "", - "auto": false, - "auto_min": "10s", - "auto_count": 30 - }, - { - "type": "query", - "name": "namespace", - "label": "Namespace", - "skipUrlSync": false, - "query": "label_values(namespace:gpu_count:allocated, namespace)", - "datasource": { - "type": "prometheus", - "uid": "$ds_prometheus" - }, - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "multi": true, - "allowCustomValue": true, - "refresh": 2, - "sort": 1, - "includeAll": true, - "auto": false, - "auto_min": "10s", - "auto_count": 30 - } - ] - }, - "annotations": {} -} diff --git a/dashboards/mongodb/mongodb-inmemory.json b/dashboards/mongodb/mongodb-inmemory.json deleted file mode 100644 index c774a314..00000000 --- a/dashboards/mongodb/mongodb-inmemory.json +++ /dev/null @@ -1,1640 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "description": "MongoDB WiredTiger InMemory Details", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "links": [ - { - "asDropdown": false, - "icon": "external link", - "includeVars": true, - "keepTime": true, - "tags": [ - "mongodb" - ], - "targetBlank": false, - "title": "Related Dashboards", - "type": "dashboards" - } - ], - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Amount of data currently stored InMemory in its uncompressed format.", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "decimals": 2, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 6, - "x": 0, - "y": 0 - }, - "hideTimeOverride": true, - "id": 1, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "text": { - "valueSize": 20 - }, - "textMode": "auto", - "wideLayout": true - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "editorMode": "code", - "expr": "avg(mongodb_mongod_wiredtiger_cache_bytes{job=\"$job\", type=\"total\"})", - "interval": "5m", - "range": true, - "refId": "A" - } - ], - "timeFrom": "1m", - "title": "InMemory Data Size", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Maximum size the InMemory data can grow to. Configurable via storage.wiredTiger.inMemory.cacheSizeGB.", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "rgb(31, 120, 193)", - "mode": "fixed" - }, - "decimals": 2, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 6, - "x": 6, - "y": 0 - }, - "hideTimeOverride": true, - "id": 2, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "text": { - "valueSize": 20 - }, - "textMode": "auto", - "wideLayout": true - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "editorMode": "code", - "expr": "avg(mongodb_mongod_wiredtiger_cache_max_bytes{job=\"$job\"})", - "interval": "5m", - "range": true, - "refId": "A" - } - ], - "timeFrom": "1m", - "title": "InMemory Max Data Size", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Amount of memory left available for InMemory databases.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(50, 172, 45, 0.97)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 90 - }, - { - "color": "rgba(245, 54, 54, 0.9)", - "value": 95 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 6, - "x": 12, - "y": 0 - }, - "id": 3, - "interval": "$interval", - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "text": { - "valueSize": 20 - }, - "textMode": "auto", - "wideLayout": true - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "1-(avg(mongodb_mongod_wiredtiger_cache_bytes{job=\"$job\", type=\"total\"})/avg(mongodb_mongod_wiredtiger_cache_max_bytes{job=\"$job\"}))", - "interval": "5m", - "legendFormat": "", - "refId": "A" - } - ], - "title": "InMemory Available", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Percentage of InMemory pages that have been changed and not yet had the modified data consolidated.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(42, 150, 37, 0.97)", - "value": null - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 30 - }, - { - "color": "rgba(245, 54, 54, 0.9)", - "value": 50 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 6, - "x": 18, - "y": 0 - }, - "id": 4, - "interval": "$interval", - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "text": { - "valueSize": 20 - }, - "textMode": "auto", - "wideLayout": true - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(mongodb_mongod_wiredtiger_cache_pages{job=\"$job\",type=\"dirty\"})/avg(mongodb_mongod_wiredtiger_cache_pages{job=\"$job\",type=\"total\"})", - "interval": "5m", - "legendFormat": "", - "refId": "A" - } - ], - "title": "InMemory Dirty Pages", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "WiredTiger internal transactions", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 3 - }, - "id": 5, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg by (type) (rate(mongodb_mongod_wiredtiger_transactions_total{job=\"$job\"}[$interval]) or irate(mongodb_mongod_wiredtiger_transactions_total{job=\"$job\"}[5m]))", - "interval": "$interval", - "legendFormat": "{{type}}", - "refId": "A" - } - ], - "title": "InMemory Transactions", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Configured max and current size of the WiredTiger cache.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 3 - }, - "id": 6, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(mongodb_mongod_wiredtiger_cache_max_bytes{job=\"$job\"})", - "interval": "$interval", - "legendFormat": "Maximum", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(mongodb_mongod_wiredtiger_cache_bytes{job=\"$job\", type=\"total\"})", - "interval": "$interval", - "legendFormat": "Used", - "refId": "B" - } - ], - "title": "InMemory Capacity", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Internal WiredTiger storage engine cursors and sessions currently open.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 11 - }, - "id": 7, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(mongodb_mongod_wiredtiger_session_open_cursors_total{job=\"$job\"})", - "interval": "$interval", - "legendFormat": "Cursors", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(mongodb_mongod_wiredtiger_session_open_sessions_total{job=\"$job\"})", - "interval": "$interval", - "legendFormat": "Sessions", - "refId": "B" - } - ], - "title": "InMemory Sessions", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Pages in the WiredTiger cache", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 11 - }, - "id": 8, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg by (type) (mongodb_mongod_wiredtiger_cache_pages{job=\"$job\"})", - "interval": "$interval", - "legendFormat": "{{type}}", - "refId": "A" - } - ], - "title": "InMemory Pages", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "A WiredTiger 'ticket' is assigned for every operation running simultaneously in the storage engine.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "/^write_/" - }, - "properties": [ - { - "id": "custom.transform", - "value": "negative-Y" - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 19 - }, - "id": 9, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg by (type) (mongodb_mongod_wiredtiger_concurrent_transactions_total_tickets{job=\"$job\"}-mongodb_mongod_wiredtiger_concurrent_transactions_out_tickets{job=\"$job\"})", - "interval": "$interval", - "legendFormat": "{{type}}", - "refId": "A" - } - ], - "title": "InMemory Concurrency Tickets", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Operations queued due to a lock", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 19 - }, - "id": 10, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg by (type) (mongodb_mongod_global_lock_current_queue{job=\"$job\"})", - "interval": "$interval", - "legendFormat": "{{type}}", - "refId": "A" - } - ], - "title": "Queued Operations", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Documents per second inserted, updated, deleted or returned.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 27 - }, - "id": 11, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg by (state) (rate(mongodb_mongod_metrics_document_total{job=\"$job\"}[$interval]) or irate(mongodb_mongod_metrics_document_total{job=\"$job\"}[5m]))", - "interval": "$interval", - "legendFormat": "{{state}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(rate(mongodb_mongod_op_counters_repl_total{job=\"$job\", type=\"delete\"}[$interval]) or irate(mongodb_mongod_op_counters_repl_total{job=\"$job\", type=\"delete\"}[5m]))", - "interval": "$interval", - "legendFormat": "repl_deleted", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(rate(mongodb_mongod_op_counters_repl_total{job=\"$job\", type=\"update\"}[$interval]) or irate(mongodb_mongod_op_counters_repl_total{job=\"$job\", type=\"update\"}[5m]))", - "interval": "$interval", - "legendFormat": "repl_updated", - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(rate(mongodb_mongod_op_counters_repl_total{job=\"$job\", type=\"insert\"}[$interval]) or irate(mongodb_mongod_op_counters_repl_total{job=\"$job\", type=\"insert\"}[5m]))", - "interval": "$interval", - "legendFormat": "repl_inserted", - "refId": "D" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(rate(mongodb_mongod_metrics_ttl_deleted_documents_total{job=\"$job\"}[$interval]) or irate(mongodb_mongod_metrics_ttl_deleted_documents_total{job=\"$job\"}[5m]))", - "interval": "$interval", - "legendFormat": "ttl_deleted", - "refId": "E" - } - ], - "title": "Document Changes", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Number of pages evicted from the WiredTiger cache. The InMemory storage engine only evicts modified pages.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "Pages / sec", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 60, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 27 - }, - "id": 12, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(rate(mongodb_mongod_wiredtiger_cache_evicted_total{job=\"$job\",type=\"modified\"}[$interval]) or irate(mongodb_mongod_wiredtiger_cache_evicted_total{job=\"$job\",type=\"modified\"}[5m]))", - "interval": "$interval", - "legendFormat": "Evicted", - "refId": "A" - } - ], - "title": "InMemory Cache Eviction", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Number of objects scanned (data and index) and documents moved to a new location.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 35 - }, - "id": 13, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg by (state) (rate(mongodb_mongod_metrics_query_executor_total{job=\"$job\"}[$interval]) or irate(mongodb_mongod_metrics_query_executor_total{job=\"$job\"}[5m]))", - "interval": "$interval", - "legendFormat": "{{state}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(rate(mongodb_mongod_metrics_record_moves_total{job=\"$job\"}[$interval]) or irate(mongodb_mongod_metrics_record_moves_total{job=\"$job\"}[5m]))", - "interval": "$interval", - "legendFormat": "moved", - "refId": "B" - } - ], - "title": "Scanned and Moved Objects", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Memory page faults. Not necessarily from MongoDB.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 2, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 35 - }, - "id": 14, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "avg(rate(mongodb_mongod_extra_info_page_faults_total{job=\"$job\"}[$interval]) or irate(mongodb_mongod_extra_info_page_faults_total{job=\"$job\"}[5m]) or rate(mongodb_extra_info_page_faults_total{job=\"$job\"}[$interval]) or irate(mongodb_extra_info_page_faults_total{job=\"$job\"}[5m]))", - "interval": "$interval", - "legendFormat": "Faults", - "refId": "A" - } - ], - "title": "Page Faults", - "type": "timeseries" - } - ], - "preload": false, - "refresh": "30s", - "schemaVersion": 39, - "tags": [ - "mongodb" - ], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "default", - "value": "default" - }, - "hide": 0, - "includeAll": false, - "label": "Datasource", - "multi": false, - "name": "ds_prometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "selected": false, - "text": "auto", - "value": "$__auto_interval_interval" - }, - "hide": 0, - "label": "Interval", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "skipUrlSync": false, - "type": "interval" - }, - { - "current": { - "selected": false, - "text": "", - "value": "" - }, - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "definition": "label_values(mongodb_up, job)", - "hide": 0, - "includeAll": false, - "label": "Service", - "multi": false, - "name": "job", - "options": [], - "query": { - "query": "label_values(mongodb_up, job)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "type": "query" - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "MongoDB InMemory Details", - "uid": "mongodb-inmemory", - "version": 1, - "weekStart": "" -} \ No newline at end of file diff --git a/dashboards/mongodb/mongodb-overview.json b/dashboards/mongodb/mongodb-overview.json deleted file mode 100644 index 558c8490..00000000 --- a/dashboards/mongodb/mongodb-overview.json +++ /dev/null @@ -1,1460 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "description": "MongoDB Overview Dashboard", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "links": [ - { - "asDropdown": false, - "icon": "external link", - "includeVars": true, - "keepTime": true, - "tags": [ - "mongodb" - ], - "targetBlank": false, - "title": "Related Dashboards", - "type": "dashboards" - } - ], - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Shows how many times a command is executed per second on average during the selected interval.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 1, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "editorMode": "code", - "expr": "rate(mongodb_mongod_op_counters_total{job=~\"$job\", type!=\"command\"}[$interval]) or \nirate(mongodb_mongod_op_counters_total{job=~\"$job\", type!=\"command\"}[5m]) or \nrate(mongodb_mongos_op_counters_total{job=~\"$job\", type!=\"command\"}[$interval]) or \nirate(mongodb_mongos_op_counters_total{job=~\"$job\", type!=\"command\"}[5m])", - "interval": "$interval", - "legendFormat": "{{type}}", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_op_counters_repl_total{job=~\"$job\", type!~\"(command|query|getmore)\"}[$interval]) or \nirate(mongodb_mongod_op_counters_repl_total{job=~\"$job\", type!~\"(command|query|getmore)\"}[5m]) or\nrate(mongodb_mongos_op_counters_repl_total{job=~\"$job\", type!~\"(command|query|getmore)\"}[$interval]) or \nirate(mongodb_mongos_op_counters_repl_total{job=~\"$job\", type!~\"(command|query|getmore)\"}[5m])", - "interval": "$interval", - "legendFormat": "repl_{{type}}", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_metrics_ttl_deleted_documents_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongod_metrics_ttl_deleted_documents_total{job=~\"$job\"}[5m]) or\nrate(mongodb_mongos_metrics_ttl_deleted_documents_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongos_metrics_ttl_deleted_documents_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "ttl_delete", - "refId": "C" - } - ], - "title": "Command Operations", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Keep in mind the hard limit on the maximum number of connections set by your distribution.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 7 - }, - "id": 2, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "editorMode": "code", - "expr": "mongodb_connections{job=~\"$job\", state=\"current\"}", - "interval": "$interval", - "legendFormat": "{{pod}}", - "range": true, - "refId": "A" - } - ], - "title": "Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Helps identify why connections are increasing. Shows active cursors compared to cursors being automatically killed after 10 minutes due to an application not closing the connection.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 7 - }, - "id": 3, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "mongodb_mongod_metrics_cursor_open{job=~\"$job\"} or\nmongodb_mongod_cursors{job=~\"$job\"} or\nmongodb_mongos_metrics_cursor_open{job=~\"$job\"} or \nmongodb_mongos_cursors{job=~\"$job\"}", - "interval": "$interval", - "legendFormat": "{{state}}", - "refId": "A" - } - ], - "title": "Cursors", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "When used in combination with 'Command Operations', this graph can help identify write amplification.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 14 - }, - "id": 4, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_metrics_document_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongod_metrics_document_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "{{state}}", - "refId": "A" - } - ], - "title": "Document Operations", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Any number of queued operations for long periods of time is an indication of possible issues. Find the cause and fix it before requests get stuck in the queue.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 14 - }, - "id": 5, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "mongodb_mongod_global_lock_current_queue{job=~\"$job\"}", - "interval": "$interval", - "legendFormat": "{{type}}", - "refId": "A" - } - ], - "title": "Queued Operations", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Ratio of scanned objects/indexes to returned documents. High values indicate inefficient queries.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 21 - }, - "id": 6, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "sum(increase(mongodb_mongod_metrics_query_executor_total{job=~\"$job\", state=\"scanned_objects\"}[5m]))/sum(increase(mongodb_mongod_metrics_document_total{job=~\"$job\", state=\"returned\"}[5m]))", - "interval": "$interval", - "legendFormat": "Document", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "sum(increase(mongodb_mongod_metrics_query_executor_total{job=~\"$job\", state=\"scanned\"}[5m]))/sum(increase(mongodb_mongod_metrics_document_total{job=~\"$job\", state=\"returned\"}[5m]))", - "interval": "$interval", - "legendFormat": "Index", - "refId": "B" - } - ], - "title": "Query Efficiency", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Number of objects scanned during queries and number of documents moved.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 21 - }, - "id": 7, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_metrics_query_executor_total{job=~\"$job\"}[$interval]) or irate(mongodb_mongod_metrics_query_executor_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "{{state}}", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_metrics_record_moves_total{job=~\"$job\"}[$interval]) or irate(mongodb_mongod_metrics_record_moves_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "moved", - "refId": "B" - } - ], - "title": "Scanned and Moved Objects", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Useful for write-heavy workloads to understand how long it takes to verify writes.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ms" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 28 - }, - "id": 8, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_metrics_get_last_error_wtime_total_milliseconds{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongod_metrics_get_last_error_wtime_total_milliseconds{job=~\"$job\"}[5m]) or\nrate(mongodb_mongos_metrics_get_last_error_wtime_total_milliseconds{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongos_metrics_get_last_error_wtime_total_milliseconds{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "Write Wait Time", - "refId": "A" - } - ], - "title": "getLastError Write Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Useful for write-heavy workloads to understand how many concurrent writes are occurring.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 28 - }, - "id": 9, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_metrics_get_last_error_wtime_num_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongod_metrics_get_last_error_wtime_num_total{job=~\"$job\"}[5m]) or\nrate(mongodb_mongos_metrics_get_last_error_wtime_num_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongos_metrics_get_last_error_wtime_num_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "Total", - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_metrics_get_last_error_wtimeouts_total{job=~\"$job\"}[$interval]) or\nirate(mongodb_mongod_metrics_get_last_error_wtimeouts_total{job=~\"$job\"}[5m]) or\nrate(mongodb_mongos_metrics_get_last_error_wtimeouts_total{job=~\"$job\"}[$interval]) or\nirate(mongodb_mongos_metrics_get_last_error_wtimeouts_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "Timeouts", - "refId": "B" - } - ], - "title": "getLastError Write Operations", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Asserts are not important by themselves, but you can correlate spikes with other graphs.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byValue", - "options": { - "op": "gte", - "reducer": "allIsZero", - "value": 0 - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": true, - "tooltip": true, - "viz": false - } - } - ] - } - ] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 35 - }, - "id": 10, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_asserts_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongod_asserts_total{job=~\"$job\"}[5m]) or\nrate(mongodb_mongos_asserts_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongos_asserts_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "{{type}}", - "refId": "A" - } - ], - "title": "Assert Events", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "description": "Page faults indicate that requests are processed from disk either because an index is missing or there is not enough memory for the data set.", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 20, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 35 - }, - "id": 11, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "expr": "rate(mongodb_mongod_extra_info_page_faults_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongod_extra_info_page_faults_total{job=~\"$job\"}[5m]) or\nrate(mongodb_mongos_extra_info_page_faults_total{job=~\"$job\"}[$interval]) or \nirate(mongodb_mongos_extra_info_page_faults_total{job=~\"$job\"}[5m])", - "interval": "$interval", - "legendFormat": "Faults", - "refId": "A" - } - ], - "title": "Page Faults", - "type": "timeseries" - } - ], - "preload": false, - "refresh": "30s", - "schemaVersion": 39, - "tags": [ - "mongodb" - ], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "default", - "value": "default" - }, - "hide": 0, - "includeAll": false, - "label": "Datasource", - "multi": false, - "name": "ds_prometheus", - "options": [], - "query": "prometheus", - "queryValue": "", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "selected": false, - "text": "auto", - "value": "$__auto_interval_interval" - }, - "hide": 0, - "label": "Interval", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "skipUrlSync": false, - "type": "interval" - }, - { - "current": { - "selected": false, - "text": "", - "value": "" - }, - "datasource": { - "type": "prometheus", - "uid": "${ds_prometheus}" - }, - "definition": "label_values(mongodb_up, job)", - "hide": 0, - "includeAll": true, - "label": "Service", - "multi": true, - "name": "job", - "options": [], - "query": { - "query": "label_values(mongodb_up, job)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "type": "query" - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "MongoDB Overview", - "uid": "mongodb-overview", - "version": 1, - "weekStart": "" -} \ No newline at end of file diff --git a/dashboards/nats/nats-jetstream.json b/dashboards/nats/nats-jetstream.json deleted file mode 100644 index d2312e7e..00000000 --- a/dashboards/nats/nats-jetstream.json +++ /dev/null @@ -1,1541 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "description": "NATS JetStream Dashboard", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": 90, - "links": [], - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 13, - "x": 0, - "y": 0 - }, - "id": 34, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "irate(nats_stream_total_messages{server_id=~\"$server\"}[5m])", - "instant": false, - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "messages per second", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 5, - "x": 13, - "y": 0 - }, - "id": 32, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_varz_jetstream_stats_memory{server_id=\"$server\"})", - "interval": "", - "legendFormat": "", - "range": true, - "refId": "A" - } - ], - "title": "Memory Used", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "min": 0, - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 6, - "x": 18, - "y": 0 - }, - "id": 14, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_varz_connections{server_id=~\"$server\"})", - "interval": "", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Connections", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 5, - "x": 13, - "y": 3 - }, - "id": 33, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_varz_jetstream_config_max_memory{server_id=~\"$server\"})", - "interval": "", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Total Memory", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 5, - "w": 6, - "x": 18, - "y": 3 - }, - "id": 29, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_server_total_consumers{server_id=~\"$server\"})", - "interval": "", - "legendFormat": "__auto", - "range": true, - "refId": "A" - } - ], - "title": "Total Consumers", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "decimals": 3, - "mappings": [], - "max": 1, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "#EAB839", - "value": 0.75 - }, - { - "color": "red", - "value": 0.9 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 4, - "x": 0, - "y": 8 - }, - "id": 28, - "options": { - "minVizHeight": 75, - "minVizWidth": 75, - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true, - "sizing": "auto" - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_varz_jetstream_stats_storage{server_id=~\"$server\"})/sum(nats_varz_jetstream_config_max_storage{server_id=~\"$server\"})", - "interval": "", - "legendFormat": "", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "expr": "", - "interval": "", - "legendFormat": "", - "refId": "B" - } - ], - "title": "Storage Used", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 5, - "x": 4, - "y": 8 - }, - "id": 15, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_varz_jetstream_stats_storage{server_id=~\"$server\"})", - "interval": "", - "legendFormat": "", - "range": true, - "refId": "A" - } - ], - "title": "Total Storage Used", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "decimals": 3, - "mappings": [], - "max": 1, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "#EAB839", - "value": 0.75 - }, - { - "color": "red", - "value": 0.9 - } - ] - }, - "unit": "percentunit" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 4, - "x": 9, - "y": 8 - }, - "id": 31, - "options": { - "minVizHeight": 75, - "minVizWidth": 75, - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true, - "sizing": "auto" - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_varz_jetstream_stats_memory{server_id=~\"$server\"})/sum(nats_varz_jetstream_config_max_memory{server_id=~\"$server\"})", - "interval": "", - "legendFormat": "", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "expr": "", - "interval": "", - "legendFormat": "", - "refId": "B" - } - ], - "title": "Memory Used", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "min": 0, - "thresholds": { - "mode": "percentage", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 5, - "x": 4, - "y": 11 - }, - "id": 30, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "editorMode": "code", - "expr": "sum(nats_varz_jetstream_config_max_storage{server_id=~\"$server\"})", - "interval": "", - "legendFormat": "", - "range": true, - "refId": "A" - } - ], - "title": "Max Storage", - "type": "stat" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 19, - "panels": [], - "title": "Stream metrics", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 0, - "y": 15 - }, - "id": 17, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(nats_stream_total_bytes) by (stream_name)", - "interval": "", - "legendFormat": "{{stream_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Stream data size", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 8, - "y": 15 - }, - "id": 24, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(nats_stream_total_messages) by (stream_name)", - "interval": "", - "legendFormat": "{{stream_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Stream message count", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "mps" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 16, - "y": 15 - }, - "id": 20, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(rate(nats_stream_total_messages{server_id=~\"$server\",stream_name=~\"$stream\"}[$__rate_interval])) by (stream_name)", - "hide": false, - "interval": "", - "legendFormat": "{{stream_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Message Rate (per second)", - "type": "timeseries" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 21 - }, - "id": 23, - "panels": [], - "title": "Consumer Metrics", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "description": "Messages added & processed per minute per consumer", - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "mps" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 24, - "x": 0, - "y": 22 - }, - "id": 25, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "right", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(rate(nats_consumer_num_pending{server_id=~\"$server\",stream_name=~\"$stream\",consumer_name=~\"$consumer\"}[$__rate_interval])+rate(nats_consumer_delivered_consumer_seq{server_id=~\"$server\",stream_name=~\"$stream\",consumer_name=~\"$consumer\"}[$__rate_interval])) by (consumer_name)", - "hide": false, - "instant": false, - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{consumer_name}} +", - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "- sum(rate(nats_consumer_delivered_consumer_seq{server_id=~\"$server\",stream_name=~\"$stream\",consumer_name=~\"$consumer\",consumer_name=~\"$consumer\"}[$__rate_interval])) by (consumer_name)", - "hide": false, - "interval": "", - "legendFormat": "{{consumer_name}} -", - "range": true, - "refId": "A" - } - ], - "title": "Messages per second (++/--)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 0, - "y": 28 - }, - "id": 21, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(nats_consumer_delivered_consumer_seq{server_id=~\"$server\",stream_name=~\"$stream\",consumer_name=~\"$consumer\"}) by (consumer_name)", - "hide": false, - "interval": "", - "legendFormat": "{{consumer_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Total delivered messages", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 8, - "y": 28 - }, - "id": 26, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(nats_consumer_num_pending{server_id=~\"$server\",stream_name=~\"$stream\",consumer_name=~\"$consumer\"}) by (consumer_name)", - "hide": false, - "interval": "", - "legendFormat": "{{consumer_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Pending messages", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 16, - "y": 28 - }, - "id": 27, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(nats_consumer_num_ack_pending{server_id=~\"$server\",stream_name=~\"$stream\",consumer_name=~\"$consumer\"}) by (consumer_name)", - "hide": false, - "interval": "", - "legendFormat": "{{consumer_name}}", - "range": true, - "refId": "A" - } - ], - "title": "Message Acks Pending", - "type": "timeseries" - } - ], - "preload": false, - "refresh": "10s", - "schemaVersion": 40, - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "vm-shortterm", - "value": "59e01639-a99e-4945-bb94-10821e415ad5" - }, - "description": "", - "label": "datasource", - "name": "DS_PROMETHEUS", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - }, - { - "current": { - "text": "", - "value": "" - }, - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "definition": "label_values(nats_varz_jetstream_stats_memory,namespace)", - "includeAll": false, - "name": "namespace", - "options": [], - "query": { - "query": "label_values(nats_varz_jetstream_stats_memory,namespace)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 1, - "regex": "", - "type": "query" - }, - { - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "definition": "label_values(nats_server_total_streams{namespace=\"$namespace\"},server_id)", - "hide": 2, - "includeAll": true, - "label": "Server", - "name": "server", - "options": [], - "query": { - "query": "label_values(nats_server_total_streams{namespace=\"$namespace\"},server_id)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "type": "query" - }, - { - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "definition": "label_values(nats_stream_last_seq{server_id=~\"$server\"},stream_name)", - "includeAll": true, - "label": "Stream", - "multi": true, - "name": "stream", - "options": [], - "query": { - "qryType": 1, - "query": "label_values(nats_stream_last_seq{server_id=~\"$server\"},stream_name)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "type": "query" - }, - { - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": { - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "definition": "label_values(nats_consumer_num_pending,consumer_name)", - "includeAll": true, - "label": "Consumer", - "multi": true, - "name": "consumer", - "options": [], - "query": { - "query": "label_values(nats_consumer_num_pending,consumer_name)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "type": "query" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": {}, - "timezone": "browser", - "title": "NATS JetStream", - "uid": "yQUo5l17k", - "version": 6, - "weekStart": "" -} diff --git a/dashboards/nats/nats-server.json b/dashboards/nats/nats-server.json deleted file mode 100644 index 02aa39b2..00000000 --- a/dashboards/nats/nats-server.json +++ /dev/null @@ -1,1463 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "description": "NATS Server Dashboard for use with built-in Prometheus NATS Exporter into nats official helm charts", - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 91, - "links": [], - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 10, - "panels": [], - "title": "OS Metrics", - "type": "row" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 1, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_cpu", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_cpu", - "refId": "A", - "step": 4 - } - ], - "title": "Server CPU", - "type": "timeseries" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 3, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_mem", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_mem", - "refId": "A", - "step": 4 - } - ], - "title": "Server Memory", - "type": "timeseries" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 8 - }, - "id": 11, - "panels": [], - "title": "Throughput", - "type": "row" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 9 - }, - "id": 7, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_in_bytes", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_in_bytes", - "refId": "A", - "step": 10 - } - ], - "title": "Bytes In", - "type": "timeseries" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 9 - }, - "id": 8, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_in_msgs", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_in_msgs", - "refId": "A", - "step": 10 - } - ], - "title": "NATS Msgs In", - "type": "timeseries" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 9 - }, - "id": 5, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_out_bytes", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_out_bytes", - "refId": "A", - "step": 10 - } - ], - "title": "Bytes Out", - "type": "timeseries" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 9 - }, - "id": 6, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_out_msgs", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_out_msgs", - "refId": "A", - "step": 10 - } - ], - "title": "NATS Msgs Out", - "type": "timeseries" - }, - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 0, - "y": 16 - }, - "id": 15, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "sum(rate(nats_varz_in_bytes[1m]))", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "metric": "nats_varz_in_bytes", - "refId": "A", - "step": 10 - } - ], - "title": "rate(Bytes In)", - "type": "timeseries" - }, - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 6, - "y": 16 - }, - "id": 13, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "sum(rate(nats_varz_in_msgs[1m]))", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "metric": "nats_varz_in_msgs", - "refId": "A", - "step": 10 - } - ], - "title": "rate(NATS Msgs In)", - "type": "timeseries" - }, - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 12, - "y": 16 - }, - "id": 16, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "sum(rate(nats_varz_out_bytes[1m]))", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "metric": "nats_varz_out_bytes", - "refId": "A", - "step": 10 - } - ], - "title": "rate(Bytes Out)", - "type": "timeseries" - }, - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 6, - "x": 18, - "y": 16 - }, - "id": 14, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "lastNotNull" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "sum(rate(nats_varz_out_msgs[1m]))", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "metric": "nats_varz_out_msgs", - "refId": "A", - "step": 10 - } - ], - "title": "rate(NATS Msgs Out)", - "type": "timeseries" - }, - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 23 - }, - "id": 12, - "panels": [], - "title": "Client Metrics", - "type": "row" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "points", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 6, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "always", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 8, - "x": 0, - "y": 24 - }, - "id": 2, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_connections", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_connections", - "refId": "A", - "step": 2 - } - ], - "title": "Connections", - "type": "timeseries" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "points", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 6, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "always", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 8, - "x": 8, - "y": 24 - }, - "id": 4, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_subscriptions", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_subscriptions", - "refId": "A", - "step": 4 - } - ], - "title": "Subscriptions", - "type": "timeseries" - }, - { - "datasource": { - "uid": "${DS_PROMETHEUS}" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "points", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 2, - "pointSize": 6, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "always", - "spanNulls": true, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 8, - "x": 16, - "y": 24 - }, - "id": 9, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.4.0", - "targets": [ - { - "datasource": { - "datasource": "PBFA97CFB590B2093", - "type": "prometheus", - "uid": "${DS_PROMETHEUS}" - }, - "exemplar": true, - "expr": "nats_varz_slow_consumers", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{server_id}}", - "metric": "nats_varz_slow_consumers", - "refId": "A", - "step": 2 - } - ], - "title": "Slow Consumers", - "type": "timeseries" - } - ], - "preload": false, - "refresh": "", - "schemaVersion": 40, - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "vm-shortterm", - "value": "59e01639-a99e-4945-bb94-10821e415ad5" - }, - "label": "datasource", - "name": "DS_PROMETHEUS", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "type": "datasource" - } - ] - }, - "time": { - "from": "now-5m", - "to": "now" - }, - "timepicker": {}, - "timezone": "browser", - "title": "NATS Server Dashboard", - "uid": "4_zbf287k", - "version": 2, - "weekStart": "" -} diff --git a/docs/agents/changelog.md b/docs/agents/changelog.md index 2fde1224..feb70597 100644 --- a/docs/agents/changelog.md +++ b/docs/agents/changelog.md @@ -6,20 +6,6 @@ This file contains detailed instructions for AI-powered IDE on how to generate c Follow these instructions when the user explicitly asks to generate a changelog. -## Scope and boundaries - -**Your single deliverable is the file `docs/changelogs/v.md`.** Write the complete, verified changelog to that path. That is the entire task. Exit as soon as the file is written and verified against the checklist in Step 9. - -Unless the caller explicitly instructs otherwise: - -- **In the cozystack working tree**, do not run `git commit`, `git push`, `git checkout` (to switch branches), `git branch`, `git tag`, `git reset`, `git merge`, or `git rebase`. Do not write to local branches, tags, or HEAD. `git fetch` is expected and fine (see the read-only analysis list below). -- **Do not** push to any remote, open pull requests, or issue GitHub API write calls (POST / PATCH / DELETE) for any repository. -- In the cozystack working tree, the **only** file you create or modify is `docs/changelogs/v.md`. Cloning auxiliary repositories under `_repos/` for cross-repo analysis (see Step 6) is fine; local git operations inside those disposable clones (`git checkout`, `git pull`, etc.) are allowed — just never push from them or open PRs against them. - -The caller — a GitHub Actions workflow in CI, or a developer running you interactively — owns branching, committing, pushing, and PR creation. They will perform those actions after you exit. Do not pre-empt them even if the working tree looks ready. - -Read-only analysis is expected and encouraged: `git log`, `git show`, `git fetch`, `git diff`, `gh pr view`, `gh api` GET requests, and reading any file in the repository. - ## Required Tools Before generating changelogs, ensure you have access to `gh` (GitHub CLI) tool, which is used to fetch commit and PR author information. The GitHub CLI is used to correctly identify PR authors from commits and pull requests. @@ -36,7 +22,7 @@ When the user asks to generate a changelog, follow these steps in the specified - [ ] Step 5: Get the list of commits for the release period - [ ] Step 6: Check additional repositories (website is REQUIRED, optional repos if tags exist) - [ ] **MANDATORY**: Check website repository for documentation changes WITH authors and PR links via GitHub CLI - - [ ] **MANDATORY**: Check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy, external-apps-example, ansible-cozystack) for tags during release period + - [ ] **MANDATORY**: Check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy) for tags during release period - [ ] **MANDATORY**: For ALL commits from additional repos, get GitHub username via CLI, prioritizing PR author over commit author. - [ ] Step 7: Analyze commits (extract PR numbers, authors, user impact) - [ ] **MANDATORY**: For EVERY PR in main repo, get PR author via `gh pr view --json author --jq .author.login` (do NOT skip this step) @@ -162,8 +148,6 @@ Cozystack release may include changes from related repositories. Check and inclu - [https://github.com/cozystack/boot-to-talos](https://github.com/cozystack/boot-to-talos) - [https://github.com/cozystack/cozyhr](https://github.com/cozystack/cozyhr) - [https://github.com/cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -- [https://github.com/cozystack/external-apps-example](https://github.com/cozystack/external-apps-example) -- [https://github.com/cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack) **⚠️ IMPORTANT**: You MUST check ALL optional repositories for tags created during the release period. Do NOT skip this step even if you think there might not be any tags. Use the process below to verify. @@ -211,7 +195,7 @@ Cozystack release may include changes from related repositories. Check and inclu 3. **For optional repositories, check if tags exist during release period:** - **⚠️ MANDATORY: You MUST check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy, external-apps-example, ansible-cozystack). Do NOT skip any repository!** + **⚠️ MANDATORY: You MUST check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy). Do NOT skip any repository!** **Use the helper script:** ```bash @@ -224,7 +208,7 @@ Cozystack release may include changes from related repositories. Check and inclu ``` The script will: - - Check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy, external-apps-example, ansible-cozystack) + - Check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy) - Look for tags created during the release period - Get commits between tags (if tags exist) or by date range (if no tags) - Extract PR numbers from commit messages @@ -585,7 +569,7 @@ Create a new changelog file in the format matching previous versions: - [ ] Step 5 completed: **ALL commits included** (including merge commits and backports) - do not skip any commits - [ ] Step 5 completed: **Backports identified and handled correctly** - original PR author used, both original and backport PR numbers included - [ ] Step 6 completed: Website repository checked for documentation changes WITH authors and PR links via GitHub CLI -- [ ] Step 6 completed: **ALL** optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy, external-apps-example, ansible-cozystack) checked for tags during release period +- [ ] Step 6 completed: **ALL** optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy) checked for tags during release period - [ ] Step 6 completed: For ALL commits from additional repos, GitHub username obtained via GitHub CLI (not skipped). For commits with PR numbers, PR author used via `gh pr view` (not commit author) - [ ] Step 7 completed: For EVERY PR in main repo (including backports), PR author obtained via `gh pr view --json author --jq .author.login` (not skipped or assumed). Commit author NOT used - always use PR author - [ ] Step 7 completed: **Backports verified** - for each backport PR, original PR found and original PR author used in changelog @@ -622,8 +606,6 @@ Create a new changelog file in the format matching previous versions: **Save the changelog:** Save the changelog to file `docs/changelogs/v.md` according to the version for which the changelog is being generated. -**Then exit.** Do not commit, push, create a branch, or open a pull request — the caller handles all git and GitHub operations after you return. See the "Scope and boundaries" section at the top of this document. - ### Important notes - **After fetch with --force** local tags are up-to-date, use them for work @@ -646,7 +628,7 @@ Save the changelog to file `docs/changelogs/v.md` according to the vers - **Additional repositories (Step 6) - MANDATORY**: - **⚠️ CRITICAL**: Always check the **website** repository for documentation changes during the release period. This is a required step and MUST NOT be skipped. - - **⚠️ CRITICAL**: You MUST check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy, external-apps-example, ansible-cozystack) for tags during the release period. Do NOT skip any repository even if you think there might not be tags. + - **⚠️ CRITICAL**: You MUST check ALL optional repositories (talm, boot-to-talos, cozyhr, cozy-proxy) for tags during the release period. Do NOT skip any repository even if you think there might not be tags. - **CRITICAL**: For ALL entries from additional repositories (website and optional), you MUST: - **MANDATORY**: Extract PR number from commit message first - **MANDATORY**: For commits with PR numbers, ALWAYS use `gh pr view --repo cozystack/ --json author --jq .author.login` to get PR author (not commit author) @@ -655,7 +637,7 @@ Save the changelog to file `docs/changelogs/v.md` according to the vers - **MANDATORY**: Do NOT use commit author for PRs - always use PR author - Include PR link or commit hash reference - Format: `* **[repo] Description**: details ([**@username**](https://github.com/username) in cozystack/repo#123)` - - For **optional repositories** (talm, boot-to-talos, cozyhr, cozy-proxy, external-apps-example, ansible-cozystack), you MUST check ALL of them for tags during the release period. Use the loop provided in Step 6 to check each repository systematically. + - For **optional repositories** (talm, boot-to-talos, cozyhr, cozy-proxy), you MUST check ALL of them for tags during the release period. Use the loop provided in Step 6 to check each repository systematically. - When including changes from additional repositories, use the format: `[repo-name] Description` and link to the repository's PR/issue if available - **Prefer PR numbers over commit hashes**: For commits from additional repositories, extract PR number from commit message using GitHub API. Use PR format (`cozystack/website#123`) instead of commit hash (`cozystack/website@abc1234`) when available - **Never add entries without author and PR/commit reference**: Every entry from additional repositories must have both author and link diff --git a/docs/agents/contributing.md b/docs/agents/contributing.md index 88b062ea..4a2a7ef9 100644 --- a/docs/agents/contributing.md +++ b/docs/agents/contributing.md @@ -1,140 +1,167 @@ -# Contributing Conventions for AI Agents +# Instructions for AI Agents -Project-side conventions for commits, branches, and pull requests in Cozystack. +Guidelines for AI agents contributing to Cozystack. ## Checklist for Creating a Pull Request -- [ ] Commit message follows Conventional Commits format +- [ ] Changes are made and tested +- [ ] Commit message uses correct `[component]` prefix - [ ] Commit is signed off with `--signoff` - [ ] Branch is rebased on `upstream/main` (no extra commits) - [ ] PR body includes description and release note -- [ ] Ran `make generate` in every package whose `values.yaml`, `values.schema.json`, `Chart.yaml`, or `README.md` was touched, and committed the regenerated files +- [ ] PR is pushed and created with `gh pr create` -## Regenerate Artifacts Before Committing +## How to Commit and Create Pull Requests -Several files in each package are produced by `make generate` from `values.yaml` + `values.schema.json` and must stay in sync with the hand-edited sources: +### 1. Make Your Changes -- `packages/(apps|extra)//README.md` — regenerated by `cozyvalues-gen` (parameter table, formatting). -- `packages/(apps|extra)//values.schema.json` — `cozyvalues-gen` rewrites ordering and derived fields. -- `packages/system/-rd/cozyrds/.yaml` — produced by `hack/update-crd.sh`, which `make generate` invokes. +Edit the necessary files in the codebase. -**Before committing edits to any of those sources**, run `make generate` inside the package and stage the full diff: +### 2. Commit with Proper Format + +Use the `[component]` prefix and `--signoff` flag: ```bash -make -C packages// generate -git add packages/// packages/system/-rd/ +git commit --signoff -m "[component] Brief description of changes" ``` -The repo's pre-commit CI job runs `make generate` in every package and then `git diff --exit-code`. Any unstaged generator output fails the job with exit code 123 and blocks the PR. Also rerun `make generate` after a `git commit --amend` if the amended change touched any of the sources above. - -To locate packages a WIP branch likely needs to be regenerated: - -```bash -git diff --name-only | xargs -n1 dirname | sort -u | grep ^packages/ -``` - -## Commit Format - -Follow [Conventional Commits](https://www.conventionalcommits.org/) with `--signoff`: - -```bash -git commit --signoff -m "type(scope): brief description" -``` - -**Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore` - -**Scopes** (examples — not an exhaustive list; pick the most specific scope that describes the change, and introduce a new one if a genuinely new area needs its own): - -- System, e.g.: `dashboard`, `platform`, `operator`, `cilium`, `kube-ovn`, `linstor`, `fluxcd`, `cluster-api` -- Apps, e.g.: `postgres`, `mariadb`, `redis`, `kafka`, `clickhouse`, `virtual-machine`, `kubernetes` -- Other, e.g.: `api`, `hack`, `tests`, `ci`, `docs`, `agents`, `maintenance` - -Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer. +**Component prefixes:** +- System: `[dashboard]`, `[platform]`, `[cilium]`, `[kube-ovn]`, `[linstor]`, `[fluxcd]`, `[cluster-api]` +- Apps: `[postgres]`, `[mysql]`, `[redis]`, `[kafka]`, `[clickhouse]`, `[virtual-machine]`, `[kubernetes]` +- Other: `[tests]`, `[ci]`, `[docs]`, `[maintenance]` **Examples:** ```bash -git commit --signoff -m "feat(dashboard): add config hash annotations to restart pods on config changes" -git commit --signoff -m "fix(postgres): update operator to version 1.2.3" -git commit --signoff -m "docs(contributing): add installation guide" +git commit --signoff -m "[dashboard] Add config hash annotations to restart pods on config changes" +git commit --signoff -m "[postgres] Update operator to version 1.2.3" +git commit --signoff -m "[docs] Add installation guide" ``` -## PR Title Auto-Labeling +### 3. Rebase on upstream/main (if needed) -`.github/workflows/pr-labeler.yaml` parses the PR title on `opened`, `edited`, `reopened`, and `synchronize` events and applies labels additively (never removes). The title is expected to follow Conventional Commits — same format as commit messages above. - -**Type → `kind/*`:** - -| type | label | -| --------- | ------------------ | -| feat | kind/feature | -| fix | kind/bug | -| docs | kind/documentation | -| chore | kind/cleanup | -| refactor | kind/cleanup | -| style, perf, test, build, ci, revert | (no kind label) | - -**Scope → `area/*`** (full mapping in `.github/workflows/pr-labeler.yaml`): - -| scope (examples) | label | -| --- | --- | -| agents, ai | area/ai | -| api, cozystack-api | area/api | -| build | area/build | -| ci | area/ci | -| dashboard | area/dashboard | -| postgres, mariadb, redis, etcd, kafka, clickhouse, postgres-operator, mariadb-operator | area/database | -| extra | area/extra | -| kubernetes | area/kubernetes | -| monitoring, vlogs, vmstack, grafana, workloadmonitor | area/monitoring | -| ingress, gateway, vpn, metallb, cilium, kube-ovn, cozy-proxy, ... | area/networking | -| platform, bundle, flux, fluxcd, cluster-api, talos, installer, cozyctl, cozystack-engine, cozy-lib | area/platform | -| backport, release | area/release | -| seaweedfs, bucket, linstor, velero, harbor, backups | area/storage | -| tests, e2e | area/testing | -| kubevirt, cdi, vmi, vm-import, virtual-machine, hami, gpu-operator | area/virtualization | - -**Special handling:** - -- `[Backport release-1.x]` prefix is stripped before parsing; `area/release` and `backport` labels are added. -- Composite scope (`feat(platform, system, apps): ...`) — each comma-separated part is mapped independently. -- `!` after type or `BREAKING CHANGE:` footer in the body → `kind/breaking-change`. -- Unmapped scope or non-conventional title → `area/uncategorized` (signals the PR needs manual area selection). -- Bracket-style fallback (`[scope] description`) maps `scope` → `area/*` but cannot infer `kind/*`. - -### AI Agent Attribution - -When an AI agent authors or materially assists with a commit, add an `Assisted-By:` trailer naming the model: - -```text -Assisted-By: Claude -Assisted-By: GPT-5 -Assisted-By: Gemini -``` - -This sits alongside the `Signed-off-by:` trailer produced by `--signoff`. Use one trailer per model if multiple contributed. - -## Rebasing on upstream/main - -If the branch has extra commits, clean it up: +If your branch has extra commits, clean it up: ```bash +# Fetch latest git fetch upstream + +# Create clean branch from upstream/main git checkout -b my-feature upstream/main + +# Cherry-pick only your commit git cherry-pick -git push -f origin my-feature + +# Force push to your branch +git push -f origin my-feature:my-branch-name ``` -## Pull Request Body +### 4. Push Your Branch -Fill in the template at [`.github/PULL_REQUEST_TEMPLATE.md`](../../.github/PULL_REQUEST_TEMPLATE.md). It includes the required `release-note` block. +```bash +git push origin +``` -Create the PR with `gh pr create --title "type(scope): brief description" --body-file `. +### 5. Create Pull Request -## Fetching Unresolved Review Comments +Write the PR body to a temporary file: -Cozystack uses GitHub review threads with resolution status. Only unresolved threads are actionable — resolved threads are already handled. +```bash +cat > /tmp/pr_body.md << 'EOF' +## What this PR does -The REST endpoint `/pulls/{pr}/reviews` returns review summaries, not individual review comments. Use the GraphQL API to access `reviewThreads` with `isResolved` status: +Brief description of the changes. + +Changes: +- Change 1 +- Change 2 + +### Release note + +```release-note +[component] Description for changelog +``` +EOF +``` + +Create the PR: + +```bash +gh pr create --title "[component] Brief description" --body-file /tmp/pr_body.md +``` + +Clean up: + +```bash +rm /tmp/pr_body.md +``` + +## Addressing AI Bot Reviewer Comments + +When the user asks to fix comments from AI bot reviewers (like Qodo, Copilot, etc.): + +### 1. Get PR Comments + +View all comments on the pull request: + +```bash +gh pr view --comments +``` + +Or for the current branch: + +```bash +gh pr view --comments +``` + +### 2. Review Each Comment Carefully + +**Important**: Do NOT blindly apply all suggestions. Each comment should be evaluated: + +- **Consider context** - Does the suggestion make sense for this specific case? +- **Check project conventions** - Does it align with Cozystack patterns? +- **Evaluate impact** - Will this improve code quality or introduce issues? +- **Question validity** - AI bots can be wrong or miss context + +**When to apply:** +- ✅ Legitimate bugs or security issues +- ✅ Clear improvements to code quality +- ✅ Better error handling or edge cases +- ✅ Conformance to project conventions + +**When to skip:** +- ❌ Stylistic preferences that don't match project style +- ❌ Over-engineering simple code +- ❌ Changes that break existing patterns +- ❌ Suggestions that show misunderstanding of the code + +### 3. Apply Valid Fixes + +Make changes addressing the valid comments. Use your judgment. + +### 4. Leave Changes Uncommitted + +**Critical**: Do NOT commit or push the changes automatically. + +Leave the changes in the working directory so the user can: +- Review the fixes +- Decide whether to commit them +- Make additional adjustments if needed + +```bash +# After making changes, show status but DON'T commit +git status +git diff +``` + +The user will commit and push when ready. + +## Code Review Comments + +When asked to fix code review comments, **always work only with unresolved (open) comments**. Resolved comments should be ignored as they have already been addressed. + +### Getting Unresolved Review Comments + +Use GitHub GraphQL API to fetch only unresolved review comments from a pull request: ```bash gh api graphql -F owner=cozystack -F repo=cozystack -F pr= -f query=' @@ -162,7 +189,27 @@ query($owner: String!, $repo: String!, $pr: Int!) { }' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .comments.nodes[]' ``` -Compact one-line variant: +### Filtering for Unresolved Comments + +The key filter is `select(.isResolved == false)` which ensures only unresolved review threads are processed. Each thread can contain multiple comments, but if the thread is resolved, all its comments should be ignored. + +### Working with Review Comments + +1. **Fetch unresolved comments** using the GraphQL query above +2. **Parse the results** to identify: + - File path (`path`) + - Line number (`line` or `originalLine`) + - Comment text (`bodyText`) + - Author (`author.login`) +3. **Address each unresolved comment** by: + - Locating the relevant code section + - Making the requested changes + - Ensuring the fix addresses the concern raised +4. **Do NOT process resolved comments** - they have already been handled + +### Example: Compact List of Unresolved Comments + +For a quick overview of unresolved comments: ```bash gh api graphql -F owner=cozystack -F repo=cozystack -F pr= -f query=' @@ -186,3 +233,43 @@ query($owner: String!, $repo: String!, $pr: Int!) { } }' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | .comments.nodes[] | "\(.path):\(.line // "N/A") - \(.author.login): \(.bodyText[:150])"' ``` + +### Important Notes + +- **REST API limitation**: The REST endpoint `/pulls/{pr}/reviews` returns review summaries, not individual review comments. Use GraphQL API for accessing `reviewThreads` with `isResolved` status. +- **Thread-based resolution**: Comments are organized in threads. If a thread is resolved (`isResolved: true`), ignore all comments in that thread. +- **Always filter**: Never process comments from resolved threads, even if they appear in the results. + +### Example Workflow + +```bash +# Get PR comments +gh pr view 1234 --comments + +# Review comments and identify valid ones +# Make necessary changes to address valid comments +# ... edit files ... + +# Show what was changed (but don't commit) +git status +git diff + +# Tell the user what was fixed and what was skipped +``` + +## Git Permissions + +Request these permissions when needed: +- `git_write` - For commit, rebase, cherry-pick, branch operations +- `network` - For push, fetch, pull operations + +## Common Issues + +**PR has extra commits?** +→ Rebase on `upstream/main` and cherry-pick only your commits + +**Wrong commit message?** +→ `git commit --amend --signoff -m "[correct] message"` then `git push -f` + +**Need to update PR?** +→ `gh pr edit --body "new description"` diff --git a/docs/agents/overview.md b/docs/agents/overview.md index ae0fd1c4..b6d69e68 100644 --- a/docs/agents/overview.md +++ b/docs/agents/overview.md @@ -78,18 +78,11 @@ packages/// - Add proper error handling and structured logging ### Git Commits -- Follow [Conventional Commits](https://www.conventionalcommits.org/) format: `type(scope): description` +- Use format: `[component] Description` - Always use `--signoff` flag - Reference PR numbers when available - Keep commits atomic and focused - -### PackageSource CRD upgrade policy - -Each component in a `PackageSource` may set `install.upgradeCRDs` to control how CRDs from the chart's `crds/` directory are handled on `HelmRelease` upgrades. Allowed values: `Skip` (default — helm-controller does not touch CRDs on upgrade), `Create` (create new CRDs only), `CreateReplace` (create new and overwrite existing). - -Set `upgradeCRDs: CreateReplace` for operators whose upstream regularly adds new CRDs between versions (etcd-operator, cnpg, kubevirt, kamaji). Without it, new CRDs from a chart bump do not land on existing clusters — only fresh installs get them. - -Do **not** set `CreateReplace` blindly: it overwrites every CRD in `crds/` and can cause silent data loss if upstream drops a field from a CRD that has live objects. Only enable it for operators whose schema evolution is additive-only. When in doubt, leave it unset and apply new CRDs manually. +- Follow conventional commit format for changelogs ### Documentation diff --git a/docs/changelogs/v0.40.5.md b/docs/changelogs/v0.40.5.md deleted file mode 100644 index 40ebd107..00000000 --- a/docs/changelogs/v0.40.5.md +++ /dev/null @@ -1,15 +0,0 @@ - - -## Improvements - -* **[dashboard] Improve dashboard session params**: Improved session parameter handling in the dashboard for better user experience and more reliable session management ([**@lllamnyp**](https://github.com/lllamnyp) in #1913, #1919). - -## Dependencies - -* **Update cozyhr to v1.6.1**: Updated cozyhr to v1.6.1, which fixes a critical bug causing helm-controller v0.37.0+ to unexpectedly uninstall HelmReleases after cozyhr apply by correcting history snapshot fields for helm-controller compatibility ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr#10). - ---- - -**Full Changelog**: [v0.40.4...v0.40.5](https://github.com/cozystack/cozystack/compare/v0.40.4...v0.40.5) diff --git a/docs/changelogs/v0.40.6.md b/docs/changelogs/v0.40.6.md deleted file mode 100644 index 40e499f5..00000000 --- a/docs/changelogs/v0.40.6.md +++ /dev/null @@ -1,11 +0,0 @@ - - -## Fixes - -* **[kubernetes] Fix manifests for kubernetes deployment**: Fixed incorrect manifests that prevented proper Kubernetes deployment, restoring correct application behavior ([**@IvanHunters**](https://github.com/IvanHunters) in #1943, #1944). - ---- - -**Full Changelog**: [v0.40.5...v0.40.6](https://github.com/cozystack/cozystack/compare/v0.40.5...v0.40.6) diff --git a/docs/changelogs/v0.40.7.md b/docs/changelogs/v0.40.7.md deleted file mode 100644 index f1b7a52e..00000000 --- a/docs/changelogs/v0.40.7.md +++ /dev/null @@ -1,11 +0,0 @@ - - -## Security - -* **[dashboard] Verify JWT token**: Added JWT token verification to the dashboard, ensuring that authentication tokens are properly validated before granting access. This prevents unauthorized access through forged or expired tokens ([**@lllamnyp**](https://github.com/lllamnyp) in #1980, #1984). - ---- - -**Full Changelog**: [v0.40.6...v0.40.7](https://github.com/cozystack/cozystack/compare/v0.40.6...v0.40.7) diff --git a/docs/changelogs/v0.41.4.md b/docs/changelogs/v0.41.4.md deleted file mode 100644 index 70f1daeb..00000000 --- a/docs/changelogs/v0.41.4.md +++ /dev/null @@ -1,11 +0,0 @@ - - -## Dependencies - -* **Update cozyhr to v1.6.1**: Updated cozyhr to v1.6.1, which fixes a critical bug causing helm-controller v0.37.0+ to unexpectedly uninstall HelmReleases after cozyhr apply by correcting history snapshot fields for helm-controller compatibility ([**@kvaps**](https://github.com/kvaps) in cozystack/cozyhr#10). - ---- - -**Full Changelog**: [v0.41.3...v0.41.4](https://github.com/cozystack/cozystack/compare/v0.41.3...v0.41.4) diff --git a/docs/changelogs/v0.41.5.md b/docs/changelogs/v0.41.5.md deleted file mode 100644 index fb96fcf4..00000000 --- a/docs/changelogs/v0.41.5.md +++ /dev/null @@ -1,21 +0,0 @@ - - -## Features and Improvements - -* **[dashboard] Add "Edit" button to all resources**: Added an "Edit" button across all resource views in the dashboard, allowing users to modify resource configurations directly from the UI ([**@sircthulhu**](https://github.com/sircthulhu) in #1928, #1931). - -* **[dashboard] Add resource quota usage to tenant details page**: Added resource quota usage display to the tenant details page, giving administrators visibility into how much of allocated resources each tenant is consuming ([**@sircthulhu**](https://github.com/sircthulhu) in #1929, #1932). - -* **[branding] Separate values for keycloak**: Separated Keycloak branding values into dedicated configuration, allowing more granular customization of Keycloak appearance without affecting other branding settings ([**@nbykov0**](https://github.com/nbykov0) in #1946). - -* **Add instance profile label to workload monitor**: Added instance profile metadata labels to the workload monitor, enabling better resource tracking and monitoring by instance profile type ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1954, #1957). - -## Fixes - -* **[kubernetes] Fix manifests for kubernetes deployment**: Fixed incorrect manifests that prevented proper Kubernetes deployment, restoring correct application behavior ([**@IvanHunters**](https://github.com/IvanHunters) in #1943, #1945). - ---- - -**Full Changelog**: [v0.41.4...v0.41.5](https://github.com/cozystack/cozystack/compare/v0.41.4...v0.41.5) diff --git a/docs/changelogs/v0.41.6.md b/docs/changelogs/v0.41.6.md deleted file mode 100644 index 8e7783df..00000000 --- a/docs/changelogs/v0.41.6.md +++ /dev/null @@ -1,17 +0,0 @@ - - -## Improvements - -* **[vm] Allow changing field external after creation**: Users can now modify the external network field on virtual machines after initial creation, providing more flexibility in VM networking configuration without requiring recreation ([**@sircthulhu**](https://github.com/sircthulhu) in #1956, #1962). - -* **[branding] Separate values for keycloak**: Separated Keycloak branding values into dedicated configuration for more granular customization of Keycloak appearance ([**@nbykov0**](https://github.com/nbykov0) in #1947, #1963). - -## Fixes - -* **[kubernetes] Fix coredns serviceaccount to match kubernetes bootstrap RBAC**: Configured the CoreDNS chart to create a `kube-dns` ServiceAccount matching the Kubernetes bootstrap ClusterRoleBinding, fixing RBAC errors (`Failed to watch`) when CoreDNS pods restart ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1958, #1978). - ---- - -**Full Changelog**: [v0.41.5...v0.41.6](https://github.com/cozystack/cozystack/compare/v0.41.5...v0.41.6) diff --git a/docs/changelogs/v0.41.7.md b/docs/changelogs/v0.41.7.md deleted file mode 100644 index 5a77664d..00000000 --- a/docs/changelogs/v0.41.7.md +++ /dev/null @@ -1,15 +0,0 @@ - - -## Security - -* **[dashboard] Verify JWT token**: Added JWT token verification to the dashboard, ensuring that authentication tokens are properly validated before granting access. This prevents unauthorized access through forged or expired tokens ([**@lllamnyp**](https://github.com/lllamnyp) in #1980, #1983). - -## Fixes - -* **[postgres-operator] Correct PromQL syntax in CNPGClusterOffline alert**: Fixed incorrect PromQL syntax in the `CNPGClusterOffline` alert rule for CloudNativePG, ensuring the alert fires correctly when all instances of a PostgreSQL cluster are offline ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1981, #1989). - ---- - -**Full Changelog**: [v0.41.6...v0.41.7](https://github.com/cozystack/cozystack/compare/v0.41.6...v0.41.7) diff --git a/docs/changelogs/v0.41.8.md b/docs/changelogs/v0.41.8.md deleted file mode 100644 index 9984c87d..00000000 --- a/docs/changelogs/v0.41.8.md +++ /dev/null @@ -1,17 +0,0 @@ - - -## Features and Improvements - -* **[kubernetes] Auto-enable Gateway API support in cert-manager**: cert-manager now automatically enables `enableGatewayAPI` when the Gateway API addon is active in the Kubernetes application. Users no longer need to manually configure this setting, and the option can still be overridden via `valuesOverride` ([**@kvaps**](https://github.com/kvaps) in #1997, #2012). - -* **[vm] Allow switching between instancetype and custom resources**: Users can now switch virtual machines between instancetype-based and custom resource configurations after creation. The upgrade hook atomically patches VM resources, providing more flexibility in adjusting VM sizing without recreation ([**@sircthulhu**](https://github.com/sircthulhu) in #2008, #2013). - -## Fixes - -* **[dashboard] Add startupProbe to prevent container restarts on slow hardware**: Added `startupProbe` to both `bff` and `web` containers in the dashboard deployment. On slow hardware, kubelet was killing containers because the `livenessProbe` only allowed ~33 seconds for startup. The `startupProbe` gives containers up to 60 seconds to start before `livenessProbe` kicks in ([**@kvaps**](https://github.com/kvaps) in #1996, #2014). - ---- - -**Full Changelog**: [v0.41.7...v0.41.8](https://github.com/cozystack/cozystack/compare/v0.41.7...v0.41.8) diff --git a/docs/changelogs/v0.41.9.md b/docs/changelogs/v0.41.9.md deleted file mode 100644 index d0cd3ff9..00000000 --- a/docs/changelogs/v0.41.9.md +++ /dev/null @@ -1,15 +0,0 @@ - - -## Fixes - -* **[cozystack-basics] Deny resourcequotas deletion for tenant admin**: Prevented tenant administrators from deleting resource quotas, ensuring that resource limits set by platform administrators cannot be bypassed by tenant-level users ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2076). - -## Dependencies - -* **Update Kube-OVN to v1.15.3**: Updated Kube-OVN CNI to v1.15.3 with latest bug fixes and improvements ([**@kvaps**](https://github.com/kvaps)). - ---- - -**Full Changelog**: [v0.41.8...v0.41.9](https://github.com/cozystack/cozystack/compare/v0.41.8...v0.41.9) diff --git a/docs/changelogs/v1.0.0-beta.3.md b/docs/changelogs/v1.0.0-beta.3.md deleted file mode 100644 index 45d654a7..00000000 --- a/docs/changelogs/v1.0.0-beta.3.md +++ /dev/null @@ -1,144 +0,0 @@ - - -> **⚠️ Beta Release Warning**: This is a pre-release version intended for testing and early adoption. Breaking changes may occur before the stable v1.0.0 release. - -## Major Features and Improvements - -### New Applications - -* **[qdrant] Add Qdrant vector database application**: Added Qdrant as a new managed application, providing a high-performance vector database for AI and machine learning workloads. Supports single replica or clustered mode, persistent storage, resource presets, API key authentication, and optional external LoadBalancer access ([**@lexfrei**](https://github.com/lexfrei) in #1987). - -### System Components - -* **[system] Add cluster-autoscaler package for Hetzner and Azure**: Added cluster-autoscaler system package with support for multiple cloud providers (Hetzner and Azure) to automatically scale management cluster nodes. Includes comprehensive documentation for Hetzner setup with Talos Linux, vSwitch configuration, and Kilo mesh networking integration ([**@kvaps**](https://github.com/kvaps) in #1964). - -* **[system] Add clustersecret-operator package**: Added clustersecret-operator system package for managing secrets across multiple namespaces in Kubernetes clusters ([**@sircthulhu**](https://github.com/sircthulhu) in #2025). - -### Networking - -* **[kilo] Update to v0.7.0 and add configurable MTU**: Updated Kilo WireGuard mesh networking to v0.7.0 from cozystack fork with pre-built images. Added configurable MTU parameter (default: auto) for WireGuard interface, allowing automatic MTU detection or manual override ([**@kvaps**](https://github.com/kvaps) in #2003). - -* **[local-ccm] Add node-lifecycle-controller component**: Added optional node-lifecycle-controller to local-ccm package that automatically deletes unreachable NotReady nodes from the cluster. Solves the "zombie" node problem when cluster autoscaler deletes cloud instances but node objects remain in Kubernetes. Supports configurable node selectors, protected labels, and HA deployment with leader election ([**@IvanHunters**](https://github.com/IvanHunters) in #1992). - -### Virtual Machines - -* **[vm] Add cpuModel field to specify CPU model without instanceType**: Added cpuModel field to VirtualMachine API, allowing users to specify CPU model directly without using instanceType, providing more granular control over VM CPU configuration ([**@sircthulhu**](https://github.com/sircthulhu) in #2007). - -* **[vm] Allow switching between instancetype and custom resources**: Implemented atomic upgrade hook that allows switching between instanceType-based and custom resource-based VM configuration, providing more flexibility in VM resource management ([**@sircthulhu**](https://github.com/sircthulhu) in #2008). - -* **[vm] Migrate to runStrategy instead of running**: Migrated VirtualMachine API from deprecated `running` field to `runStrategy` field, following KubeVirt upstream best practices ([**@sircthulhu**](https://github.com/sircthulhu) in #2004). - -### Backups - -* **[backups] Add comprehensive backup and restore functionality**: Major update to backup system including BackupClass for Velero, virtual machine backup strategies, RestoreJob resource with end-to-end restore workflows, Velero integration with polling and status tracking, and enhanced backup plans UI with simplified Plan/BackupJob API ([**@androndo**](https://github.com/androndo) in #1967, [**@lllamnyp**](https://github.com/lllamnyp) in #1968). - -* **[backups] Add kubevirt plugin to velero**: Added KubeVirt plugin to Velero for proper virtual machine backup support, enabling consistent snapshots of VM state and data ([**@lllamnyp**](https://github.com/lllamnyp) in #2017). - -* **[backups] Install backupstrategy controller by default**: Enabled backupstrategy controller by default to provide automatic backup scheduling and management for managed applications ([**@lllamnyp**](https://github.com/lllamnyp) in #2020). - -* **[backups] Better selectors for VM strategy**: Improved VM backup strategy selectors for more accurate and reliable backup targeting ([**@lllamnyp**](https://github.com/lllamnyp) in #2023). - -### Platform - -* **[kubernetes] Auto-enable Gateway API support in cert-manager**: Added automatic Gateway API support in cert-manager for tenant Kubernetes clusters, enabling automatic certificate management for Gateway API resources ([**@kvaps**](https://github.com/kvaps) in #1997). - -* **[tenant,rbac] Use shared clusterroles**: Refactored tenant RBAC to use shared ClusterRoles, improving maintainability and consistency across tenant namespaces ([**@lllamnyp**](https://github.com/lllamnyp) in #1999). - -* **[mongodb] Unify users and databases configuration**: Simplified MongoDB user and database configuration with a more unified API structure ([**@kvaps**](https://github.com/kvaps) in #1923). - -## Improvements - -* **[keycloak-configure,dashboard] Enable insecure TLS verification by default**: Made SSL certificate verification configurable with insecure mode enabled by default for easier local development and testing ([**@IvanHunters**](https://github.com/IvanHunters) in #2005). - -* **[dashboard] Add startupProbe to prevent container restarts on slow hardware**: Added startup probe to dashboard pods to prevent unnecessary container restarts on slow hardware or during high load ([**@kvaps**](https://github.com/kvaps) in #1996). - -* **[cilium] Change cilium-operator replicas to 1**: Reduced Cilium operator replicas from 2 to 1 to decrease resource consumption in smaller deployments ([**@IvanHunters**](https://github.com/IvanHunters) in #1784). - -* **[monitoring] Enable monitoring for core components**: Enhanced monitoring capabilities with better dashboards and metrics collection for core Cozystack components ([**@IvanHunters**](https://github.com/IvanHunters) in #1937). - -* **[branding] Separate values for Keycloak**: Separated Keycloak branding values for better customization capabilities ([**@nbykov0**](https://github.com/nbykov0) in #1947). - -* **[kubernetes] Use ingress-nginx nodeport service**: Changed Kubernetes managed clusters to use ingress-nginx NodePort service for improved compatibility and flexibility ([**@sircthulhu**](https://github.com/sircthulhu) in #1948). - -## Fixes - -* **[linstor] Extract piraeus-operator CRDs into separate package**: Fixed issue where Helm did not reliably install all CRDs from large crds.yaml files by creating dedicated piraeus-operator-crds package. This ensures the linstorsatellites.io CRD is properly installed, preventing satellite pod creation failures ([**@IvanHunters**](https://github.com/IvanHunters) in #1991). - -* **[platform] Fix cozystack-values secret race condition**: Fixed race condition in cozystack-values secret creation that could cause platform initialization failures ([**@lllamnyp**](https://github.com/lllamnyp) in #2024). - -* **[seaweedfs] Increase certificate duration to 10 years**: Increased SeaweedFS certificate validity from 1 year to 10 years to reduce certificate rotation overhead and prevent unexpected certificate expiration issues ([**@IvanHunters**](https://github.com/IvanHunters) in #1986). - -* **[monitoring] Remove cozystack-controller dependency**: Fixed monitoring package to remove unnecessary dependency on cozystack-controller, allowing monitoring to be installed independently ([**@IvanHunters**](https://github.com/IvanHunters) in #1990). - -* **[monitoring] Remove duplicate dashboards.list from extra/monitoring**: Fixed duplicate dashboards.list configuration in extra/monitoring package ([**@IvanHunters**](https://github.com/IvanHunters) in #2016). - -* **[mongodb] Fix pre-commit check**: Fixed pre-commit linting issues in MongoDB package ([**@kvaps**](https://github.com/kvaps) in #1753). - -* **[mongodb] Update MongoDB logo**: Updated MongoDB application logo in the dashboard to use the correct branding ([**@kvaps**](https://github.com/kvaps) in #2027). - -* **[bootbox] Auto-create bootbox-application as dependency**: Fixed bootbox package to automatically create required bootbox-application dependency ([**@kvaps**](https://github.com/kvaps) in #1974). - -* **[migrations] Add migration 25 for v1.0 upgrade cleanup**: Added migration script to handle cleanup during v1.0 upgrade path ([**@kvaps**](https://github.com/kvaps) in #1975). - -* **[build] Fix platform migrations image build**: Fixed Docker image build process for platform migrations ([**@kvaps**](https://github.com/kvaps) in #1976). - -* **[postgres-operator] Correct PromQL syntax in CNPGClusterOffline alert**: Fixed incorrect PromQL syntax in CNPGClusterOffline Prometheus alert for PostgreSQL clusters ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1981). - -* **[coredns] Fix serviceaccount to match kubernetes bootstrap RBAC**: Fixed CoreDNS service account configuration to correctly match Kubernetes bootstrap RBAC requirements ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1958). - -* **[dashboard] Verify JWT token**: Added JWT token verification to dashboard for improved security ([**@lllamnyp**](https://github.com/lllamnyp) in #1980). - -* **[talm] Skip config loading for completion subcommands**: Fixed talm CLI to skip unnecessary config loading for shell completion commands ([**@kitsunoff**](https://github.com/kitsunoff) in [cozystack/talm#109](https://github.com/cozystack/talm/pull/109)). - -## Dependencies - -* **[kube-ovn] Update Kube-OVN to v1.15.3**: Updated Kube-OVN CNI to v1.15.3 with performance improvements and bug fixes ([**@kvaps**](https://github.com/kvaps) in #2022). - -* **[local-ccm] Update to v0.3.0**: Updated local cloud controller manager to v0.3.0 with node-lifecycle-controller support ([**@kvaps**](https://github.com/kvaps) in #1992). - -* **[kilo] Update to v0.7.0**: Updated Kilo to v0.7.0 from cozystack fork with improved MTU handling ([**@kvaps**](https://github.com/kvaps) in #2003). - -## Development, Testing, and CI/CD - -* **[ci] Use GitHub Copilot CLI for changelog generation**: Automated changelog generation using GitHub Copilot CLI to improve release process efficiency ([**@androndo**](https://github.com/androndo) in #1753). - -* **[ci] Choose runner conditional on label**: Added conditional runner selection in CI based on PR labels for more flexible CI/CD workflows ([**@lllamnyp**](https://github.com/lllamnyp) in #1998). - -* **[backups] Add restore jobs controller**: Added controller for managing backup restore jobs ([**@androndo**](https://github.com/androndo) in #1811). - -* **Update CODEOWNERS**: Updated CODEOWNERS file to include new maintainers ([**@lllamnyp**](https://github.com/lllamnyp) in #1972, [**@IvanHunters**](https://github.com/IvanHunters) in #2015). - -## Documentation - -* **[website] Add LINSTOR disk preparation guide**: Added comprehensive documentation for preparing disks for LINSTOR storage system ([**@IvanHunters**](https://github.com/IvanHunters) in [cozystack/website#411](https://github.com/cozystack/website/pull/411)). - -* **[website] Add Proxmox VM migration guide**: Added detailed guide for migrating virtual machines from Proxmox to Cozystack ([**@IvanHunters**](https://github.com/IvanHunters) in [cozystack/website#410](https://github.com/cozystack/website/pull/410)). - -* **[website] Describe operator-based and HelmRelease-based package patterns**: Added development documentation explaining operator-based and HelmRelease-based package patterns for Cozystack ([**@kvaps**](https://github.com/kvaps) in [cozystack/website#413](https://github.com/cozystack/website/pull/413)). - -* **[website] Correct typo in kubeconfig reference in Kubernetes installation guide**: Fixed documentation typo in kubeconfig reference ([**@shkarface**](https://github.com/shkarface) in [cozystack/website#414](https://github.com/cozystack/website/pull/414)). - -* **[website] Check quotas before an upgrade**: Added troubleshooting documentation for checking resource quotas before performing upgrades ([**@nbykov0**](https://github.com/nbykov0) in [cozystack/website#405](https://github.com/cozystack/website/pull/405)). - ---- - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@androndo**](https://github.com/androndo) -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@lllamnyp**](https://github.com/lllamnyp) -* [**@mattia-eleuteri**](https://github.com/mattia-eleuteri) -* [**@nbykov0**](https://github.com/nbykov0) -* [**@shkarface**](https://github.com/shkarface) -* [**@sircthulhu**](https://github.com/sircthulhu) - ---- - -**Full Changelog**: [v1.0.0-beta.2...v1.0.0-beta.3](https://github.com/cozystack/cozystack/compare/v1.0.0-beta.2...v1.0.0-beta.3) diff --git a/docs/changelogs/v1.0.0-beta.4.md b/docs/changelogs/v1.0.0-beta.4.md deleted file mode 100644 index c5694a73..00000000 --- a/docs/changelogs/v1.0.0-beta.4.md +++ /dev/null @@ -1,96 +0,0 @@ - - -> **⚠️ Beta Release Warning**: This is a pre-release version intended for testing and early adoption. Breaking changes may occur before the stable v1.0.0 release. - -## Major Features and Improvements - -### Virtual Machines - -* **[vm-instance] Complete migration from virtual-machine to vm-disk and vm-instance**: Completed the architectural redesign of virtual machine management by fully migrating from the legacy `virtual-machine` application to the new `vm-disk` and `vm-instance` applications. This includes automatic migration scripts (migration 28) that convert existing virtual machines, handle CDI webhook configurations, and update cloud-init references. The new architecture provides better separation of concerns between disk management and VM lifecycle, enabling more flexible VM configuration and improved resource management ([**@kvaps**](https://github.com/kvaps) in #2040). - -* **[vm-instance] Port advanced VM features**: Ported critical VM features from the legacy virtual-machine application including cpuModel field for direct CPU model specification, support for switching between instanceType and custom resource configurations, and migration from deprecated `running` field to `runStrategy` field following KubeVirt best practices ([**@kvaps**](https://github.com/kvaps) in #2040). - -### Storage and CSI - -* **[kubevirt-csi-driver] Add RWX Filesystem (NFS) support**: Added Read-Write-Many (RWX) filesystem support to kubevirt-csi-driver, enabling multiple pods to mount the same persistent volume simultaneously via NFS. This provides native NFS support for shared storage use cases without requiring external NFS provisioners, with automatic NFS server deployment per PVC and seamless integration with KubeVirt's storage layer ([**@kvaps**](https://github.com/kvaps) in #2042). - -### Platform and Infrastructure - -* **[cozystack-api] Switch from DaemonSet to Deployment**: Migrated cozystack-api from DaemonSet to Deployment with PreferClose topology spread constraints, improving resource efficiency while maintaining high availability. The Deployment approach reduces resource consumption compared to running API pods on every node, while topology spreading ensures resilient pod placement across the cluster ([**@kvaps**](https://github.com/kvaps) in #2041, #2048). - -* **[linstor] Move CRDs installation to dedicated chart**: Refactored LINSTOR CRDs installation by moving them to a dedicated `piraeus-operator-crds` chart, solving Helm's limitation with large CRD files that could cause unreliable installations. This ensures all LINSTOR CRDs (including linstorsatellites.io) are properly installed before the operator starts, preventing satellite pod creation failures. Includes automatic migration script to reassign existing CRDs to the new chart ([**@kvaps**](https://github.com/kvaps) in #2036). - -* **[installer] Unify operator templates**: Merged separate operator templates into a single variant-based template, simplifying the installation process and reducing configuration duplication. The new template supports different deployment variants (Talos, non-Talos) through a unified configuration approach ([**@kvaps**](https://github.com/kvaps) in #2034). - -### Applications - -* **[mariadb] Rename mysql application to mariadb**: Renamed the MySQL application to MariaDB to accurately reflect the underlying database engine being used. Includes automatic migration script (migration 27) that handles resource renaming and ensures seamless upgrade path for existing MySQL deployments. All resources, including databases, users, backups, and configurations, are automatically migrated to use the mariadb naming ([**@kvaps**](https://github.com/kvaps) in #2026). - -* **[ferretdb] Remove FerretDB application**: Removed the FerretDB application from the catalog as it has been superseded by native MongoDB support with improved performance and features ([**@kvaps**](https://github.com/kvaps) in #2028). - -## Improvements - -* **[rbac] Use hierarchical naming scheme**: Refactored RBAC configuration to use hierarchical naming scheme for cluster roles and role bindings, improving organization and maintainability of permission structures across the platform ([**@lllamnyp**](https://github.com/lllamnyp) in #2019). - -* **[backups] Create RBAC for backup resources**: Added comprehensive RBAC configuration for backup resources, enabling proper permission management for backup operations and restore jobs across different user roles ([**@lllamnyp**](https://github.com/lllamnyp) in #2018). - -* **[etcd-operator] Add vertical-pod-autoscaler dependency**: Added vertical-pod-autoscaler as a dependency to etcd-operator package, ensuring proper resource scaling and optimization for etcd clusters ([**@sircthulhu**](https://github.com/sircthulhu) in #2047). - -## Fixes - -* **[cozystack-operator] Preserve existing suspend field in package reconciler**: Fixed package reconciler to properly preserve the existing suspend field state during reconciliation, preventing unintended resumption of suspended packages ([**@sircthulhu**](https://github.com/sircthulhu) in #2043). - -* **[cozystack-operator] Fix namespace privileged flag resolution**: Fixed operator to correctly resolve namespace privileged flag by checking all Packages in the namespace, not just the first one. This ensures namespaces are properly marked as privileged when any package requires elevated permissions ([**@kvaps**](https://github.com/kvaps) in #2046). - -* **[cozystack-operator] Fix namespace reconciliation field ownership**: Fixed Server-Side Apply (SSA) field ownership conflicts by using per-Package field owner for namespace reconciliation, preventing conflicts when multiple packages reconcile the same namespace ([**@kvaps**](https://github.com/kvaps) in #2046). - -* **[platform] Clean up Helm secrets for removed releases**: Added cleanup logic to migration 23 to remove orphaned Helm secrets from removed -rd releases, preventing secret accumulation and reducing cluster resource usage ([**@kvaps**](https://github.com/kvaps) in #2035). - -* **[monitoring] Fix YAML parse error in vmagent template**: Fixed YAML parsing error in monitoring-agents vmagent template that could cause monitoring stack deployment failures ([**@kvaps**](https://github.com/kvaps) in #2037). - -* **[talm] Fix metadata.id type casting in physical_links_info**: Fixed Prometheus query in physical_links_info chart to properly cast metadata.id to string for regexMatch operations, preventing query failures with numeric interface IDs ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#110). - -## Dependencies - -* **[kilo] Update to v0.7.1**: Updated Kilo WireGuard mesh networking to v0.7.1 with bug fixes and improvements ([**@kvaps**](https://github.com/kvaps) in #2049). - -## Development, Testing, and CI/CD - -* **[ci] Improve cozyreport functionality**: Enhanced cozyreport tool with improved reporting capabilities for CI/CD pipelines, providing better visibility into test results and build status ([**@lllamnyp**](https://github.com/lllamnyp) in #2032). - -* **[e2e] Increase HelmRelease readiness timeout for kubernetes test**: Increased HelmRelease readiness timeout in Kubernetes end-to-end tests to prevent false failures on slower hardware or during high load conditions, specifically targeting ingress-nginx component which may take longer to become ready ([**@lexfrei**](https://github.com/lexfrei) in #2033). - -## Documentation - -* **[website] Add documentation versioning**: Implemented comprehensive documentation versioning system with separate v0 and v1 documentation trees, version selector in the UI, proper URL redirects for unversioned docs, and improved navigation for users working with different Cozystack versions ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#415). - -* **[website] Describe upgrade to v1.0**: Added detailed upgrade instructions for migrating from v0.x to v1.0, including prerequisites, upgrade steps, and troubleshooting guidance ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website@21bbe84). - -* **[website] Update support documentation**: Updated support documentation with current contact information and support channels ([**@xrmtech-isk**](https://github.com/xrmtech-isk) in cozystack/website#420). - ---- - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@IvanStukov**](https://github.com/IvanStukov) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@lllamnyp**](https://github.com/lllamnyp) -* [**@nbykov0**](https://github.com/nbykov0) -* [**@sircthulhu**](https://github.com/sircthulhu) -* [**@xrmtech-isk**](https://github.com/xrmtech-isk) - -### New Contributors - -We're excited to welcome our first-time contributors: - -* [**@IvanStukov**](https://github.com/IvanStukov) - First contribution! -* [**@xrmtech-isk**](https://github.com/xrmtech-isk) - First contribution! - ---- - -**Full Changelog**: [v1.0.0-beta.3...v1.0.0-beta.4](https://github.com/cozystack/cozystack/compare/v1.0.0-beta.3...v1.0.0-beta.4) diff --git a/docs/changelogs/v1.0.0-beta.5.md b/docs/changelogs/v1.0.0-beta.5.md deleted file mode 100644 index b8bc306c..00000000 --- a/docs/changelogs/v1.0.0-beta.5.md +++ /dev/null @@ -1,36 +0,0 @@ - - -> **⚠️ Beta Release Warning**: This is a pre-release version intended for testing and early adoption. Breaking changes may occur before the stable v1.0.0 release. - -## Features and Improvements - -* **[installer] Add variant-aware templates for generic Kubernetes support**: Extended the installer chart to support generic and hosted Kubernetes deployments via the existing `cozystackOperator.variant` parameter. When using `variant=generic`, the installer now renders separate templates for the Cozystack operator, skipping Talos-specific components. This enables users to deploy Cozystack on standard Kubernetes distributions and hosted Kubernetes services, expanding platform compatibility beyond Talos Linux ([**@lexfrei**](https://github.com/lexfrei) in #2010). - -* **[kilo] Add Cilium compatibility variant**: Added a new `cilium` variant to the kilo PackageSource that deploys kilo with the `--compatibility=cilium` flag. This enables Cilium-aware IPIP encapsulation where the outer packet IP matches the inner packet source, allowing Cilium's network policies to function correctly with kilo's WireGuard mesh networking. Users can now run kilo alongside Cilium CNI while maintaining full network policy enforcement capabilities ([**@kvaps**](https://github.com/kvaps) in #2055). - -* **[cluster-autoscaler] Enable enforce-node-group-min-size by default**: Enabled the `enforce-node-group-min-size` option for the system cluster-autoscaler chart. This ensures node groups are always scaled up to their configured minimum size, even when current workload demands are lower, preventing unexpected scale-down below minimum thresholds and improving cluster stability for production workloads ([**@kvaps**](https://github.com/kvaps) in #2050). - -* **[dashboard] Upgrade dashboard to version 1.4.0**: Updated the Cozystack dashboard to version 1.4.0 with new features and improvements for better user experience and cluster management capabilities ([**@sircthulhu**](https://github.com/sircthulhu) in #2051). - -## Breaking Changes & Upgrade Notes - -* **[vpc] Migrate subnets definition from map to array format**: Migrated VPC subnets definition from map format (`map[string]Subnet`) to array format (`[]Subnet`) with an explicit `name` field. This aligns VPC subnet definitions with the vm-instance `networks` field pattern and provides more intuitive configuration. Existing VPC deployments are automatically migrated via migration 30, which converts the subnet map to an array while preserving all existing subnet configurations and network connectivity ([**@kvaps**](https://github.com/kvaps) in #2052). - -## Dependencies - -* **[kilo] Update to v0.8.0**: Updated Kilo WireGuard mesh networking to v0.8.0 with performance improvements, bug fixes, and new compatibility features ([**@kvaps**](https://github.com/kvaps) in #2053). - -* **[talm] Skip config loading for __complete command**: Fixed CLI completion behavior by skipping config loading for the `__complete` command, preventing errors during shell completion when configuration files are not available or misconfigured ([**@kitsunoff**](https://github.com/kitsunoff) in cozystack/talm#109). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@sircthulhu**](https://github.com/sircthulhu) - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0-beta.4...v1.0.0-beta.5 diff --git a/docs/changelogs/v1.0.0-beta.6.md b/docs/changelogs/v1.0.0-beta.6.md deleted file mode 100644 index 99e565d7..00000000 --- a/docs/changelogs/v1.0.0-beta.6.md +++ /dev/null @@ -1,46 +0,0 @@ - - -> **⚠️ Beta Release Warning**: This is a pre-release version intended for testing and early adoption. Breaking changes may occur before the stable v1.0.0 release. - -## Features and Improvements - -* **[platform] Add cilium-kilo networking variant**: Added a new `cilium-kilo` networking variant that combines Cilium CNI with Kilo WireGuard mesh overlay. This variant enables `enable-ipip-termination` in Cilium for proper IPIP packet handling and deploys Kilo with `--compatibility=cilium` flag. Users can now select `cilium-kilo` as their networking variant during platform setup, simplifying the multi-location WireGuard setup compared to manually combining Cilium and standalone Kilo ([**@kvaps**](https://github.com/kvaps) in #2064). - -* **[nats] Add monitoring**: Added Grafana dashboards for NATS JetStream and server metrics monitoring, along with Prometheus monitoring support with TLS-aware endpoint configuration. Includes updated image customization options (digest and full image name) and component version upgrades for the NATS exporter and utilities. Users now have full observability into NATS message broker performance and health ([**@klinch0**](https://github.com/klinch0) in #1381). - -* **[platform] Add DNS-1035 validation for Application names**: Added dynamic DNS-1035 label validation for Application names in the Cozystack API, using `IsDNS1035Label` from `k8s.io/apimachinery`. Validation is performed at creation time and accounts for the root host length to prevent names that would exceed Kubernetes resource naming limits. This prevents creation of resources with invalid names that would fail downstream Kubernetes resource creation ([**@lexfrei**](https://github.com/lexfrei) in #1771). - -* **[operator] Add automatic CRD installation at startup**: Added `--install-crds` flag to the Cozystack operator that installs embedded CRD manifests at startup, ensuring CRDs exist before the operator begins reconciliation. CRD manifests are now embedded in the operator binary and verified for consistency with the Helm `crds/` directory via a new CI Makefile check. This eliminates ordering issues during initial cluster setup where CRDs might not yet be present ([**@lexfrei**](https://github.com/lexfrei) in #2060). - -## Fixes - -* **[platform] Adopt tenant-root into cozystack-basics during migration**: Added migration 31 to adopt existing `tenant-root` Namespace and HelmRelease into the `cozystack-basics` Helm release when upgrading from v0.41.x to v1.0. Previously these resources were applied via `kubectl apply` with no Helm release tracking, causing Helm to treat them as foreign resources and potentially delete them during reconciliation. This migration ensures a safe upgrade path by annotating and labeling these resources for Helm adoption ([**@kvaps**](https://github.com/kvaps) in #2065). - -* **[platform] Preserve tenant-root HelmRelease during migration**: Fixed a data-loss risk during migration from v0.41.x to v1.0.0-beta where the `tenant-root` HelmRelease (and the namespace it manages) could be deleted, causing tenant service outages. Added safety annotation to the HelmRelease and lookup logic to preserve current parameters during migration, preventing unwanted deletion of tenant-root resources ([**@sircthulhu**](https://github.com/sircthulhu) in #2063). - -* **[codegen] Add gen_client to update-codegen.sh and regenerate applyconfiguration**: Fixed a build error in `pkg/generated/applyconfiguration/utils.go` caused by a reference to `testing.TypeConverter` which was removed in client-go v0.34.1. The root cause was that `hack/update-codegen.sh` never called `gen_client`, leaving the generated applyconfiguration code stale. Running the full code generation now produces a consistent and compilable codebase ([**@lexfrei**](https://github.com/lexfrei) in #2061). - -* **[e2e] Make kubernetes test retries effective by cleaning up stale resources**: Fixed E2E test retries for the Kubernetes tenant test by adding pre-creation cleanup of backend deployment/service and NFS pod/PVC in `run-kubernetes.sh`. Previously, retries would fail immediately because stale resources from a failed attempt blocked re-creation. Also increased the tenant deployment wait timeout from 90s to 300s to handle CI resource pressure ([**@lexfrei**](https://github.com/lexfrei) in #2062). - -## Development, Testing, and CI/CD - -* **[e2e] Use helm install instead of kubectl apply for cozystack installation**: Replaced the pre-rendered static YAML application flow (`kubectl apply`) with direct `helm upgrade --install` of the `packages/core/installer` chart in E2E tests. Removed the CRD/operator artifact upload/download steps from the CI workflow, simplifying the pipeline. The chart with correct values is already present in the sandbox via workspace copy and `pr.patch` ([**@lexfrei**](https://github.com/lexfrei) in #2060). - -## Documentation - -* **[website] Improve Azure autoscaling troubleshooting guide**: Enhanced the Azure autoscaling troubleshooting documentation with serial console instructions for debugging VMSS worker nodes, a troubleshooting section for nodes stuck in maintenance mode due to invalid or missing machine config, `az vmss update --custom-data` instructions for updating machine config, and a warning that Azure does not support reading back `customData` ([**@kvaps**](https://github.com/kvaps) in cozystack/website#424). - -* **[website] Update multi-location documentation for cilium-kilo variant**: Updated multi-location networking documentation to reflect the new integrated `cilium-kilo` variant selection during platform setup, replacing the previous manual Kilo installation and Cilium configuration steps. Added explanation of `enable-ipip-termination` and updated the troubleshooting section ([**@kvaps**](https://github.com/kvaps) in cozystack/website@02d63f0). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@klinch0**](https://github.com/klinch0) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@sircthulhu**](https://github.com/sircthulhu) - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0-beta.5...v1.0.0-beta.6 diff --git a/docs/changelogs/v1.0.0-rc.1.md b/docs/changelogs/v1.0.0-rc.1.md deleted file mode 100644 index 0fabe1b6..00000000 --- a/docs/changelogs/v1.0.0-rc.1.md +++ /dev/null @@ -1,65 +0,0 @@ - - -> **⚠️ Release Candidate Warning**: This is a release candidate intended for final validation before the stable v1.0.0 release. Breaking changes are not expected at this stage, but please test thoroughly before deploying to production. - -## Features and Improvements - -* **[harbor] Add managed Harbor container registry**: Added Harbor v2.14.2 as a managed tenant-level container registry service. The application uses CloudNativePG for PostgreSQL, the Redis operator for caching, and S3 via COSI BucketClaim (from SeaweedFS) for registry image storage. Auto-generated admin credentials are persisted across upgrades, TLS is handled by cert-manager, and Trivy vulnerability scanner is included. Users can now deploy a fully managed, production-ready OCI container registry within their tenant ([**@lexfrei**](https://github.com/lexfrei) in #2058). - -* **[kubernetes] Update supported Kubernetes versions to v1.30–v1.35**: Updated the tenant Kubernetes version matrix to v1.30, v1.31, v1.32, v1.33, v1.34, and v1.35 (now the default). EOL versions v1.28 and v1.29 are removed. Kamaji is updated to edge-26.2.4 with full Kubernetes 1.35 support, and the CAPI Kamaji provider is updated to v0.16.0. A compatibility patch ensures kubelets older than v1.35 are not broken by Kamaji injecting 1.35-specific kubelet fields ([**@lexfrei**](https://github.com/lexfrei) in #2073). - -* **[platform] Make cluster issuer name and ACME solver configurable**: Added `publishing.certificates.solver` (`http01` or `dns01`) and `publishing.certificates.issuerName` (default: `letsencrypt-prod`) parameters to the platform chart. This allows operators to point all ingress TLS annotations at any ClusterIssuer — custom ACME, self-signed, or internal CA — without modifying individual package templates. See the Breaking Changes section for the rename from the previous `issuerType` field ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077). - -* **[dashboard] VMInstance dropdowns for disks and instanceType**: The VM instance creation form now renders API-backed dropdowns for the `instanceType` field (populated from `VirtualMachineClusterInstancetype` cluster resources) and for disk `name` fields (populated from `VMDisk` resources in the same namespace). Default values are read from the ApplicationDefinition's OpenAPI schema. This eliminates manual lookups and reduces misconfiguration when attaching disks or selecting VM instance types ([**@sircthulhu**](https://github.com/sircthulhu) in #2071). - -* **[installer] Remove CRDs from Helm chart, delegate lifecycle to operator**: The `cozy-installer` Helm chart no longer ships CRDs in its `crds/` directory. CRD lifecycle is now fully managed by the Cozystack operator via the `--install-crds` flag, which applies embedded CRD manifests on every startup using server-side apply. The platform PackageSource is also created by the operator instead of a Helm template. This ensures CRDs and the PackageSource are always up to date after each operator restart, eliminating stale CRDs from Helm's install-only behavior ([**@lexfrei**](https://github.com/lexfrei) in #2074). - -## Fixes - -* **[kubevirt] Update KubeVirt to v1.6.4 and CDI to v1.64.0, fix VM pod initialization**: Updated KubeVirt operator to v1.6.4 and CDI operator to v1.64.0, including live migration of existing VMs during the upgrade. Additionally, disabled serial console logging globally via the KubeVirt CR to prevent a known v1.6.x issue ([upstream #15989](https://github.com/kubevirt/kubevirt/issues/15989)) where the `guest-console-log` init container blocked virt-launcher pods from starting, causing all VMs to get stuck in `PodInitializing` state ([**@nbykov0**](https://github.com/nbykov0) in #1833; [**@kvaps**](https://github.com/kvaps) in 7dfb819). - -* **[linstor] Fix DRBD+LUKS+STORAGE resource creation failure**: All newly created encrypted volumes were failing because the DRBD `.res` file was never written due to a missing `setExists(true)` call in the `LuksLayer`. Applied the upstream `skip-adjust-when-device-inaccessible` patch ([LINBIT/linstor-server#477](https://github.com/LINBIT/linstor-server/pull/477)) which fixes the root cause and also prevents unnecessary lsblk calls when devices are not yet physically present ([**@kvaps**](https://github.com/kvaps) in #2072). - -* **[system] Fix monitoring-agents FQDN resolution for tenant workload clusters**: Monitoring agents (`vmagent`, `fluent-bit`) in tenant workload clusters were failing to deliver metrics and logs because service addresses used short DNS names without the cluster domain suffix. Fixed by appending the configured cluster domain from `_cluster.cluster-domain` (with fallback to `cluster.local`) to all vmagent remoteWrite URLs and fluent-bit output hosts ([**@IvanHunters**](https://github.com/IvanHunters) in #2075). - -* **[cozystack-basics] Preserve existing HelmRelease values during reconciliations**: Fixed a data-loss bug where changes made to the `tenant-root` HelmRelease were silently dropped on the next forced or upgrade reconciliation of the `cozystack-basics` HelmRelease. The reconciler now merges new configuration with existing values instead of overwriting them ([**@sircthulhu**](https://github.com/sircthulhu) in #2068). - -* **[cozystack-basics] Deny resourcequotas deletion for tenant admin**: Fixed the `cozy:tenant:admin:base` ClusterRole to explicitly deny deletion of `ResourceQuota` objects for tenant admins and superadmins, preventing accidental removal of tenant resource limits ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2076). - -## Breaking Changes & Upgrade Notes - -* **[platform] Certificate issuer configuration parameters renamed**: The `publishing.certificates.issuerType` field is renamed to `publishing.certificates.solver`, and the value `cloudflare` is renamed to `dns01` to align with standard ACME terminology. A new `publishing.certificates.issuerName` field (default: `letsencrypt-prod`) is introduced to allow pointing all ingresses at a custom ClusterIssuer. Migration 32 is included and automatically converts existing configurations during upgrade — no manual action is required ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077). - -## Documentation - -* **[website] Migrate ConfigMap references to Platform Package in v1 documentation**: Updated the entire v1 documentation tree to replace legacy ConfigMap-based configuration references with the new Platform Package API, ensuring guides are consistent with the v1 configuration model ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#426). - -* **[website] Add generic Kubernetes deployment guide for v1**: Added a new installation guide covering Cozystack deployment on any generic Kubernetes cluster, expanding the set of supported deployment targets beyond provider-specific guides ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#408). - -* **[website] Refactor resource planning documentation**: Improved the resource planning guide with a clearer structure and more comprehensive coverage of planning considerations for Cozystack deployments ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#423). - -* **[website] Add ServiceAccount API access documentation and update FAQ**: Added a new article documenting ServiceAccount API access token configuration and updated the FAQ to include related troubleshooting guidance ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#421). - -* **[website] Update networking-mesh allowed-location-ips example**: Replaced provider-specific CLI usage with standard `kubectl` commands in the multi-location networking guide's `allowed-location-ips` example, making the documentation more universally applicable ([**@kvaps**](https://github.com/kvaps) in cozystack/website#425). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@IvanStukov**](https://github.com/IvanStukov) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@nbykov0**](https://github.com/nbykov0) -* [**@sircthulhu**](https://github.com/sircthulhu) - -### New Contributors - -We're excited to welcome our first-time contributors: - -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) - First contribution! - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0-beta.6...v1.0.0-rc.1 diff --git a/docs/changelogs/v1.0.0-rc.2.md b/docs/changelogs/v1.0.0-rc.2.md deleted file mode 100644 index a056ff8f..00000000 --- a/docs/changelogs/v1.0.0-rc.2.md +++ /dev/null @@ -1,57 +0,0 @@ - - -> **⚠️ Release Candidate Warning**: This is a release candidate intended for final validation before the stable v1.0.0 release. Breaking changes are not expected at this stage, but please test thoroughly before deploying to production. - -## Features and Improvements - -* **[keycloak] Allow custom Ingress hostname via values**: Added an `ingress.host` field to the cozy-keycloak chart values, allowing operators to override the default `keycloak.` Ingress hostname. The custom hostname is applied to both the Ingress resource and the `KC_HOSTNAME` environment variable in the StatefulSet. When left empty, the original behavior is preserved (fully backward compatible) ([**@sircthulhu**](https://github.com/sircthulhu) in #2101). - -## Fixes - -* **[platform] Fix upgrade issues in migrations, etcd timeout, and migration script**: Fixed multiple upgrade failures discovered during v0.41.1 → v1.0 upgrade testing. Migration 26 now uses the `cozystack.io/ui=true` label (always present on v0.41.1) instead of the new label that depends on migration 22 having run, and adds robust Helm secret deletion with fallback and verification. Migrations 28 and 29 wrap `grep` calls to prevent `pipefail` exits and fix the reconcile annotation to use RFC3339 format. Migration 27 now skips missing CRDs and adds a name-pattern fallback for Helm secret deletion. The etcd HelmRelease timeout is increased from 10m to 30m to accommodate TLS cert rotation hooks. The `migrate-to-version-1.0.sh` script gains the missing `bundle-disable`, `bundle-enable`, `expose-ingress`, and `expose-services` field mappings ([**@kvaps**](https://github.com/kvaps) in #2096). - -* **[platform] Fix orphaned -rd HelmReleases after application renames**: After the `ferretdb→mongodb`, `mysql→mariadb`, and `virtual-machine→vm-disk+vm-instance` renames, the system-level `-rd` HelmReleases in `cozy-system` (`ferretdb-rd`, `mysql-rd`, `virtual-machine-rd`) were left orphaned, referencing ExternalArtifacts that no longer exist and causing persistent reconciliation failures. Migrations 28 and 29 are updated to remove these resources, and migration 33 is added as a safety net for clusters that already passed those migrations ([**@kvaps**](https://github.com/kvaps) in #2102). - -* **[monitoring-agents] Fix FQDN resolution regression in tenant workload clusters**: The fix introduced in #2075 used `_cluster.cluster-domain` references in `values.yaml`, but `_cluster` values are not accessible from Helm subchart contexts — meaning fluent-bit received empty hostnames and failed to forward logs. This PR replaces the `_cluster` references with a new `global.clusterDomain` variable (empty by default for management clusters, set to the cluster domain for tenant clusters), which is correctly shared with all subcharts ([**@kvaps**](https://github.com/kvaps) in #2086). - -* **[dashboard] Fix legacy templating and cluster identifier in sidebar links**: Standardized the cluster identifier used across dashboard menu links, administration links, and API request paths, resolving incorrect or broken link targets for the Backups and External IPs sidebar sections ([**@androndo**](https://github.com/androndo) in #2093). - -* **[dashboard] Fix backupjobs creation form and sidebar backup category identifier**: Fixed the backup job creation form configuration, adding the required Name, Namespace, Plan Name, Application, and Backup Class fields. Fixed the sidebar backup category identifier that was causing incorrect navigation ([**@androndo**](https://github.com/androndo) in #2103). - -## Documentation - -* **[website] Add Helm chart development principles guide**: Added a new developer guide section documenting Cozystack's four core Helm chart principles: easy upstream updates, local-first artifacts, local dev/test workflow, and no external dependencies ([**@kvaps**](https://github.com/kvaps) in cozystack/website#418). - -* **[website] Add network architecture overview**: Added comprehensive network architecture documentation covering the multi-layered networking stack — MetalLB (L2/BGP), Cilium eBPF (kube-proxy replacement), Kube-OVN (centralized IPAM), and tenant isolation with identity-based eBPF policies — with Mermaid diagrams for all major traffic flows ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#422). - -* **[website] Update documentation to use jsonpatch for service exposure**: Improved `kubectl patch` commands throughout installation and configuration guides to use JSON Patch `add` operations for extending arrays instead of replacing them wholesale, making the documented commands safer and more precise ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#427). - -* **[website] Update certificates section in Platform Package documentation**: Updated the certificate configuration documentation to reflect the new `solver` and `issuerName` fields introduced in v1.0.0-rc.1, replacing the legacy `issuerType` references ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#429). - -* **[website] Add tenant Kubernetes cluster log querying guide**: Added documentation for querying logs from tenant Kubernetes clusters in Grafana using VictoriaLogs labels (`tenant`, `kubernetes_namespace_name`, `kubernetes_pod_name`), including the `monitoringAgents` addon prerequisite and step-by-step filtering examples ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#430). - -* **[website] Replace non-idempotent commands with idempotent alternatives**: Updated `helm install` to `helm upgrade --install`, `kubectl create -f` to `kubectl apply -f`, and `kubectl create ns` to the dry-run+apply pattern across all installation and deployment guides so commands can be safely re-run ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#431). - -* **[website] Fix broken documentation links with `.md` suffix**: Fixed incorrect internal links with `.md` suffix across virtualization guides for both v0 and v1 documentation, standardizing link text to "Developer Guide" ([**@cheese**](https://github.com/cheese) in cozystack/website#432). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@androndo**](https://github.com/androndo) -* [**@cheese**](https://github.com/cheese) -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@sircthulhu**](https://github.com/sircthulhu) - -### New Contributors - -We're excited to welcome our first-time contributors: - -* [**@cheese**](https://github.com/cheese) - First contribution! - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0-rc.1...v1.0.0-rc.2 diff --git a/docs/changelogs/v1.0.0.md b/docs/changelogs/v1.0.0.md deleted file mode 100644 index 469ea1db..00000000 --- a/docs/changelogs/v1.0.0.md +++ /dev/null @@ -1,289 +0,0 @@ - - -# Cozystack v1.0.0 — "Stable" - -We are thrilled to announce **Cozystack v1.0.0**, the first stable major release of the Cozystack platform. This milestone represents a fundamental architectural evolution from the v0.x series, introducing a fully operator-driven package management system, a comprehensive backup and restore framework, a redesigned virtual machine architecture, and a rich set of new managed applications — all hardened through an extensive alpha, beta, and release-candidate cycle. - -## Feature Highlights - -### Package-Based Architecture with Cozystack Operator - -The most significant architectural change in v1.0.0 is the replacement of HelmRelease bundle deployments with a declarative **Package** and **PackageSource** model managed by the new `cozystack-operator`. Operators now define their platform configuration in a structured `values.yaml` and the operator reconciles the desired state by managing Package and PackageSource resources across the cluster. - -The operator also takes ownership of CRD lifecycle — installing and updating CRDs from embedded manifests at every startup — eliminating the stale-CRD problem that affected Helm-only installations. Flux sharding has been added to distribute tenant HelmRelease reconciliation across multiple Flux controllers, providing horizontal scalability in large multi-tenant environments. - -A migration script (`hack/migrate-to-version-1.0.sh`) is provided for upgrading existing v0.x clusters, along with 33 incremental migration steps that automate resource renaming, secret cleanup, and configuration conversion. - -### Comprehensive Backup and Restore System - -v1.0.0 ships a fully featured, production-ready backup and restore framework built on Velero integration. Users can define **BackupClass** resources to describe backup storage targets, create **BackupPlan** schedules, and trigger **RestoreJob** resources for end-to-end application recovery. - -Virtual machine backups are supported natively via the Velero KubeVirt plugin, which captures consistent VM disk snapshots alongside metadata. The backup controller and the backup strategy sub-controllers (including the VM-specific strategy) are installed by default, and a full dashboard UI allows users to monitor backup status, view backup job history, and initiate restore workflows. - -### Redesigned Virtual Machine Architecture - -The legacy `virtual-machine` application has been replaced with a two-resource architecture: **`vm-disk`** for managing persistent disks and **`vm-instance`** for managing VM lifecycle. This separation provides cleaner disk/instance management, allows disks to be reused across VM instances, and aligns with modern KubeVirt patterns. - -New capabilities include: a `cpuModel` field for direct CPU model specification without using an instanceType; the ability to switch between `instanceType`-based and custom resource-based configurations; migration from the deprecated `running` field to `runStrategy`; and native **RWX (NFS) filesystem support** in the KubeVirt CSI driver, enabling multiple pods to mount the same persistent volume simultaneously. - -### New Managed Applications - -v1.0.0 expands the application catalog significantly: - -- **MongoDB**: A fully managed MongoDB replica set with persistent storage, monitoring integration, and unified user/database configuration API. -- **Qdrant**: A high-performance vector database for AI and machine learning workloads, supporting single-replica and clustered modes with API key authentication and optional external LoadBalancer access. -- **Harbor**: A fully managed OCI container registry backed by CloudNativePG, Redis operator, and COSI BucketClaim (SeaweedFS). Includes Trivy vulnerability scanner, auto-generated admin credentials, and TLS via cert-manager. -- **NATS**: Enhanced with full Grafana monitoring dashboards for JetStream and server metrics, Prometheus support with TLS-aware configuration, and updated image customization options. -- **MariaDB**: The `mysql` application is renamed to `mariadb`, accurately reflecting the underlying engine. An automatic migration (migration 27) converts all existing MySQL resources to use the `mariadb` naming. - -FerretDB has been removed from the catalog as it is superseded by native MongoDB support. - -### Multi-Location Networking with Kilo and cilium-kilo - -Cozystack v1.0.0 introduces first-class support for multi-location clusters via the **Kilo** WireGuard mesh networking package. Kilo automatically establishes encrypted WireGuard tunnels between nodes in different network segments, enabling seamless cross-region communication. - -A new integrated **`cilium-kilo`** networking variant combines Cilium eBPF CNI with Kilo's WireGuard overlay in a single platform configuration selection. This variant enables `enable-ipip-termination` in Cilium and deploys Kilo with `--compatibility=cilium`, allowing Cilium network policies to function correctly over the WireGuard mesh — without any manual configuration of the two components. - -### Flux Sharding for Scalable Multi-Tenancy - -Tenant HelmRelease reconciliation is now distributed across multiple Flux controllers via sharding labels. Each tenant workload is assigned to a shard based on a deterministic hash, preventing a single Flux controller from becoming a bottleneck in large multi-tenant environments. The platform operator manages the shard assignment automatically, and new shards can be added by scaling the Flux deployment. - -## Major Features and Improvements - -### Cozystack Operator - -* **[cozystack-operator] Introduce Package and PackageSource APIs**: Added new CRDs for declarative package management, defining the full API for Package and PackageSource resources ([**@kvaps**](https://github.com/kvaps) in #1740, #1741, #1755, #1756, #1760, #1761). -* **[platform] Migrate from HelmRelease bundles to Package-based deployment**: Replaced HelmRelease bundle system with Package resources managed by cozystack-operator, including restructured values.yaml with full configuration support for networking, publishing, authentication, scheduling, branding, and resources ([**@kvaps**](https://github.com/kvaps) in #1816). -* **[cozystack-operator] Add automatic CRD installation at startup**: Added `--install-crds` flag to install embedded CRD manifests on every startup via server-side apply, ensuring CRDs and the PackageSource are always up to date ([**@lexfrei**](https://github.com/lexfrei) in #2060). -* **[installer] Remove CRDs from Helm chart, delegate lifecycle to operator**: The `cozy-installer` Helm chart no longer ships CRDs; CRD lifecycle is fully managed by the Cozystack operator ([**@lexfrei**](https://github.com/lexfrei) in #2074). -* **[cozystack-operator] Preserve existing suspend field in package reconciler**: Fixed package reconciler to properly preserve the suspend field state during reconciliation ([**@sircthulhu**](https://github.com/sircthulhu) in #2043). -* **[cozystack-operator] Fix namespace privileged flag resolution and field ownership**: Fixed operator to correctly check all Packages in a namespace when determining privileged status, and resolved SSA field ownership conflicts ([**@kvaps**](https://github.com/kvaps) in #2046). -* **[platform] Add flux-plunger controller**: Added flux-plunger controller to automatically fix stuck HelmRelease errors by cleaning up failed resources and retrying reconciliation ([**@kvaps**](https://github.com/kvaps) in #1843). -* **[installer] Add variant-aware templates for generic Kubernetes support**: Extended the installer to support generic and hosted Kubernetes deployments via the `cozystackOperator.variant=generic` parameter ([**@lexfrei**](https://github.com/lexfrei) in #2010). -* **[installer] Unify operator templates**: Merged separate operator templates into a single variant-based template supporting Talos and non-Talos deployments ([**@kvaps**](https://github.com/kvaps) in #2034). - -### API and Platform - -* **[api] Rename CozystackResourceDefinition to ApplicationDefinition**: Renamed CRD and all related types for clarity and consistency, with migration 24 handling the transition automatically ([**@kvaps**](https://github.com/kvaps) in #1864). -* **[platform] Add DNS-1035 validation for Application names**: Added dynamic DNS-1035 label validation for Application names at creation time, preventing resources with invalid names that would fail downstream ([**@lexfrei**](https://github.com/lexfrei) in #1771). -* **[platform] Make cluster issuer name and ACME solver configurable**: Added `publishing.certificates.solver` and `publishing.certificates.issuerName` parameters to allow pointing all ingress TLS annotations at any ClusterIssuer ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077). -* **[platform] Add cilium-kilo networking variant**: Added integrated `cilium-kilo` networking variant combining Cilium CNI with Kilo WireGuard mesh overlay ([**@kvaps**](https://github.com/kvaps) in #2064). -* **[cozystack-api] Switch from DaemonSet to Deployment**: Migrated cozystack-api to a Deployment with PreferClose topology spread constraints, reducing resource consumption while maintaining high availability ([**@kvaps**](https://github.com/kvaps) in #2041, #2048). - -### Virtual Machines - -* **[vm-instance] Complete migration from virtual-machine to vm-disk and vm-instance**: Fully migrated from `virtual-machine` to the new `vm-disk` and `vm-instance` architecture, with automatic migration script (migration 28) for existing VMs ([**@kvaps**](https://github.com/kvaps) in #2040). -* **[kubevirt-csi-driver] Add RWX Filesystem (NFS) support**: Added Read-Write-Many filesystem support to kubevirt-csi-driver via automatic NFS server deployment per PVC ([**@kvaps**](https://github.com/kvaps) in #2042). -* **[vm] Add cpuModel field to specify CPU model without instanceType**: Added cpuModel field to VirtualMachine API for granular CPU control ([**@sircthulhu**](https://github.com/sircthulhu) in #2007). -* **[vm] Allow switching between instancetype and custom resources**: Implemented atomic upgrade hook for switching between instanceType-based and custom resource VM configurations ([**@sircthulhu**](https://github.com/sircthulhu) in #2008). -* **[vm] Migrate to runStrategy instead of running**: Migrated VirtualMachine API from deprecated `running` field to `runStrategy` ([**@sircthulhu**](https://github.com/sircthulhu) in #2004). -* **[vm] Always expose VMs with a service**: Virtual machines are now always exposed with at least a ClusterIP service, ensuring in-cluster DNS names ([**@lllamnyp**](https://github.com/lllamnyp) in #1738, #1751). -* **[dashboard] VMInstance dropdowns for disks and instanceType**: VM instance creation form now renders API-backed dropdowns for `instanceType` and disk `name` fields ([**@sircthulhu**](https://github.com/sircthulhu) in #2071). - -### Backup System - -* **[backups] Implement comprehensive backup and restore functionality**: Core backup Plan controller, Velero strategy controller, RestoreJob resource with end-to-end restore workflows, and enhanced backup plans UI ([**@lllamnyp**](https://github.com/lllamnyp) in #1640, #1685, #1687, #1719, #1720, #1737, #1967; [**@androndo**](https://github.com/androndo) in #1762, #1967, #1968, #1811). -* **[backups] Add kubevirt plugin to velero**: Added KubeVirt plugin to Velero for consistent VM state and data snapshots ([**@lllamnyp**](https://github.com/lllamnyp) in #2017). -* **[backups] Install backupstrategy controller by default**: Enabled backupstrategy controller by default for automatic backup scheduling ([**@lllamnyp**](https://github.com/lllamnyp) in #2020). -* **[backups] Better selectors for VM strategy**: Improved VM backup strategy selectors for accurate and reliable backup targeting ([**@lllamnyp**](https://github.com/lllamnyp) in #2023). -* **[backups] Create RBAC for backup resources**: Added comprehensive RBAC configuration for backup operations and restore jobs ([**@lllamnyp**](https://github.com/lllamnyp) in #2018). - -### Networking - -* **[kilo] Introduce Kilo WireGuard mesh networking**: Added Kilo as a system package providing secure WireGuard-based VPN mesh for connecting Kubernetes nodes across different networks and regions ([**@kvaps**](https://github.com/kvaps) in #1691). -* **[kilo] Add Cilium compatibility variant**: Added `cilium` variant enabling Cilium-aware IPIP encapsulation for full network policy enforcement with Kilo mesh ([**@kvaps**](https://github.com/kvaps) in #2055). -* **[kilo] Update to v0.8.0 with configurable MTU**: Updated Kilo to v0.8.0 with configurable MTU parameter and performance improvements ([**@kvaps**](https://github.com/kvaps) in #2003, #2049, #2053). -* **[local-ccm] Add local-ccm package**: Added local cloud controller manager for managing load balancer services in bare-metal environments ([**@kvaps**](https://github.com/kvaps) in #1831). -* **[local-ccm] Add node-lifecycle-controller component**: Added optional node-lifecycle-controller that automatically deletes unreachable NotReady nodes, solving the "zombie" node problem in autoscaled clusters ([**@IvanHunters**](https://github.com/IvanHunters) in #1992). -* **[tenant] Allow egress to parent ingress pods**: Updated tenant network policies to allow egress traffic to parent cluster ingress pods ([**@lexfrei**](https://github.com/lexfrei) in #1765, #1776). - -### New Applications - -* **[mongodb] Add MongoDB managed application**: Added MongoDB as a fully managed database with replica sets, persistent storage, and unified user/database configuration ([**@lexfrei**](https://github.com/lexfrei) in #1822; [**@kvaps**](https://github.com/kvaps) in #1923). -* **[qdrant] Add Qdrant vector database**: Added Qdrant as a high-performance vector database for AI/ML workloads with API key authentication and optional LoadBalancer access ([**@lexfrei**](https://github.com/lexfrei) in #1987). -* **[harbor] Add managed Harbor container registry**: Added Harbor v2.14.2 as a managed tenant-level container registry with CloudNativePG, Redis operator, COSI BucketClaim storage, and Trivy scanner ([**@lexfrei**](https://github.com/lexfrei) in #2058). -* **[nats] Add monitoring**: Added Grafana dashboards for NATS JetStream and server metrics, Prometheus monitoring with TLS support ([**@klinch0**](https://github.com/klinch0) in #1381). -* **[mariadb] Rename mysql application to mariadb**: Renamed MySQL application to MariaDB with automatic migration (migration 27) for all existing resources ([**@kvaps**](https://github.com/kvaps) in #2026). -* **[ferretdb] Remove FerretDB application**: Removed FerretDB, superseded by native MongoDB support ([**@kvaps**](https://github.com/kvaps) in #2028). - -### Kubernetes and System Components - -* **[kubernetes] Update supported Kubernetes versions to v1.30–v1.35**: Updated the tenant Kubernetes version matrix, with v1.35 as the new default. Kamaji updated to edge-26.2.4 and CAPI Kamaji provider to v0.16.0 ([**@lexfrei**](https://github.com/lexfrei) in #2073). -* **[kubernetes] Auto-enable Gateway API support in cert-manager**: Added automatic Gateway API support in cert-manager for tenant clusters ([**@kvaps**](https://github.com/kvaps) in #1997). -* **[kubernetes] Use ingress-nginx nodeport service**: Changed tenant Kubernetes clusters to use ingress-nginx NodePort service for improved compatibility ([**@sircthulhu**](https://github.com/sircthulhu) in #1948). -* **[system] Add cluster-autoscaler for Hetzner and Azure**: Added cluster-autoscaler system package for automatically scaling management cluster nodes on Hetzner and Azure ([**@kvaps**](https://github.com/kvaps) in #1964). -* **[cluster-autoscaler] Enable enforce-node-group-min-size by default**: Ensures node groups are always scaled up to their configured minimum size ([**@kvaps**](https://github.com/kvaps) in #2050). -* **[system] Add clustersecret-operator package**: Added clustersecret-operator for managing secrets across multiple namespaces ([**@sircthulhu**](https://github.com/sircthulhu) in #2025). - -### Monitoring - -* **[monitoring] Enable monitoring for core components**: Enhanced monitoring capabilities with dashboards and metrics for core Cozystack components ([**@IvanHunters**](https://github.com/IvanHunters) in #1937). -* **[monitoring] Add SLACK_SEVERITY_FILTER and VMAgent for tenant monitoring**: Added SLACK_SEVERITY_FILTER for Slack alert filtering and VMAgent for tenant namespace metrics scraping ([**@IvanHunters**](https://github.com/IvanHunters) in #1712). -* **[monitoring-agents] Fix FQDN resolution for tenant workload clusters**: Fixed monitoring agents in tenant clusters to use full DNS names with cluster domain suffix ([**@IvanHunters**](https://github.com/IvanHunters) in #2075; [**@kvaps**](https://github.com/kvaps) in #2086). - -### Storage - -* **[linstor] Move CRDs to dedicated piraeus-operator-crds chart**: Moved LINSTOR CRDs to a dedicated chart, ensuring reliable installation of all CRDs including `linstorsatellites.io` ([**@kvaps**](https://github.com/kvaps) in #2036; [**@IvanHunters**](https://github.com/IvanHunters) in #1991). -* **[seaweedfs] Increase certificate duration to 10 years**: Increased SeaweedFS certificate validity to 10 years to reduce rotation overhead ([**@IvanHunters**](https://github.com/IvanHunters) in #1986). - -## Improvements - -* **[dashboard] Upgrade dashboard to version 1.4.0**: Updated Cozystack dashboard to v1.4.0 with new features and improvements ([**@sircthulhu**](https://github.com/sircthulhu) in #2051). -* **[dashboard] Hide Ingresses/Services/Secrets tabs when no selectors defined**: Tabs are now conditionally shown based on whether the ApplicationDefinition has resource selectors configured, reducing UI clutter ([**@kvaps**](https://github.com/kvaps) in #2087). -* **[dashboard] Add startupProbe to prevent container restarts on slow hardware**: Added startup probe to dashboard pods to prevent unnecessary restarts ([**@kvaps**](https://github.com/kvaps) in #1996). -* **[keycloak] Allow custom Ingress hostname via values**: Added `ingress.host` field to cozy-keycloak chart values for overriding the default `keycloak.` hostname ([**@sircthulhu**](https://github.com/sircthulhu) in #2101). -* **[branding] Separate values for Keycloak**: Separated Keycloak branding values for better customization capabilities ([**@nbykov0**](https://github.com/nbykov0) in #1947). -* **[rbac] Use hierarchical naming scheme**: Refactored RBAC to use hierarchical naming for cluster roles and role bindings ([**@lllamnyp**](https://github.com/lllamnyp) in #2019). -* **[tenant,rbac] Use shared clusterroles**: Refactored tenant RBAC to use shared ClusterRoles for improved consistency ([**@lllamnyp**](https://github.com/lllamnyp) in #1999). -* **[kubernetes] Increase default apiServer resourcesPreset to large**: Increased kube-apiserver resource preset to `large` for more reliable operation under higher workloads ([**@kvaps**](https://github.com/kvaps) in #1875). -* **[kubernetes] Increase kube-apiserver startup probe threshold**: Increased startup probe threshold to allow more time for API server readiness ([**@kvaps**](https://github.com/kvaps) in #1876). -* **[etcd] Increase probe thresholds for better recovery**: Increased etcd probe thresholds to improve cluster resilience during temporary slowdowns ([**@kvaps**](https://github.com/kvaps) in #1874). -* **[etcd-operator] Add vertical-pod-autoscaler dependency**: Added VPA as a dependency to etcd-operator for proper resource scaling ([**@sircthulhu**](https://github.com/sircthulhu) in #2047). -* **[cilium] Change cilium-operator replicas to 1**: Reduced Cilium operator replicas to decrease resource consumption in smaller deployments ([**@IvanHunters**](https://github.com/IvanHunters) in #1784). -* **[keycloak-configure,dashboard] Enable insecure TLS verification by default**: Made SSL certificate verification configurable with insecure mode enabled by default for local development ([**@IvanHunters**](https://github.com/IvanHunters) in #2005). -* **[platform] Split telemetry between operator and controller**: Separated telemetry collection for better metrics isolation ([**@kvaps**](https://github.com/kvaps) in #1869). -* **[system] Add resource requests and limits to etcd-defrag**: Added resource requests and limits to etcd-defrag job to prevent resource contention ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1785, #1786). - -## Fixes - -* **[dashboard] Fix sidebar visibility on cluster-level pages**: Fixed broken URLs with double `//` on cluster-level pages by hiding namespace-scoped sidebar items when no tenant is selected ([**@sircthulhu**](https://github.com/sircthulhu) in #2106). -* **[platform] Fix upgrade issues in migrations, etcd timeout, and migration script**: Fixed multiple upgrade failures discovered during v0.41.1 → v1.0 upgrade testing, including migration 26-29 fixes, RFC3339 format for annotations, and extended etcd HelmRelease timeout to 30m ([**@kvaps**](https://github.com/kvaps) in #2096). -* **[platform] Fix orphaned -rd HelmReleases after application renames**: Migrations 28-29 updated to remove orphaned `-rd` HelmReleases in `cozy-system` after `ferretdb→mongodb`, `mysql→mariadb`, and `virtual-machine→vm-disk+vm-instance` renames, with migration 33 as a safety net ([**@kvaps**](https://github.com/kvaps) in #2102). -* **[platform] Adopt tenant-root into cozystack-basics during migration**: Added migration 31 to adopt existing `tenant-root` Namespace and HelmRelease into `cozystack-basics` for a safe v0.41.x → v1.0 upgrade path ([**@kvaps**](https://github.com/kvaps) in #2065). -* **[platform] Preserve tenant-root HelmRelease during migration**: Fixed data-loss risk during migration where `tenant-root` HelmRelease could be deleted ([**@sircthulhu**](https://github.com/sircthulhu) in #2063). -* **[platform] Fix cozystack-values secret race condition**: Fixed race condition in cozystack-values secret creation that could cause initialization failures ([**@lllamnyp**](https://github.com/lllamnyp) in #2024). -* **[cozystack-basics] Preserve existing HelmRelease values during reconciliations**: Fixed data-loss bug where changes to `tenant-root` HelmRelease were dropped on the next reconciliation ([**@sircthulhu**](https://github.com/sircthulhu) in #2068). -* **[cozystack-basics] Deny resourcequotas deletion for tenant admin**: Fixed `cozy:tenant:admin:base` ClusterRole to explicitly deny deletion of ResourceQuota objects ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2076). -* **[dashboard] Fix legacy templating and cluster identifier in sidebar links**: Standardized cluster identifier across dashboard menu links resolving broken link targets for Backups and External IPs ([**@androndo**](https://github.com/androndo) in #2093). -* **[dashboard] Fix backupjobs creation form and sidebar backup category identifier**: Fixed backup job creation form fields and fixed sidebar backup category identifier ([**@androndo**](https://github.com/androndo) in #2103). -* **[kubevirt] Update KubeVirt to v1.6.4 and CDI to v1.64.0, fix VM pod initialization**: Updated KubeVirt and CDI and disabled serial console logging globally to fix the `guest-console-log` init container blocking virt-launcher pods ([**@nbykov0**](https://github.com/nbykov0) in #1833; [**@kvaps**](https://github.com/kvaps)). -* **[linstor] Fix DRBD+LUKS+STORAGE resource creation failure**: Applied upstream fix for all newly created encrypted volumes failing due to missing `setExists(true)` call in `LuksLayer` ([**@kvaps**](https://github.com/kvaps) in #2072). -* **[platform] Clean up Helm secrets for removed releases**: Added cleanup logic to migration 23 to remove orphaned Helm secrets from removed `-rd` releases ([**@kvaps**](https://github.com/kvaps) in #2035). -* **[monitoring] Fix YAML parse error in vmagent template**: Fixed YAML parsing error in monitoring-agents vmagent template ([**@kvaps**](https://github.com/kvaps) in #2037). -* **[monitoring] Remove cozystack-controller dependency**: Fixed monitoring package to remove unnecessary cozystack-controller dependency ([**@IvanHunters**](https://github.com/IvanHunters) in #1990). -* **[monitoring] Remove duplicate dashboards.list**: Fixed duplicate dashboards.list configuration in extra/monitoring package ([**@IvanHunters**](https://github.com/IvanHunters) in #2016). -* **[linstor] Update piraeus-server patches with critical fixes**: Backported critical patches fixing edge cases in device management and DRBD resource handling ([**@kvaps**](https://github.com/kvaps) in #1850). -* **[apiserver] Fix Watch resourceVersion and bookmark handling**: Fixed Watch API handling of resourceVersion and bookmarks for proper event streaming ([**@kvaps**](https://github.com/kvaps) in #1860). -* **[bootbox] Auto-create bootbox-application as dependency**: Fixed bootbox package to automatically create required bootbox-application dependency ([**@kvaps**](https://github.com/kvaps) in #1974). -* **[postgres-operator] Correct PromQL syntax in CNPGClusterOffline alert**: Fixed incorrect PromQL syntax in the CNPGClusterOffline Prometheus alert ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1981). -* **[coredns] Fix serviceaccount to match kubernetes bootstrap RBAC**: Fixed CoreDNS service account to correctly match Kubernetes bootstrap RBAC requirements ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1958). -* **[dashboard] Verify JWT token**: Added JWT token verification to dashboard for improved security ([**@lllamnyp**](https://github.com/lllamnyp) in #1980). -* **[codegen] Fix missing gen_client in update-codegen.sh**: Fixed build error in `pkg/generated/applyconfiguration/utils.go` by including `gen_client` in the codegen script ([**@lexfrei**](https://github.com/lexfrei) in #2061). -* **[kubevirt-operator] Fix typo in VMNotRunningFor10Minutes alert**: Fixed typo in VM alert name ensuring proper alert triggering ([**@lexfrei**](https://github.com/lexfrei) in #1770, #1775). - -## Security - -* **[dashboard] Verify JWT token**: Added JWT token verification to the dashboard for improved authentication security ([**@lllamnyp**](https://github.com/lllamnyp) in #1980). - -## Dependencies - -* **[cilium] Update to v1.18.6**: Updated Cilium CNI to v1.18.6 with security fixes and performance improvements ([**@sircthulhu**](https://github.com/sircthulhu) in #1868). -* **[kube-ovn] Update to v1.15.3**: Updated Kube-OVN CNI to v1.15.3 with performance improvements and bug fixes ([**@kvaps**](https://github.com/kvaps) in #2022). -* **[kilo] Update to v0.8.0**: Updated Kilo WireGuard mesh to v0.8.0 with performance improvements and new compatibility features ([**@kvaps**](https://github.com/kvaps) in #2053). -* **Update Talos Linux to v1.12.1**: Updated Talos Linux to v1.12.1 with latest features and security patches ([**@kvaps**](https://github.com/kvaps) in #1877). - -## System Configuration - -* **[vpc] Migrate subnets definition from map to array format**: Migrated VPC subnets from `map[string]Subnet` to `[]Subnet` with explicit `name` field, with automatic migration via migration 30 ([**@kvaps**](https://github.com/kvaps) in #2052). -* **[migrations] Add migrations 23-33 for v1.0 upgrade path**: Added 11 incremental migrations handling CRD ownership, resource renaming, secret cleanup, Helm adoption, and configuration conversion for the v0.41.x → v1.0.0 upgrade path ([**@kvaps**](https://github.com/kvaps) in #1975, #2035, #2036, #2040, #2026, #2065, #2052, #2102). -* **[tenant] Run cleanup job from system namespace**: Moved tenant cleanup job to system namespace for improved security and resource isolation ([**@lllamnyp**](https://github.com/lllamnyp) in #1774, #1777). - -## Development, Testing, and CI/CD - -* **[ci] Use GitHub Copilot CLI for changelog generation**: Automated changelog generation using GitHub Copilot CLI ([**@androndo**](https://github.com/androndo) in #1753). -* **[ci] Choose runner conditional on label**: Added conditional runner selection in CI based on PR labels ([**@lllamnyp**](https://github.com/lllamnyp) in #1998). -* **[e2e] Use helm install instead of kubectl apply for cozystack installation**: Replaced static YAML apply flow with direct `helm upgrade --install` of the installer chart in E2E tests ([**@lexfrei**](https://github.com/lexfrei) in #2060). -* **[e2e] Make kubernetes test retries effective by cleaning up stale resources**: Fixed E2E test retries by adding pre-creation cleanup and increasing deployment wait timeout to 300s ([**@lexfrei**](https://github.com/lexfrei) in #2062). -* **[e2e] Increase HelmRelease readiness timeout for kubernetes test**: Increased HelmRelease readiness timeout to prevent false failures on slower hardware ([**@lexfrei**](https://github.com/lexfrei) in #2033). -* **[ci] Improve cozyreport functionality**: Enhanced cozyreport tool with improved reporting for CI/CD pipelines ([**@lllamnyp**](https://github.com/lllamnyp) in #2032). -* **feat(cozypkg): add cross-platform build targets with version injection**: Added cross-platform build targets for cozypkg/cozyhr tool for linux/amd64, linux/arm64, darwin/amd64, darwin/arm64 ([**@kvaps**](https://github.com/kvaps) in #1862). -* **refactor: move scripts to hack directory**: Reorganized scripts to the standard `hack/` location ([**@kvaps**](https://github.com/kvaps) in #1863). -* **Update CODEOWNERS**: Updated CODEOWNERS to include new maintainers ([**@lllamnyp**](https://github.com/lllamnyp) in #1972; [**@IvanHunters**](https://github.com/IvanHunters) in #2015). -* **[talm] Skip config loading for completion subcommands**: Fixed talm CLI to skip config loading for shell completion commands ([**@kitsunoff**](https://github.com/kitsunoff) in cozystack/talm#109). -* **[talm] Fix metadata.id type casting in physical_links_info**: Fixed Prometheus query to properly cast metadata.id to string for regexMatch operations ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#110). - -## Documentation - -* **[website] Add documentation versioning**: Implemented comprehensive documentation versioning with separate v0 and v1 documentation trees and a version selector in the UI ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#415). -* **[website] Describe upgrade to v1.0**: Added detailed upgrade instructions for migrating from v0.x to v1.0 ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website@21bbe84). -* **[website] Migrate ConfigMap references to Platform Package in v1 docs**: Updated entire v1 documentation to replace legacy ConfigMap-based configuration with the new Platform Package API ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#426). -* **[website] Add generic Kubernetes deployment guide for v1**: Added installation guide for deploying Cozystack on any generic Kubernetes cluster ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#408). -* **[website] Describe operator-based and HelmRelease-based package patterns**: Added development documentation explaining operator-based and HelmRelease-based package patterns ([**@kvaps**](https://github.com/kvaps) in cozystack/website#413). -* **[website] Add Helm chart development principles guide**: Added developer guide documenting Cozystack's four core Helm chart principles ([**@kvaps**](https://github.com/kvaps) in cozystack/website#418). -* **[website] Add network architecture overview**: Added comprehensive network architecture documentation covering the multi-layered networking stack with Mermaid diagrams ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#422). -* **[website] Add LINSTOR disk preparation guide**: Added comprehensive documentation for preparing disks for LINSTOR storage ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#411). -* **[website] Add Proxmox VM migration guide**: Added detailed guide for migrating virtual machines from Proxmox to Cozystack ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#410). -* **[website] Add cluster autoscaler documentation**: Added documentation for Hetzner setup with Talos, vSwitch, and Kilo mesh integration ([**@kvaps**](https://github.com/kvaps) in #1964). -* **[website] Improve Azure autoscaling troubleshooting guide**: Enhanced Azure autoscaling documentation with serial console instructions and `az vmss update --custom-data` guidance ([**@kvaps**](https://github.com/kvaps) in cozystack/website#424). -* **[website] Update multi-location documentation for cilium-kilo variant**: Updated multi-location networking docs to reflect the integrated `cilium-kilo` variant selection ([**@kvaps**](https://github.com/kvaps) in cozystack/website@02d63f0). -* **[website] Update documentation to use jsonpatch for service exposure**: Improved `kubectl patch` commands to use JSON Patch `add` operations ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#427). -* **[website] Update certificates section in Platform Package documentation**: Updated certificate configuration docs to reflect new `solver` and `issuerName` fields ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#429). -* **[website] Add tenant Kubernetes cluster log querying guide**: Added documentation for querying logs from tenant clusters in Grafana using VictoriaLogs labels ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#430). -* **[website] Replace non-idempotent commands with idempotent alternatives**: Updated `helm install` to `helm upgrade --install` and `kubectl create` to `kubectl apply` across all installation guides ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#431). -* **[website] Fix broken documentation links with .md suffix**: Fixed incorrect internal links across virtualization guides for v0 and v1 documentation ([**@cheese**](https://github.com/cheese) in cozystack/website#432). -* **[website] Refactor resource planning documentation**: Improved resource planning guide with clearer structure and more comprehensive coverage ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#423). -* **[website] Add ServiceAccount API access documentation and update FAQ**: Added documentation for ServiceAccount API access token configuration and updated FAQ ([**@IvanStukov**](https://github.com/IvanStukov) in cozystack/website#421). -* **[website] Update networking-mesh allowed-location-ips example**: Replaced provider-specific CLI with standard `kubectl` commands in multi-location networking guide ([**@kvaps**](https://github.com/kvaps) in cozystack/website#425). -* **[website] docs(storage): simplify NFS driver setup instructions**: Simplified NFS driver setup documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website#399). -* **[website] Add Hetzner RobotLB documentation**: Added documentation for configuring public IP with Hetzner RobotLB ([**@kvaps**](https://github.com/kvaps) in cozystack/website#394). -* **[website] Add documentation for creating and managing cloned VMs**: Added comprehensive guide for VM cloning operations ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#401). -* **[website] Update Talos installation docs for Hetzner and Servers.com**: Updated installation documentation for Hetzner and Servers.com environments ([**@kvaps**](https://github.com/kvaps) in cozystack/website#395). -* **[website] Add Hidora organization support details**: Added Hidora to the support page ([**@matthieu-robin**](https://github.com/matthieu-robin) in cozystack/website#397, cozystack/website#398). -* **[website] Check quotas before an upgrade**: Added troubleshooting documentation for checking resource quotas before upgrades ([**@nbykov0**](https://github.com/nbykov0) in cozystack/website#405). -* **[website] Update support documentation**: Updated support documentation with current contact information ([**@xrmtech-isk**](https://github.com/xrmtech-isk) in cozystack/website#420). -* **[website] Correct typo in kubeconfig reference in Kubernetes installation guide**: Fixed documentation typo in kubeconfig reference ([**@shkarface**](https://github.com/shkarface) in cozystack/website#414). - -## Breaking Changes & Upgrade Notes - -* **[api] CozystackResourceDefinition renamed to ApplicationDefinition**: The `CozystackResourceDefinition` CRD has been renamed to `ApplicationDefinition`. Migration 24 handles the transition automatically during upgrade ([**@kvaps**](https://github.com/kvaps) in #1864). - -* **[platform] Certificate issuer configuration parameters renamed**: The `publishing.certificates.issuerType` field is renamed to `publishing.certificates.solver`, and the value `cloudflare` is renamed to `dns01`. A new `publishing.certificates.issuerName` field (default: `letsencrypt-prod`) is added. Migration 32 automatically converts existing configurations — no manual action required ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2077). - -* **[vpc] VPC subnets definition migrated from map to array format**: VPC subnets are now defined as `[]Subnet` with an explicit `name` field instead of `map[string]Subnet`. Migration 30 handles the conversion automatically ([**@kvaps**](https://github.com/kvaps) in #2052). - -* **[vm] virtual-machine application replaced by vm-disk and vm-instance**: The legacy `virtual-machine` application has been fully replaced. Migration 28 automatically converts existing VMs to the new architecture ([**@kvaps**](https://github.com/kvaps) in #2040). - -* **[mysql] mysql application renamed to mariadb**: Existing MySQL deployments are automatically renamed to MariaDB via migration 27 ([**@kvaps**](https://github.com/kvaps) in #2026). - -### Upgrade Guide - -To upgrade from v0.41.x to v1.0.0: -1. **Backup your cluster** before upgrading. -2. Run the provided migration script: `hack/migrate-to-version-1.0.sh`. -3. The 33 incremental migration steps will automatically handle all resource renaming, configuration conversion, CRD adoption, and secret cleanup. -4. Refer to the [upgrade documentation](https://cozystack.io/docs/v1/upgrade) for detailed instructions and troubleshooting. - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@androndo**](https://github.com/androndo) -* [**@cheese**](https://github.com/cheese) -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@IvanStukov**](https://github.com/IvanStukov) -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@klinch0**](https://github.com/klinch0) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@lllamnyp**](https://github.com/lllamnyp) -* [**@matthieu-robin**](https://github.com/matthieu-robin) -* [**@mattia-eleuteri**](https://github.com/mattia-eleuteri) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@nbykov0**](https://github.com/nbykov0) -* [**@shkarface**](https://github.com/shkarface) -* [**@sircthulhu**](https://github.com/sircthulhu) -* [**@xrmtech-isk**](https://github.com/xrmtech-isk) - -### New Contributors - -We're excited to welcome our first-time contributors: - -* [**@cheese**](https://github.com/cheese) - First contribution! -* [**@IvanStukov**](https://github.com/IvanStukov) - First contribution! -* [**@kitsunoff**](https://github.com/kitsunoff) - First contribution! -* [**@shkarface**](https://github.com/shkarface) - First contribution! -* [**@xrmtech-isk**](https://github.com/xrmtech-isk) - First contribution! - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.41.0...v1.0.0 diff --git a/docs/changelogs/v1.0.1.md b/docs/changelogs/v1.0.1.md deleted file mode 100644 index 2faf2755..00000000 --- a/docs/changelogs/v1.0.1.md +++ /dev/null @@ -1,21 +0,0 @@ - - -## Fixes - -* **[platform] Prevent cozystack-version ConfigMap from deletion**: Added resource protection to prevent the `cozystack-version` ConfigMap from being accidentally deleted, improving platform stability and reliability ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2112, #2114). - -* **[installer] Add keep annotation to Namespace and update migration script**: Added `helm.sh/resource-policy: keep` annotation to the `cozy-system` Namespace in the installer Helm chart to prevent Helm from deleting the namespace (and all HelmReleases within it) when the installer release is removed. The v1.0 migration script is also updated to annotate the `cozy-system` namespace and `cozystack-version` ConfigMap with this policy before migration ([**@kvaps**](https://github.com/kvaps) in #2122, #2123). - -* **[dashboard] Add FlowSchema to exempt BFF from API throttling**: Added a `cozy-dashboard-exempt` FlowSchema to exempt the dashboard Back-End-for-Frontend (BFF) service account from Kubernetes API Priority and Fairness throttling. Previously, the BFF fell under the `workload-low` priority level, causing 429 (Too Many Requests) errors under load, resulting in dashboard unresponsiveness ([**@kvaps**](https://github.com/kvaps) in #2121, #2124). - -## Documentation - -* **[website] Replace bundles documentation with variants**: Renamed the "Bundles" documentation section to "Variants" to match current Cozystack terminology. Removed deprecated variants (`iaas-full`, `distro-full`, `distro-hosted`) and added new variants: `default` (PackageSources only, for manual package management via cozypkg) and `isp-full-generic` (full PaaS/IaaS on k3s, kubeadm, or RKE2). Updated all cross-references throughout the documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website#433). - -* **[website] Add step to protect namespace before upgrading**: Updated the cluster upgrade guide and v0.41→v1.0 migration guide with a required step to annotate the `cozy-system` namespace and `cozystack-version` ConfigMap with `helm.sh/resource-policy=keep` before running `helm upgrade`, preventing accidental namespace deletion ([**@kvaps**](https://github.com/kvaps) in cozystack/website#435). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0...v1.0.1 diff --git a/docs/changelogs/v1.0.2.md b/docs/changelogs/v1.0.2.md deleted file mode 100644 index fad9275e..00000000 --- a/docs/changelogs/v1.0.2.md +++ /dev/null @@ -1,19 +0,0 @@ - - -## Fixes - -* **[platform] Suspend cozy-proxy if it conflicts with installer release during migration**: Added a check in the v0.41→v1.0 migration script to detect and automatically suspend the `cozy-proxy` HelmRelease when its `releaseName` is set to `cozystack`, which conflicts with the installer release and would cause `cozystack-operator` deletion during the upgrade ([**@kvaps**](https://github.com/kvaps) in #2128, #2130). - -* **[platform] Fix off-by-one error in run-migrations script**: Fixed a bug in the migration runner where the first required migration was always skipped due to an off-by-one error in the migration range calculation, ensuring all upgrade steps execute correctly ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2126, #2132). - -* **[system] Fix Keycloak proxy configuration for v26.x**: Replaced the deprecated `KC_PROXY=edge` environment variable with `KC_PROXY_HEADERS=xforwarded` and `KC_HTTP_ENABLED=true` in the Keycloak StatefulSet template. `KC_PROXY` was removed in Keycloak 26.x, previously causing "Non-secure context detected" warnings and broken cookie handling when running behind a reverse proxy with TLS termination ([**@sircthulhu**](https://github.com/sircthulhu) in #2125, #2134). - -* **[dashboard] Allow clearing instanceType field and preserve newlines in secret copy**: Added `allowEmpty: true` to the `instanceType` field in the VMInstance form so users can explicitly clear it to use custom KubeVirt resources without a named instance type. Also fixed newline preservation when copying secrets with CMD+C ([**@sircthulhu**](https://github.com/sircthulhu) in #2135, #2137). - -* **[dashboard] Restore stock-instance sidebars for namespace-level pages**: Restored `stock-instance-api-form`, `stock-instance-api-table`, `stock-instance-builtin-form`, and `stock-instance-builtin-table` sidebar resources that were inadvertently removed in #2106. Without these sidebars, namespace-level pages such as Backup Plans rendered as empty pages with no interactive content ([**@sircthulhu**](https://github.com/sircthulhu) in #2136, #2138). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.1...v1.0.2 diff --git a/docs/changelogs/v1.0.3.md b/docs/changelogs/v1.0.3.md deleted file mode 100644 index 27ae6720..00000000 --- a/docs/changelogs/v1.0.3.md +++ /dev/null @@ -1,17 +0,0 @@ - - -## Fixes - -* **[platform] Fix package name conversion in migration script**: Fixed the `migrate-to-version-1.0.sh` script to correctly prepend the `cozystack.` prefix when converting `BUNDLE_DISABLE` and `BUNDLE_ENABLE` package name lists, ensuring packages are properly identified during the v0.41→v1.0 upgrade ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2144, #2148). - -## Documentation - -* **[website] Add white labeling guide**: Added a comprehensive guide for configuring white labeling (branding) in Cozystack v1, covering Dashboard fields (`titleText`, `footerText`, `tenantText`, `logoText`, `logoSvg`, `iconSvg`) and Keycloak fields (`brandName`, `brandHtmlName`). Includes SVG preparation workflow with theme-aware template variables, portable base64 encoding, and migration notes from the v0 ConfigMap approach ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#441). - -* **[website] Actualize backup and recovery documentation**: Reworked the backup and recovery docs to be user-focused, separating operator and tenant workflows. Added tenant-facing documentation for `BackupJob` and `Plan` resources and status inspection commands, and added a new Velero administration guide for operators covering storage credentials and backup storage configuration ([**@androndo**](https://github.com/androndo) in cozystack/website#434). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.2...v1.0.3 diff --git a/docs/changelogs/v1.0.4.md b/docs/changelogs/v1.0.4.md deleted file mode 100644 index 4c55e2f3..00000000 --- a/docs/changelogs/v1.0.4.md +++ /dev/null @@ -1,25 +0,0 @@ - - -## Fixes - -* **[system] Fix Keycloak probe crashloop with management port health endpoints**: Fixed a crashloop where Keycloak 26.x was endlessly restarting because liveness and readiness probes were sending HTTP requests to port 8080. Keycloak 26.x redirects all requests on port 8080 to `KC_HOSTNAME` (HTTPS), and since kubelet does not follow redirects, probes failed, eventually triggering container restarts. The fix switches probes to the dedicated management port 9000 (`/health/live`, `/health/ready`) enabled via `KC_HEALTH_ENABLED=true`, exposes management port 9000, and adds a `startupProbe` with appropriate failure thresholds for better startup tolerance ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2162, #2178). - -* **[system] Fix etcd-operator deprecated kube-rbac-proxy image**: Replaced the deprecated `gcr.io/kubebuilder/kube-rbac-proxy:v0.16.0` image with `quay.io/brancz/kube-rbac-proxy:v0.18.1` in the vendored etcd-operator chart. The GCR-hosted image became unavailable after March 18, 2025, causing etcd-operator pods to fail on image pull ([**@kvaps**](https://github.com/kvaps) in #2181, #2183). - -* **[platform] Fix VM MAC address not preserved during virtual-machine to vm-instance migration**: During the `virtual-machine` → `vm-instance` migration (script 29), VM MAC addresses were not preserved. Kube-OVN reads MAC addresses exclusively from the pod annotation `ovn.kubernetes.io/mac_address`, not from `spec.macAddress` of the IP resource. Without this annotation, migrated VMs received a new random MAC address, breaking OS-level network configuration that matches by MAC (e.g., netplan). The fix adds a Helm `lookup` in the vm-instance chart template to read the Kube-OVN IP resource and automatically inject the MAC and IP addresses as pod annotations ([**@sircthulhu**](https://github.com/sircthulhu) in #2169, #2191). - -* **[dashboard] Fix External IPs page showing empty rows**: Fixed the External IPs administration page displaying empty rows instead of service data. The `EnrichedTable` configuration in the `external-ips` factory was using incorrect property names — replaced `clusterNamePartOfUrl` with `cluster` and changed `pathToItems` from array format to dot-path string format, matching the convention used by all other `EnrichedTable` instances ([**@IvanHunters**](https://github.com/IvanHunters) in #2175, #2192). - -* **[dashboard] Fix disabled/hidden state reset on MarketplacePanel reconciliation**: Fixed a bug where the dashboard controller was hardcoding `disabled=false` and `hidden=false` on every reconcile loop, overwriting changes made through the dashboard UI. Services disabled or hidden via the marketplace panel now correctly retain their state after controller reconciliation ([**@IvanHunters**](https://github.com/IvanHunters) in #2176, #2202). - -* **[dashboard] Fix hidden MarketplacePanel resources appearing in sidebar menu**: Fixed the sidebar navigation showing all resources regardless of their MarketplacePanel `hidden` state. The controller now fetches MarketplacePanels during sidebar reconciliation and filters out resources where `hidden=true`, ensuring that hiding a resource from the marketplace also removes it from the sidebar navigation. Listing failures are non-fatal — if the configuration fetch fails, no hiding is applied and the dashboard remains functional ([**@IvanHunters**](https://github.com/IvanHunters) in #2177, #2204). - -## Documentation - -* **[website] Add OIDC self-signed certificates configuration guide**: Added a comprehensive guide for configuring OIDC authentication with Keycloak when using self-signed certificates (the default in Cozystack). Covers Talos machine configuration with certificate mounting and host entries, kubelogin setup instructions, and a troubleshooting section. The guide is available for both v0 and v1 versioned documentation paths ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#443). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.3...v1.0.4 diff --git a/docs/changelogs/v1.0.5.md b/docs/changelogs/v1.0.5.md deleted file mode 100644 index 51f01143..00000000 --- a/docs/changelogs/v1.0.5.md +++ /dev/null @@ -1,29 +0,0 @@ - - -## Fixes - -* **[api] Fix spurious OpenAPI post-processing errors for non-apps group versions**: The API server no longer logs false errors while generating OpenAPI specs for core and other non-`apps.cozystack.io` group versions. The post-processor now exits early when the base `Application` schemas are absent, reducing noisy startup logs without affecting application schema generation ([**@kvaps**](https://github.com/kvaps) in #2212, #2216). - -## Documentation - -* **[website] Add `DependenciesNotReady` troubleshooting and correct packages management build target**: Added a troubleshooting guide for packages stuck in `DependenciesNotReady`, including how to inspect operator logs and identify missing dependencies, and fixed the outdated `make image-cozystack` command to `make image-packages` in the packages management guide ([**@kvaps**](https://github.com/kvaps) in cozystack/website#450). - -* **[website] Clarify operator-first installation order**: Reordered the platform installation guide and tutorial so users install the Cozystack operator before preparing and applying the Platform Package, matching the rest of the installation docs and reducing setup confusion during fresh installs ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#449). - -* **[website] Add automated installation guide for Ansible**: Added end-to-end documentation for deploying Cozystack with the `cozystack.installer` Ansible collection, including inventory examples, distro-specific playbooks, configuration reference, verification steps, and explicit version pinning guidance to help operators automate installs safely ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#442). - -* **[website] Expand CA rotation operations guide**: Completed the CA rotation documentation with separate Talos and Kubernetes certificate rotation procedures, dry-run preview steps, and post-rotation guidance for fetching updated `talosconfig` and `kubeconfig` files after certificate changes ([**@kvaps**](https://github.com/kvaps) in cozystack/website#406). - -* **[website] Improve backup operations documentation**: Enhanced the operator backup and recovery guide with clearer Velero enablement steps, concrete provider and bucket examples, and more useful commands for inspecting backups, schedules, restores, CRD status, and logs ([**@androndo**](https://github.com/androndo) in cozystack/website#440). - -* **[website] Add custom metrics collection guide**: Added a monitoring guide showing how tenants can expose their own Prometheus exporters through `VMServiceScrape` and `VMPodScrape`, including namespace labeling requirements, example manifests, verification steps, and troubleshooting advice ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#444). - -* **[website] Document PackageSource and Package architecture**: Added a Key Concepts reference covering `PackageSource` and `Package` reconciliation flow, dependency handling, update propagation, rollback behavior, FluxPlunger recovery, and the `cozypkg` CLI for package management ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#445). - -* **[website] Refresh v1 application and platform documentation**: Fixed the documentation auto-update flow and published a broad v1 documentation refresh covering newly documented applications, updated naming and navigation, virtualization and platform content updates, and reorganized versioned docs pages ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#439). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.4...v1.0.5 diff --git a/docs/changelogs/v1.0.6.md b/docs/changelogs/v1.0.6.md deleted file mode 100644 index c65c5fd5..00000000 --- a/docs/changelogs/v1.0.6.md +++ /dev/null @@ -1,21 +0,0 @@ - - -## Fixes - -* **[kubernetes] Fix CiliumNetworkPolicy endpointSelector for multi-node RWX volumes**: When an NFS-backed RWX volume is published to multiple VMs, the network policy's `endpointSelector` was only capturing the first VM. Subsequent volume publications added owner references but never broadened the selector, causing Cilium to block NFS egress and making mounts hang on all nodes except the first. The fix switches from `matchLabels` to `matchExpressions` (`operator: In`) so the selector lists all VM names and is rebuilt whenever owner references change ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2227, #2228). - -* **[dashboard] Fix dashboard authentication failures after secret recreation**: Added a `secret-hash` annotation containing the SHA256 hash of the client secret to the dashboard `KeycloakClient` resource. Without this annotation, if the `dashboard-client` Secret was recreated (e.g. after an upgrade or reinstall), the `KeycloakClient` spec stayed unchanged, the EDP Keycloak operator skipped reconciliation, and Keycloak kept the stale secret — causing dashboard authentication failures. Now any secret value change updates the annotation hash, triggering operator reconciliation and syncing the new secret to Keycloak ([**@sircthulhu**](https://github.com/sircthulhu) in #2231, #2240). - -* **[etcd] Fix defrag CronJob accumulating pods during cluster upgrades**: Added protective limits to the etcd defragmentation CronJob to prevent job pile-up when etcd is temporarily unavailable during upgrades. Without `concurrencyPolicy: Forbid`, new jobs kept being created hourly while previous ones were still failing, accumulating hundreds of running/failed pods across tenants. The fix adds `concurrencyPolicy: Forbid`, a `startingDeadlineSeconds: 300` guard against missed schedules, a 30-minute job timeout, and limits retries to 2 ([**@sircthulhu**](https://github.com/sircthulhu) in #2233, #2235). - -## Documentation - -* **[website] Document `keycloakInternalUrl` platform value**: Added documentation for the `authentication.oidc.keycloakInternalUrl` platform value to the Platform Package Reference, Self-Signed Certificates guide, and Enable OIDC Server pages. This value routes dashboard backend OIDC requests through the internal Keycloak service, which is useful in environments with self-signed certificates ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#452). - -* **[website] Publish Cozystack v1.0 release announcement**: Added the official Cozystack v1.0 release announcement blog post and supporting images, celebrating the first stable release of the platform ([**@tym83**](https://github.com/tym83) in cozystack/website#453, cozystack/website#454). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.5...v1.0.6 diff --git a/docs/changelogs/v1.0.7.md b/docs/changelogs/v1.0.7.md deleted file mode 100644 index 942115bf..00000000 --- a/docs/changelogs/v1.0.7.md +++ /dev/null @@ -1,27 +0,0 @@ - - -## Fixes - -* **[platform] Fix tenant admins unable to create FoundationDB, Harbor, MongoDB, OpenBAO, OpenSearch, Qdrant, and VPN applications**: The `cozy:tenant:admin:base` ClusterRole was missing RBAC entries for `foundationdbs`, `harbors`, `mongodbs`, `openbaos`, `opensearches`, `qdrants`, and `vpns` resources from `apps.cozystack.io`. Without these permissions, tenant admins could not create these applications — the "Add" button was inactive in the dashboard. The fix adds all seven missing resource verbs ([**@sircthulhu**](https://github.com/sircthulhu) in #2268, #2271). - -* **[system] Fix 403 error on Service details page for tenant users**: The `cozy:tenant:base` and `cozy:tenant:view:base` ClusterRoles were missing read permissions for `discovery.k8s.io/endpointslices`. The dashboard requests EndpointSlices to display the "Pod serving" section on the Service details page, and without this permission tenant users received a 403 error. The fix adds `get`, `list`, and `watch` verbs for endpointslices to both tenant roles ([**@sircthulhu**](https://github.com/sircthulhu) in #2257, #2284). - -* **[dashboard] Fix "Pod serving" table showing "Raw:" prefixes and "Invalid Date" on Service details page**: The EndpointSlice table on the service details page displayed raw data and broken timestamps because the `EnrichedTable` component referenced the `factory-kube-service-details-endpointslice` customization ID which had no corresponding `CustomColumnsOverride`. The fix adds column definitions for Pod (`.targetRef.name`), Addresses (`.addresses`), Ready (`.conditions.ready`), and Node (`.nodeName`) ([**@sircthulhu**](https://github.com/sircthulhu) in #2266, #2282). - -* **[dashboard] Fix broken backup menu links missing cluster context**: Backup resources (plans, backupjobs, backups) are not `ApplicationDefinitions`, so `ensureNavigation()` never created their `baseFactoriesMapping` entries. Without these mappings, the OpenUI frontend could not resolve the `{cluster}` context for backup pages, producing broken sidebar links with an empty cluster segment (e.g. `/openapi-ui//tenant-root/...` instead of `/openapi-ui/default/tenant-root/...`). The fix adds the three missing static entries to the Navigation resource ([**@sircthulhu**](https://github.com/sircthulhu) in #2232, #2270). - -* **[linstor] Fix swapped VMPodScrape job labels causing incorrect alerts**: The `job` labels in the `cozy-linstor` VictoriaMetrics `VMPodScrape` templates were swapped: `linstor-satellite` metrics were relabeled as `job=linstor-controller` and vice versa. This caused `linstorControllerOffline` alerts to fire against satellite endpoints (`:9942`) while reporting the controller as unreachable. The fix ensures `linstor-satellite` metrics keep `job=linstor-satellite` and `linstor-controller` metrics keep `job=linstor-controller`, restoring consistent alerting and dashboard semantics ([**@sasha-sup**](https://github.com/sasha-sup) in #2264, #2288). - -* **[piraeus-operator] Fix LINSTOR satellite alert annotations and reduce false-positive alerts**: Two issues in the LINSTOR alerts shipped by `cozy-piraeus-operator` were fixed. First, `linstorSatelliteErrorRate` used a non-existent `name` label in annotations, resulting in `Satellite ""` in alert notifications — corrected to use `{{ $labels.hostname }}`. Second, `linstorSatelliteErrorRate` produced false positives when the `linstor-controller` scrape flapped and historical `linstor_error_reports_count` counters reappeared inside the alert window — fixed by requiring stable `up{job="linstor-controller"}` for the full 15-minute window. Additionally, the controller availability alert was split to add a dedicated warning for metrics scrape failures with a 10-minute hold time to reduce transient noise ([**@sasha-sup**](https://github.com/sasha-sup) in #2265, #2287). - -## Documentation - -* **[website] Add Backup and Recovery guide for VMInstance and VMDisk**: Replaced the generic Kubernetes Backup and Recovery guide with a virtualization-focused Backup and Recovery doc covering VMInstance and VMDisk one-off and scheduled backups, restores, status checks, and troubleshooting (including Velero-related notes) ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#456). - -* **[website] Update developer guide with operator-driven architecture and OCIRepository/migration flow**: Rewrote the development guide to describe the operator-driven in-cluster architecture, bootstrap flow, operator responsibilities, and platform install/update sequence. Added documentation for OCIRepositories and the migration flow with migration hook examples and sequencing rules for pre-upgrade/install migrations. Also updated the concepts guide with the two-repository update model, dependency ordering rules, namespace creation behavior, and cluster-wide values injection ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#458). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.6...v1.0.7 diff --git a/docs/changelogs/v1.1.0.md b/docs/changelogs/v1.1.0.md deleted file mode 100644 index ad61c1a6..00000000 --- a/docs/changelogs/v1.1.0.md +++ /dev/null @@ -1,126 +0,0 @@ - - -# Cozystack v1.1.0 - -Cozystack v1.1.0 delivers a major expansion of the managed application catalog with **OpenBAO** (open-source HashiCorp Vault fork) for secrets management, comprehensive **tiered object storage** with SeaweedFS storage pools, a new bucket **user model** with per-user credentials and S3 login support, **RabbitMQ version selection**, and **MongoDB Grafana dashboards**. The dashboard gains storageClass dropdowns for all stateful apps. This release also incorporates all fixes from the v1.0.x patch series. - -## Feature Highlights - -### OpenBAO: Managed Secrets Management Service - -Cozystack now ships **OpenBAO** as a fully managed PaaS application — an open-source fork of HashiCorp Vault providing enterprise-grade secrets management. Users can deploy OpenBAO instances in standalone mode (single replica with file storage) or in high-availability Raft mode (multiple replicas with integrated Raft consensus), with the mode switching automatically based on the `replicas` field. - -Each OpenBAO instance gets TLS enabled by default via cert-manager self-signed certificates, with DNS SANs covering all service endpoints and pod addresses. The Vault injector and CSI provider are intentionally disabled (they are cluster-scoped components not safe for per-tenant use). OpenBAO requires manual initialization and unsealing by design — no auto-unseal is configured. - -A full end-to-end E2E test covers the complete lifecycle: deploy, wait for certificate and API readiness, init, unseal, verify, and cleanup. OpenBAO is available in the application catalog for tenant namespaces. - -### SeaweedFS Tiered Storage Pools - -SeaweedFS now supports **tiered storage pools** — operators can define separate storage pools per disk type (SSD, HDD, NVMe) in the `volume.pools` field (Simple topology) or `volume.zones[name].pools` (MultiZone topology). Each pool creates an additional Volume StatefulSet alongside the default one, with SeaweedFS distinguishing storage via the `-disk=` flag on volume servers. - -Each pool automatically generates its own set of COSI resources: a standard `BucketClass`, a `-lock` BucketClass (COMPLIANCE mode, 365-day retention), a read-write `BucketAccessClass`, and a `-readonly` BucketAccessClass. This allows applications to place data on specific storage tiers and request appropriate access policies per pool. - -In MultiZone topology, pools are defined per zone and each zone × pool combination creates a dedicated StatefulSet (e.g., `us-east-ssd`, `us-west-hdd`), with nodes selected via `topology.kubernetes.io/zone` labels. Existing deployments with no pools defined produce output identical to previous versions — no migration is required. - -### Bucket User Model with S3 Login - -The bucket application introduces a new **user model** for access management. Instead of a single implicit BucketAccess resource, operators now define a `users` map where each entry creates a dedicated `BucketAccess` with its own credentials secret and an optional `readonly` flag. The S3 Manager UI has been updated with a login screen that uses per-session credentials from the user's own secret, replacing the previous basic-auth approach. - -Two new bucket parameters are available: `locking` provisions from the `-lock` BucketClass (COMPLIANCE mode, 365-day object lock retention) for write-once-read-many use cases, and `storagePool` selects a specific pool's BucketClass for tiered storage placement. The COSI driver has been updated to v0.3.0 to support the new `diskType` parameter. - -**⚠️ Breaking change**: The implicit default BucketAccess resource is no longer created. Existing buckets that relied on the single auto-generated BucketAccess will need to explicitly define users in the `users` map after upgrading. - -### RabbitMQ Version Selection - -RabbitMQ instances now support a configurable **version selector** (`version` field with values: `v4.2`, `v4.1`, `v4.0`, `v3.13`; default `v4.2`). The chart validates the selection at deploy time and uses it to pin the runtime image, giving operators control over the RabbitMQ release channel per instance. An automatic migration backfills the `version` field on all existing RabbitMQ resources to `v4.2`. - -## Major Features and Improvements - -* **[apps] Add OpenBAO as a managed secrets management service**: Deployed as a PaaS application with standalone (file storage) and HA Raft modes, TLS enabled by default via cert-manager, injector and CSI provider disabled for tenant safety, and a full E2E lifecycle test ([**@lexfrei**](https://github.com/lexfrei) in #2059). - -* **[seaweedfs] Add storage pools support for tiered storage**: Added `volume.pools` (Simple) and `volume.zones[name].pools` (MultiZone) for per-disk-type StatefulSets, zone overrides (`nodeSelector`, `storageClass`, `dataCenter`), per-pool COSI BucketClass and BucketAccessClass resources, and bumped seaweedfs-cosi-driver to v0.3.0 ([**@sircthulhu**](https://github.com/sircthulhu) in #2097). - -* **[apps][system] Add bucket user model with locking and storage pool selection**: Replaced implicit BucketAccess with per-user `users` map, added `locking` and `storagePool` parameters, renamed COSI BucketClass suffix from `-worm` to `-lock`, added `-readonly` BucketAccessClass for all topologies, and updated S3 Manager with login screen using per-user credentials ([**@IvanHunters**](https://github.com/IvanHunters) in #2119). - -* **[rabbitmq] Add version selection for RabbitMQ instances**: Added `version` field (`v4.2`, `v4.1`, `v4.0`, `v3.13`) with chart-level validation, default `v4.2`, and an automatic migration to backfill the field on existing instances ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2092). - -* **[system] Add MongoDB Overview and InMemory Details Grafana dashboards**: Added two comprehensive Grafana dashboards for MongoDB monitoring — Overview (command operations, connections, cursors, query efficiency, write time) and InMemory Details (WiredTiger cache, transactions, concurrency, eviction). Dashboards are registered in `dashboards.list` for automatic GrafanaDashboard CRD generation ([**@IvanHunters**](https://github.com/IvanHunters) in #2158). - -* **[dashboard] Add storageClass dropdown for all stateful apps**: Replaced the free-text `storageClass` input with an API-backed dropdown listing available StorageClasses from the cluster. Affects ClickHouse, Harbor, HTTPCache, Kubernetes, MariaDB, MongoDB, NATS, OpenBAO, Postgres, Qdrant, RabbitMQ, Redis, VMDisk (top-level `storageClass`), FoundationDB (`storage.storageClass`), and Kafka (`kafka.storageClass`, `zookeeper.storageClass`) ([**@sircthulhu**](https://github.com/sircthulhu) in #2131). - -* **[bucket] Add readonly S3 access credentials**: Added a readonly `BucketAccessClass` to the SeaweedFS COSI chart and updated the bucket application to automatically provision two sets of S3 credentials per bucket: read-write (for UI) and readonly ([**@IvanHunters**](https://github.com/IvanHunters) in #2105). - -* **[dashboard] Hide sidebar on cluster-level pages when no tenant selected**: Fixed broken URLs with double `//` on the main cluster page (before tenant selection) by clearing `CUSTOMIZATION_SIDEBAR_FALLBACK_ID` so no sidebar renders when no namespace is selected ([**@sircthulhu**](https://github.com/sircthulhu) in #2106). - -* **[cert-manager] Update cert-manager to v1.19.3**: Upgraded cert-manager with new CRDs moved into a dedicated CRD package, added global `nodeSelector` and `hostUsers` (pod user-namespace isolation), and renamed `ServiceMonitor` targetPort default to `http-metrics` ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2070). - -* **[dashboard] Add backupClasses dropdown to Plan/BackupJob forms**: Replaced free-text input for `backupClass` field with an API-backed dropdown populated with available BackupClass resources, making it easier to select the correct backup target ([**@androndo**](https://github.com/androndo) in #2104). - -## Fixes - -* **[platform] Fix package name conversion in migration script**: Fixed the `migrate-to-version-1.0.sh` script to correctly prepend the `cozystack.` prefix when converting `BUNDLE_DISABLE` and `BUNDLE_ENABLE` package name lists, ensuring packages are properly identified during the v0.41→v1.0 upgrade ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2144, #2148). - -* **[backups] Fix RBAC for backup controllers**: Updated RBAC permissions for the backup strategy controller to support enhanced backup and restore capabilities, including Velero integration and status management ([**@androndo**](https://github.com/androndo) in #2145). - -* **[kubernetes] Set explicit MTU for Cilium in tenant clusters**: Set explicit MTU 1350 for Cilium in KubeVirt-based tenant Kubernetes clusters to prevent packet drops caused by VXLAN encapsulation overhead. Cilium's auto-detection does not account for VXLAN overhead (50 bytes) when the VM interface inherits MTU 1400 from the parent OVN/Geneve overlay, causing intermittent connectivity issues and HTTP 499 errors under load ([**@IvanHunters**](https://github.com/IvanHunters) in #2147). - -* **[platform] Prevent cozystack-version ConfigMap from deletion**: Added resource protection annotations to prevent the `cozystack-version` ConfigMap from being accidentally deleted, improving platform stability ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2112, #2114). - -* **[installer] Add keep annotation to Namespace and update migration script**: Added `helm.sh/resource-policy: keep` annotation to the `cozy-system` Namespace in the installer Helm chart to prevent Helm from deleting the namespace and all HelmReleases within it when the installer release is removed. The v1.0 migration script is also updated to annotate the namespace and `cozystack-version` ConfigMap before migration ([**@kvaps**](https://github.com/kvaps) in #2122, #2123). - -* **[dashboard] Add FlowSchema to exempt BFF from API throttling**: Added a `cozy-dashboard-exempt` FlowSchema to exempt the dashboard Back-End-for-Frontend service account from Kubernetes API Priority and Fairness throttling, preventing 429 errors under load ([**@kvaps**](https://github.com/kvaps) in #2121, #2124). - -* **[platform] Suspend cozy-proxy if it conflicts with installer release during migration**: Added a check in the v0.41→v1.0 migration script to detect and suspend the `cozy-proxy` HelmRelease when its `releaseName` is set to `cozystack`, which conflicts with the installer release and would cause `cozystack-operator` deletion during the upgrade ([**@kvaps**](https://github.com/kvaps) in #2128, #2130). - -* **[platform] Fix off-by-one error in run-migrations script**: Fixed a bug in the migration runner where the first required migration was always skipped due to an off-by-one error in the migration range calculation ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2126, #2132). - -* **[system] Fix Keycloak proxy configuration for v26.x**: Replaced the deprecated `KC_PROXY=edge` environment variable with `KC_PROXY_HEADERS=xforwarded` and `KC_HTTP_ENABLED=true` in the Keycloak StatefulSet. `KC_PROXY` was removed in Keycloak 26.x, previously causing "Non-secure context detected" warnings and broken cookie handling behind a reverse proxy with TLS termination ([**@sircthulhu**](https://github.com/sircthulhu) in #2125, #2134). - -* **[dashboard] Allow clearing instanceType field and preserve newlines in secret copy**: Added `allowEmpty: true` to the `instanceType` field in the VMInstance form so users can explicitly clear it to use custom KubeVirt resources without a named instance type. Also fixed newline preservation when copying secrets with CMD+C ([**@sircthulhu**](https://github.com/sircthulhu) in #2135, #2137). - -* **[dashboard] Restore stock-instance sidebars for namespace-level pages**: Restored `stock-instance-api-form`, `stock-instance-api-table`, `stock-instance-builtin-form`, and `stock-instance-builtin-table` sidebar resources that were inadvertently removed in #2106. Without these sidebars, namespace-level pages such as Backup Plans rendered as empty pages ([**@sircthulhu**](https://github.com/sircthulhu) in #2136, #2138). - -## System Configuration - -* **[platform] Disable private key rotation in CA certs**: Set `rotationPolicy: Never` for all CA/root certificates used by system components (ingress-nginx, linstor, linstor-scheduler, seaweedfs, victoria-metrics-operator, kubeovn-webhook, lineage-controller-webhook, cozystack-api, etcd, linstor API/internal) to prevent trust chain problems when CA certificates are reissued ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2113). - -## Development, Testing, and CI/CD - -* **[ci] Add debug improvements for CI tests**: Added extra debug commands for Kubernetes startup diagnostics and improved error output in CI test runs ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2111). - -## Documentation - -* **[website] Add object storage guide (pools, buckets, users)**: Added a comprehensive guide covering SeaweedFS object storage configuration including storage pools for tiered storage, bucket creation with access classes, per-user credential management, and credential rotation procedures ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#438). - -* **[website] Add Build Your Own Platform (BYOP) guide**: Added a new "Build Your Own Platform" guide and split the installation documentation into platform installation and BYOP sub-pages, with cross-references throughout the documentation ([**@kvaps**](https://github.com/kvaps) in cozystack/website#437). - -* **[website] Add white labeling guide**: Added a comprehensive guide for configuring white labeling (branding) in Cozystack v1, covering Dashboard fields (`titleText`, `footerText`, `tenantText`, `logoText`, `logoSvg`, `iconSvg`) and Keycloak fields (`brandName`, `brandHtmlName`). Includes SVG preparation workflow with theme-aware template variables and portable base64 encoding ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#441). - -* **[website] Actualize backup and recovery documentation**: Reworked the backup and recovery docs to be user-focused, separating operator and tenant workflows. Added tenant-facing documentation for `BackupJob` and `Plan` resources and a new Velero administration guide for operators ([**@androndo**](https://github.com/androndo) in cozystack/website#434). - -* **[website] Add step to protect namespace before upgrading**: Updated the cluster upgrade guide and v0.41→v1.0 migration guide with a required step to annotate the `cozy-system` namespace and `cozystack-version` ConfigMap with `helm.sh/resource-policy=keep` before running `helm upgrade` ([**@kvaps**](https://github.com/kvaps) in cozystack/website#435). - -* **[website] Replace bundles documentation with variants**: Renamed the "Bundles" documentation section to "Variants" to match current Cozystack terminology. Removed deprecated variants and added new ones: `default` and `isp-full-generic` ([**@kvaps**](https://github.com/kvaps) in cozystack/website#433). - -* **[website] Fix component values override instructions**: Corrected the component values override documentation to reflect current configuration patterns ([**@kvaps**](https://github.com/kvaps) in cozystack/website#436). - -## Breaking Changes & Upgrade Notes - -* **[bucket] Bucket user model now requires explicit user definitions**: The implicit default `BucketAccess` resource is no longer created automatically. Existing buckets that relied on a single auto-generated credential secret will need to define users explicitly in the `users` map after upgrading. Each user entry creates its own `BucketAccess` resource and credential secret (optionally with `readonly: true`). The COSI BucketClass suffix has also been renamed from `-worm` to `-lock` ([**@IvanHunters**](https://github.com/IvanHunters) in #2119). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@androndo**](https://github.com/androndo) -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@sircthulhu**](https://github.com/sircthulhu) - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.0.0...v1.1.0 diff --git a/docs/changelogs/v1.1.1.md b/docs/changelogs/v1.1.1.md deleted file mode 100644 index 18bb6814..00000000 --- a/docs/changelogs/v1.1.1.md +++ /dev/null @@ -1,23 +0,0 @@ - - -## Fixes - -* **[dashboard] Fix hidden MarketplacePanel resources appearing in sidebar menu**: The sidebar was generated independently from MarketplacePanels, always showing all resources regardless of their `hidden` state. Fixed by fetching MarketplacePanels during sidebar reconciliation and skipping resources where `hidden=true`, so hiding a resource from the marketplace also removes it from the sidebar navigation ([**@IvanHunters**](https://github.com/IvanHunters) in #2177, #2203). - -* **[dashboard] Fix disabled/hidden state overwritten on every MarketplacePanel reconciliation**: The controller was hardcoding `disabled=false` and `hidden=false` on every reconciliation, silently overwriting any user changes made through the dashboard UI. Fixed by reading and preserving the current `disabled`/`hidden` values from the existing resource before updating ([**@IvanHunters**](https://github.com/IvanHunters) in #2176, #2201). - -* **[dashboard] Fix External IPs factory EnrichedTable rendering**: The external-IPs table displayed empty rows because the factory used incorrect `EnrichedTable` properties. Replaced `clusterNamePartOfUrl` with `cluster` and changed `pathToItems` from array to dot-path string format, consistent with all other working `EnrichedTable` instances ([**@IvanHunters**](https://github.com/IvanHunters) in #2175, #2193). - -* **[platform] Fix VM MAC address not preserved during virtual-machine to vm-instance migration**: Kube-OVN reads MAC address exclusively from the pod annotation `ovn.kubernetes.io/mac_address`, not from the IP resource `spec.macAddress`. Without the annotation, migrated VMs received a new random MAC, breaking OS-level network configurations that match by MAC (e.g. netplan). Added a Helm `lookup` for the Kube-OVN IP resource in the vm-instance chart so that MAC and IP addresses are automatically injected as pod annotations when the resource exists ([**@sircthulhu**](https://github.com/sircthulhu) in #2169, #2190). - -* **[etcd-operator] Replace deprecated kube-rbac-proxy image**: The `gcr.io/kubebuilder/kube-rbac-proxy` image became unavailable after Google Container Registry was deprecated. Replaced it with `quay.io/brancz/kube-rbac-proxy` from the original upstream author, restoring etcd-operator functionality ([**@kvaps**](https://github.com/kvaps) in #2181, #2182). - -* **[migrations] Handle missing RabbitMQ CRD in migration 34**: Migration 34 failed with an error when the `rabbitmqs.apps.cozystack.io` CRD did not exist — which occurs on clusters where RabbitMQ was never installed. Added a CRD presence check before attempting to list resources so that migration 34 completes cleanly on such clusters ([**@IvanHunters**](https://github.com/IvanHunters) in #2168, #2180). - -* **[keycloak] Fix Keycloak crashloop due to misconfigured health probes**: Keycloak 26.x redirects all HTTP requests on port 8080 to the configured HTTPS hostname; since kubelet does not follow redirects, liveness and readiness probes failed causing a crashloop. Fixed by enabling `KC_HEALTH_ENABLED=true`, exposing management port 9000, and switching all probes to `/health/live` and `/health/ready` on port 9000. Also added a `startupProbe` for improved startup tolerance ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2162, #2179). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.1.0...v1.1.1 diff --git a/docs/changelogs/v1.1.2.md b/docs/changelogs/v1.1.2.md deleted file mode 100644 index 29dba321..00000000 --- a/docs/changelogs/v1.1.2.md +++ /dev/null @@ -1,25 +0,0 @@ - - -## Fixes - -* **[bucket] Fix S3 Manager endpoint mismatch with COSI credentials**: The S3 Manager UI previously constructed an `s3..` endpoint even though COSI-issued bucket credentials point to the root-level S3 endpoint. This caused login failures with "invalid credentials" despite valid secrets. The deployment now uses the actual endpoint from `BucketInfo`, with the old namespace-based endpoint kept only as a fallback before `BucketAccess` secrets exist ([**@IvanHunters**](https://github.com/IvanHunters) in #2211, #2215). - -* **[platform] Fix spurious OpenAPI post-processing errors on cozystack-api startup**: The OpenAPI post-processor was being invoked for non-`apps.cozystack.io` group versions where the base `Application*` schemas do not exist, producing noisy startup errors on every API server launch. It now skips those non-apps group versions gracefully instead of returning an error ([**@kvaps**](https://github.com/kvaps) in #2212, #2217). - -## Documentation - -* **[website] Add troubleshooting for packages stuck in `DependenciesNotReady`**: Added an operations guide that explains how to diagnose missing package dependencies in operator logs and corrected the packages management development docs to use the current `make image-packages` target ([**@kvaps**](https://github.com/kvaps) in cozystack/website#450). - -* **[website] Reorder installation docs to install the operator before the platform package**: Updated the platform installation guide and tutorial so the setup sequence consistently installs the Cozystack operator first, then prepares and applies the Platform Package, matching the rest of the documentation set ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#449). - -* **[website] Add automated installation guide for the Ansible collection**: Added a full guide for deploying Cozystack with the `cozystack.installer` collection, including inventory examples, distro-specific playbooks, configuration reference, and explicit version pinning guidance ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#442). - -* **[website] Expand monitoring and platform architecture reference docs**: Added a tenant custom metrics collection guide for `VMServiceScrape` and `VMPodScrape`, and documented `PackageSource`/`Package` architecture, reconciliation flow, rollback behavior, and the `cozypkg` workflow in Key Concepts ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#444, cozystack/website#445). - -* **[website] Improve operations guides for CA rotation and Velero backups**: Completed the CA rotation documentation with dry-run and post-rotation credential retrieval steps, and expanded the backup configuration guide with concrete examples, verification commands, and clearer operator procedures ([**@kvaps**](https://github.com/kvaps) in cozystack/website#406; [**@androndo**](https://github.com/androndo) in cozystack/website#440). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.1.1...v1.1.2 diff --git a/docs/changelogs/v1.1.3.md b/docs/changelogs/v1.1.3.md deleted file mode 100644 index f589476e..00000000 --- a/docs/changelogs/v1.1.3.md +++ /dev/null @@ -1,19 +0,0 @@ - - -## Fixes - -* **[kubernetes] Fix CiliumNetworkPolicy endpointSelector not updated for multi-node RWX volumes**: When an NFS-backed RWX volume was published to multiple VMs, the `CiliumNetworkPolicy` `endpointSelector.matchLabels` was set only for the first VM and never broadened on subsequent `ControllerPublishVolume` calls. This caused Cilium to block NFS egress so that mounts hung on all nodes except the first. The selector now uses `matchExpressions` with `operator: In` and is rebuilt whenever owner references are added or removed ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2227, #2229). - -* **[dashboard] Fix dashboard-client secret desynchronization with Keycloak after upgrades**: When the `dashboard-client` Kubernetes Secret was recreated with a new value after an upgrade or reinstall, the `KeycloakClient` spec remained unchanged and the EDP Keycloak operator skipped reconciliation, leaving Keycloak with the stale secret and causing authentication failures for the dashboard. A `secret-hash` annotation containing the SHA256 hash of the client secret is now added to the `KeycloakClient` resource; any secret rotation updates the hash in metadata, triggering operator reconciliation and syncing the new secret to Keycloak ([**@sircthulhu**](https://github.com/sircthulhu) in #2231, #2241). - -* **[etcd] Fix defrag CronJob accumulating hundreds of pods during cluster upgrades**: After upgrading CozyStack, the etcd defrag CronJob could accumulate hundreds of running and failed pods when etcd was temporarily unavailable during the upgrade, because no concurrency or retry limits were configured. Added `concurrencyPolicy: Forbid` to prevent parallel jobs, `startingDeadlineSeconds: 300` to discard missed schedules older than 5 minutes, `failedJobsHistoryLimit: 1` to limit failure retention, `activeDeadlineSeconds: 1800` for a 30-minute per-job timeout, and `backoffLimit: 2` to cap retries ([**@sircthulhu**](https://github.com/sircthulhu) in #2233, #2234). - -## Documentation - -* **[website] Document `keycloakInternalUrl` platform value**: Added reference documentation for the `authentication.oidc.keycloakInternalUrl` platform value to the Platform Package Reference, Self-Signed Certificates guide, and Enable OIDC Server guide, explaining how to route dashboard backend OIDC requests through the internal Keycloak service URL ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#452). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.1.2...v1.1.3 diff --git a/docs/changelogs/v1.1.4.md b/docs/changelogs/v1.1.4.md deleted file mode 100644 index f1e4ede9..00000000 --- a/docs/changelogs/v1.1.4.md +++ /dev/null @@ -1,41 +0,0 @@ - - -## Features and Improvements - -* **[boot-to-talos] Add support for ISO, RAW, and HTTP image sources**: The `boot-to-talos` tool can now use ISO files, raw disk images, and HTTP URLs as Talos image sources in addition to container registry images. This allows bootstrapping nodes in air-gapped environments or from locally stored images without requiring a container registry ([**@lexfrei**](https://github.com/lexfrei) in cozystack/boot-to-talos#13). - -* **[boot-to-talos] Use permanent MAC address for predictable network interface names**: Interface name detection now reads the permanent MAC address directly from sysfs instead of relying on udev data, providing a stable hardware MAC that is unaffected by user modifications to the active MAC address. This makes network interface naming more reliable across reboots and hardware changes ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/boot-to-talos#14). - -## Fixes - -* **[dashboard] Fix broken backup menu links missing cluster context**: Backup resources (plans, backupjobs, backups) are not `ApplicationDefinition`s, so `ensureNavigation()` never created their `baseFactoriesMapping` entries. Without these entries the OpenUI frontend could not resolve the `{cluster}` context for backup pages, producing broken sidebar links with an empty cluster segment (e.g. `/openapi-ui//tenant-root/...`). The missing `baseFactoriesMapping` entries for all backup resource types are now added to the static `Navigation` resource ([**@sircthulhu**](https://github.com/sircthulhu) in #2232, #2269). - -* **[platform] Fix tenant admins unable to create FoundationDB, Harbor, MongoDB, OpenBAO, OpenSearch, Qdrant, and VPN applications**: The `cozy:tenant:admin:base` `ClusterRole` was missing seven application resources from `apps.cozystack.io` (`foundationdbs`, `harbors`, `mongodbs`, `openbaos`, `opensearches`, `qdrants`, `vpns`). Without these permissions, tenant admins could not create these applications — the "Add" button was inactive in the dashboard. The missing resources have been added to the ClusterRole ([**@sircthulhu**](https://github.com/sircthulhu) in #2268, #2272). - -* **[dashboard] Fix StorageClass dropdown showing "Error" in application forms**: The dashboard UI fetches `StorageClass` resources to populate dropdowns (e.g. in the Postgres form), but the `cozystack-dashboard-readonly` `ClusterRole` did not include `storage.k8s.io/storageclasses`. This caused authenticated users to see "Error" instead of the StorageClass name. `get`/`list`/`watch` permissions for `storageclasses` have been added to the dashboard readonly role ([**@sircthulhu**](https://github.com/sircthulhu) in #2267, #2274). - -* **[system] Fix 403 error on Service details page by granting tenants read access to EndpointSlices**: The dashboard requested `EndpointSlices` from the `discovery.k8s.io` API group to display the "Pod serving" section on the Service details page, but `cozy:tenant:base` and `cozy:tenant:view:base` `ClusterRole`s lacked permissions for this resource. Tenant users received a 403 error when opening the Service details page. `get`/`list`/`watch` permissions for `endpointslices` have been added to both tenant ClusterRoles ([**@sircthulhu**](https://github.com/sircthulhu) in #2257, #2285). - -* **[dashboard] Fix "Pod serving" table displaying "Raw:" and "Invalid Date" on Service details page**: The Service details page `EndpointSlice` table showed "Raw:" prefixes and "Invalid Date" values because the `EnrichedTable` referenced `customizationId` `factory-kube-service-details-endpointslice` which had no corresponding `CustomColumnsOverride`. Column definitions for Pod (`.targetRef.name`), Addresses (`.addresses`), Ready (`.conditions.ready`), and Node (`.nodeName`) have been added ([**@sircthulhu**](https://github.com/sircthulhu) in #2266, #2283). - -* **[piraeus-operator] Fix LINSTOR satellite alert labels, reduce scrape-flap false positives, and improve controller alerting**: Three alerting issues in `cozy-piraeus-operator` have been addressed: (1) `linstorSatelliteErrorRate` used a non-existent `name` label in annotations, resulting in `Satellite ""` in alert notifications — corrected to `{{ $labels.hostname }}`; (2) `linstorSatelliteErrorRate` could produce false positives when the `linstor-controller` scrape flapped and historical `linstor_error_reports_count` counters reappeared inside the alert window — fixed by adding a minimum scrape-count guard; (3) The `LinstorControllerOffline` alert has been split into separate availability and metrics-availability alerts with configurable hold time to reduce noise during brief connectivity interruptions ([**@sasha-sup**](https://github.com/sasha-sup) in #2265, #2286). - -* **[linstor] Fix swapped VMPodScrape job labels causing incorrect controller offline alerts**: The `cozy-linstor` VictoriaMetrics `VMPodScrape` templates had the `job` relabeling rules swapped: `linstor-satellite` metrics were labeled as `job=linstor-controller` and vice versa. This caused `linstorControllerOffline` alerts to fire for satellite endpoints (`:9942`) while reporting that the controller was unreachable. The `job` labels are now correctly assigned to their respective targets ([**@sasha-sup**](https://github.com/sasha-sup) in #2264, #2289). - -* **[boot-to-talos] Fix triple-fault on hosts with 5-level paging (LA57) enabled**: On hosts with `CONFIG_X86_5LEVEL=y` in the kernel, kexec into Talos caused a triple-fault because the Talos kernel does not support 5-level page tables. `boot-to-talos` now detects LA57 before kexec and automatically patches GRUB with `no5lvl`, runs `update-grub`, and reboots. After reboot with 5-level paging disabled, `boot-to-talos` proceeds normally ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/boot-to-talos#15). - -* **[boot-to-talos] Fix EFI boot entry creation when using loop device images**: Talos installer skips EFI variable creation when running on loop devices. `boot-to-talos` now creates a proper UEFI boot entry with an `HD()` device path pointing to the real target disk's ESP by reading the GPT partition table from the target disk after image copy, instead of relying on the Talos installer ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos#16). - -* **[talm] Fix silent empty output when no template files are specified**: Running `talm template` without `--file` or `--template` flags previously produced minimal or empty output without any error. Validation has been added to `engine.Render` to return a clear error message when no template files are specified, making misconfigured invocations immediately apparent ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#112). - -## Documentation - -* **[website] Add documentation for VMInstance and VMDisk backups**: Added a new virtualization-focused Backup and Recovery guide covering one-off and scheduled backups for `VMInstance` and `VMDisk` resources, restore procedures, status verification commands, and troubleshooting notes including Velero-related issues ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#456). - -* **[website] Update developer guide with operator-driven architecture and OCIRepository migration flow**: Rewrote the development guide to describe the operator-driven in-cluster architecture, bootstrap flow, operator responsibilities, and the platform install/update sequence. Added an "OCIRepositories and Migration Flow" section with migration hook examples and sequencing rules for pre-upgrade hooks ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#458). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.1.3...v1.1.4 diff --git a/docs/changelogs/v1.1.5.md b/docs/changelogs/v1.1.5.md deleted file mode 100644 index e756bdd9..00000000 --- a/docs/changelogs/v1.1.5.md +++ /dev/null @@ -1,13 +0,0 @@ - - -## Fixes - -* **[platform] Prevent installed packages deletion**: Added the `helm.sh/resource-policy: keep` annotation to all platform packages. Previously, moving a package to `disabledPackages` or removing it from `enabledPackages` caused Helm to automatically delete it, contradicting the documented behavior that requires the platform administrator to manually delete packages when needed ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2273, #2298). - -* **[linstor] Fix TCP port mismatches after toggle-disk operations causing DRBD resources to enter StandAlone state**: During toggle-disk operations, `removeLayerData()` freed TCP ports from the number pool and `ensureStackDataExists()` could then allocate different ports. If a satellite missed the resulting update (e.g. due to a controller restart), it retained the old ports while peers received the new ones, causing DRBD connections to fail with StandAlone state. The fix introduces `copyDrbdTcpPortsIfExists()`, which preserves existing TCP ports in the `LayerPayload` before `removeLayerData()` releases them ([**@kvaps**](https://github.com/kvaps) in #2292, #2300). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.1.4...v1.1.5 diff --git a/docs/changelogs/v1.1.6.md b/docs/changelogs/v1.1.6.md deleted file mode 100644 index 77c49475..00000000 --- a/docs/changelogs/v1.1.6.md +++ /dev/null @@ -1,19 +0,0 @@ - - -## Fixes - -* **[build] Filter git describe to match only v* tags**: Adds `--match 'v*'` to all `git describe` calls in `hack/common-envs.mk`. The `api/apps/v1alpha1/*` subtags share the same commit as release tags, causing `git describe --exact-match` to pick `api/apps/v1alpha1/vX.Y.Z` instead of `vX.Y.Z`, producing invalid Docker image tags ([**@kvaps**](https://github.com/kvaps) in #2386, #2388). - -## Development, Testing, and CI/CD - -* **[ci] Replace cozystack-bot PAT with cozystack-ci GitHub App**: Replaces the long-lived `cozystack-bot` personal access token with short-lived, scoped tokens from the `cozystack-ci` GitHub App across all release workflows. Improves security and auditability of CI operations ([**@tym83**](https://github.com/tym83) in #2351). - -* **[ci] Replace GH_PAT with cozystack-ci GitHub App token in pull-requests workflow**: Switches the pull-requests release workflow to use the cozystack-ci GitHub App token instead of the personal access token ([**@kvaps**](https://github.com/kvaps) in #2383). - -* **[ci] Use cozystack org noreply email for bot commits**: Updates CI workflows to use the cozystack organization noreply email for bot commits ([**@kvaps**](https://github.com/kvaps) in #2392). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.1.5...v1.1.6 diff --git a/docs/changelogs/v1.2.0.md b/docs/changelogs/v1.2.0.md deleted file mode 100644 index 7c5b5e24..00000000 --- a/docs/changelogs/v1.2.0.md +++ /dev/null @@ -1,204 +0,0 @@ - - -# Cozystack v1.2.0 - -> **⚠️ WARNING: Do not use this release.** This version includes CloudNativePG operator, which updates the default PostgreSQL image to version 18. CNPG is unable to perform the migration from the previous major version automatically, which will cause PostgreSQL clusters to fail to start after the upgrade. Please use [v1.2.1](https://github.com/cozystack/cozystack/releases/tag/v1.2.1) instead. - -Cozystack v1.2.0 delivers significant platform enhancements: a fully managed **OpenSearch** service joining the application catalog, **VPC peering** for secure inter-tenant networking, tenant workload placement control via the new **SchedulingClass** system, a highly-available **VictoriaLogs cluster** replacing the single-node setup, and **Linstor volume relocation** for optimized clone and snapshot restore placement. Additional highlights include external-dns as a standalone extra package, multi-node RWX volume fixes, and a wave of dashboard and monitoring improvements. - -## Feature Highlights - -### OpenSearch: Managed Search and Analytics Service - -Cozystack now ships **OpenSearch** as a fully managed PaaS application — supporting OpenSearch v1, v2, and v3 in a multi-role topology with dedicated master, data, ingest, coordinating, and ML nodes. TLS is enabled by default, HTTP Basic auth is provided out of the box, and custom user definitions allow per-application credentials. The optional **OpenSearch Dashboards** UI can be enabled alongside the engine. External access, topology spread policies, and a comprehensive JSON schema are all included. - -A companion `opensearch-operator` system package wraps the upstream Opster OpenSearch Operator v2.8.0 and adds a sysctl DaemonSet to configure the required `vm.max_map_count` kernel parameter on every node automatically. An ApplicationDefinition package ties everything into the Cozystack platform dashboard with schema validation and resource management. - -### SchedulingClass: Tenant Workload Placement - -Cozystack now supports a **SchedulingClass** CRD that allows platform operators to define cluster-wide scheduling constraints — pinning tenant workloads to specific data centers, hardware generations, or node groups without requiring tenants to manage scheduler configuration themselves. Tenants declare a `schedulingClass` in their Tenant spec; the platform injects the appropriate `schedulerName` into all workloads in that namespace. - -The `lineage-controller-webhook` has been extended to verify the referenced SchedulingClass CR before injection, and child tenants inherit their parent's scheduling constraints (children cannot override). A **SchedulingClass dropdown** in the Tenant creation form in the dashboard makes the feature fully self-service. The underlying `cozystack-scheduler` — a custom kube-scheduler extension with SchedulingClass-aware affinity plugins — is now installed and enabled by default as part of the platform. - -### VPC Peering for Multi-Tenant Environments - -The `vpc` application gains bilateral **VPC peering** using Kube-OVN's native `vpcPeerings` mechanism, allowing tenants to securely interconnect their private networks without routing traffic through public endpoints. Peering link-local IPs (`169.254.0.0/16`) are allocated deterministically from a hash of the sorted VPC pair names, ensuring stable addresses across reconciliations. Static route support (`staticRoutes`) enables fine-grained inter-VPC routing policies. A `cozy-lib` helper (`hexToInt`) performs the deterministic IP allocation, and a JSON Schema validation enforces the `^tenant-` namespace pattern for peered VPCs. - -### VictoriaLogs: Clustered Mode for High Availability - -The platform's log storage has been upgraded from the deprecated single-node `VLogs` CR to a **VLCluster** deployment with separate vlinsert, vlselect, and vlstorage components, each running with 2 replicas by default — consistent with the existing VMCluster setup. This brings horizontal scalability and resilience to the logging tier. VPA autoscaling is enabled for all VLCluster components, and the victoria-metrics-operator has been upgraded from v0.55.0 to v0.68.1 to add VLCluster CRD support. - -### Linstor CSI: Volume Relocation After Clone and Restore - -The Linstor CSI driver now carries upstream patches enabling **automatic replica relocation** after PVC clone and snapshot restore operations. Two new parameters control the behavior: `linstor.csi.linbit.com/relocateAfterClone` on StorageClasses moves replicas to optimal nodes after a clone, and `snap.linstor.csi.linbit.com/relocate-after-restore` on VolumeSnapshotClasses does the same after a restore. VolumeSnapshotClasses for Velero and Kasten use cases are pre-configured. This enables full PVC-level backup and restore workflows with automatic data rebalancing, a key prerequisite for production Velero/Kasten integrations. - -## Major Features and Improvements - -* **[apps] Add managed OpenSearch service**: Deployed as a PaaS application supporting OpenSearch v1/v2/v3 with multi-role node topology, TLS, HTTP Basic auth, custom users, optional OpenSearch Dashboards UI, external access, and topology spread policies; backed by the opster OpenSearch Operator v2.8.0 and a sysctl DaemonSet for `vm.max_map_count` ([**@matthieu-robin**](https://github.com/matthieu-robin) in #1953). - -* **[vpc] Add VPC peering support for multi-tenant environments**: Bilateral VPC peering via Kube-OVN's `vpcPeerings`, deterministic link-local IP allocation from sorted VPC pair hash, static routes support, ConfigMap peer discovery enrichment, and JSON Schema validation enforcing `^tenant-` namespace pattern ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2152). - -* **[monitoring] Migrate VictoriaLogs from VLogs to VLCluster**: Replaced deprecated single-node `VLogs` CR with clustered `VLCluster` (vlinsert/vlselect/vlstorage, 2 replicas each), added VPA for all components, upgraded victoria-metrics-operator to v0.68.1 ([**@sircthulhu**](https://github.com/sircthulhu) in #2153). - -* **[scheduler] Integrate SchedulingClass support for tenant workloads**: Added `schedulingClass` Tenant parameter with inheritance enforcement, `scheduling.cozystack.io/class` namespace label, lineage-webhook extension to verify and inject `schedulerName`, SchedulingClass dropdown in Tenant dashboard form ([**@sircthulhu**](https://github.com/sircthulhu) in #2223). - -* **[cozystack-scheduler] Add custom scheduler as an optional system package**: Vendored `cozystack-scheduler` from github.com/cozystack/cozystack-scheduler — a kube-scheduler extension with SchedulingClass-aware affinity plugins, including Helm chart with RBAC, ConfigMap, Deployment, and CRD ([**@lllamnyp**](https://github.com/lllamnyp) in #2205). - -* **[platform] Enable cozystack-scheduler by default**: The cozystack-scheduler and SchedulingClass CRD are now installed as default system packages; the backup tool has been moved to optional packages ([**@lllamnyp**](https://github.com/lllamnyp) in #2253). - -* **[extra] Add external-dns as a standalone extra package**: Packaged external-dns as an installable extra (tenant-level) component for automatic DNS record management from Kubernetes Service and Ingress resources ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #1988). - -* **[linstor] Add linstor-csi patches for clone/snapshot relocation**: New patch enabling `relocateAfterClone` StorageClass parameter and `relocate-after-restore` VolumeSnapshotClass parameter; pre-configured VolumeSnapshotClasses for Velero and relocation workflows; CDI switched to csi-clone strategy ([**@kvaps**](https://github.com/kvaps) in #2133). - -* **[monitoring] Add inlineScrapeConfig support to tenant vmagent**: Tenants can now define inline scrape configurations directly in their VMAgent spec, enabling custom metrics collection from services that are not discoverable via standard Kubernetes service discovery ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2200). - -* **[monitoring] Add Slack dashboard URL, vmagent environment label, and dynamictext Grafana plugin**: Added `SLACK_DASHBOARD_URL` and `SLACK_SUMMARY_FMT` environment variables for richer alert notifications, per-vmagent `environment` label for metric source identification, and the `dynamictext-panel` plugin for Grafana dashboards ([**@vnyakas**](https://github.com/vnyakas) in #2210). - -* **[monitoring] Scope infrastructure dashboards to tenant-root only**: Infrastructure-level Grafana dashboards are now scoped to the tenant-root namespace only, preventing them from appearing in tenant sub-namespaces and reducing dashboard noise ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2197). - -* **[tenant] Allow egress to virt-handler for VM metrics scraping**: Extended tenant NetworkPolicy to permit egress to virt-handler pods, enabling Prometheus to scrape VM-level metrics from KubeVirt without additional policy exceptions ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2199). - -* **[dashboard] Add keycloakInternalUrl for backend-to-backend OIDC requests**: Added a `keycloakInternalUrl` platform value for the dashboard backend to perform OIDC token introspection via an internal cluster URL, avoiding external round-trips and improving reliability in air-gapped environments ([**@sircthulhu**](https://github.com/sircthulhu) in #2224). - -* **[dashboard] Add secret-hash annotation to KeycloakClient for secret sync**: Added a `secret-hash` annotation to the KeycloakClient resource so that changes to the client secret trigger automatic reconciliation and propagation to dependent components ([**@sircthulhu**](https://github.com/sircthulhu) in #2231). - -* **[docs] Add OpenAPI and Go types code generation for apps**: Added tooling to generate OpenAPI schemas and Go types from Helm chart values, enabling type-safe programmatic access to managed application configurations and automatic API reference generation ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2214). - -## Improvements (minor) - -* **[cozystack-scheduler] Update to v0.2.0**: Updated the cozystack-scheduler to v0.2.0 with improved SchedulingClass affinity handling ([**@lllamnyp**](https://github.com/lllamnyp) in #2244). - -* **[platform] Ensure cozystack-packages OCIRepository updates reliably**: Added configuration to ensure the `cozystack-packages` OCIRepository resource is consistently reconciled and reflects the latest package versions on upgrade ([**@sircthulhu**](https://github.com/sircthulhu) in #2246). - -* **[etcd] Add protective limits to defrag CronJob**: Added CPU and memory resource limits to the etcd defragmentation CronJob to prevent it from starving other workloads during scheduled defragmentation runs ([**@sircthulhu**](https://github.com/sircthulhu) in #2233). - -* **[platform] Add missing apps to tenant admin RBAC**: Extended the tenant admin ClusterRole to include RBAC permissions for recently added applications that were missing from the role binding ([**@sircthulhu**](https://github.com/sircthulhu) in #2268). - -## Bug Fixes - -* **[keycloak] Fix health probe configuration for Keycloak v26.x+**: Replaced deprecated `KC_PROXY=edge` with `KC_PROXY_HEADERS=xforwarded`/`KC_HTTP_ENABLED=true`; replaced liveness/readiness probes with management port endpoints (`/health/live`, `/health/ready`) and added a `startupProbe` to handle slow Keycloak startup without triggering premature restarts ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2162). - -* **[migrations] Handle missing RabbitMQ CRD in migration 34**: Fixed a crash in migration script 34 that occurred when the RabbitMQ CRD was not yet installed, allowing upgrades from environments where RabbitMQ was never deployed ([**@IvanHunters**](https://github.com/IvanHunters) in #2168). - -* **[platform] Fix VM MAC address not preserved during migration**: Fixed the `virtual-machine` to `vm-instance` migration script to correctly carry over the MAC address, preventing network identity changes after upgrading existing VM resources ([**@sircthulhu**](https://github.com/sircthulhu) in #2169). - -* **[dashboard] Fix External IPs factory EnrichedTable rendering**: Corrected the External IPs factory component to use the EnrichedTable renderer, resolving blank/broken rendering of the external IP address list in the dashboard ([**@IvanHunters**](https://github.com/IvanHunters) in #2175). - -* **[dashboard] Preserve disabled/hidden state on MarketplacePanel reconciliation**: Fixed a regression where MarketplacePanel reconciliation would reset the `disabled` and `hidden` flags set by operators, causing hidden applications to reappear in the catalog ([**@IvanHunters**](https://github.com/IvanHunters) in #2176). - -* **[dashboard] Exclude hidden MarketplacePanel resources from sidebar menu**: Fixed the sidebar to omit applications that have been hidden via MarketplacePanel flags, preventing inaccessible menu entries from being displayed to users ([**@IvanHunters**](https://github.com/IvanHunters) in #2177). - -* **[etcd-operator] Replace deprecated kube-rbac-proxy image**: Replaced the unmaintained `gcr.io/kubebuilder/kube-rbac-proxy` sidecar with the actively maintained `quay.io/brancz/kube-rbac-proxy` image to eliminate deprecation warnings and ensure continued security updates ([**@kvaps**](https://github.com/kvaps) in #2181). - -* **[backups] Fix RBAC and backupstrategy-controller location**: Corrected role bindings and the deployment location for the backup strategy controller to restore full backup and restore functionality ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2149). - -* **[api] Skip OpenAPI post-processor for non-apps group versions**: Fixed the API server to bypass OpenAPI schema post-processing for non-`apps` group versions, preventing schema corruption in unrelated API groups ([**@kvaps**](https://github.com/kvaps) in #2212). - -* **[bucket] Fix s3manager endpoint mismatch with COSI credentials**: Corrected the S3 Manager UI to use the actual S3 endpoint from the BucketInfo COSI resource rather than a hardcoded value, resolving connection failures when the S3 endpoint differs from the default ([**@IvanHunters**](https://github.com/IvanHunters) in #2211). - -* **[kubernetes] Fix tenant Kubernetes cluster creation for versions < 1.32**: Resolved a template rendering error that prevented creation of tenant Kubernetes clusters with versions older than 1.32 ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2209). - -* **[kube-ovn] Fix MASTER_NODES detection for multi-master Kubernetes clusters**: Updated kube-ovn configuration to discover control-plane nodes via the standard `node-role.kubernetes.io/control-plane` label rather than relying on static node lists, fixing OVN connectivity issues in multi-master generic Kubernetes deployments ([**@lexfrei**](https://github.com/lexfrei) in #2245). - -* **[kubernetes] Fix CiliumNetworkPolicy endpointSelector for multi-node RWX volumes**: Corrected the CiliumNetworkPolicy endpoint selector for NFS-based ReadWriteMany volumes to properly allow NFS traffic when data is spread across multiple Linstor storage nodes ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2227). - -* **[csi] Hide disk.img and lost+found from RWX NFS mounts**: Fixed the Linstor CSI NFS server to exclude internal files (`disk.img`, `lost+found`) from being visible inside NFS-mounted volumes, preventing application errors caused by unexpected files in volume root directories ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2243). - -* **[dashboard] Fix broken backup menu links missing cluster context**: Restored cluster context in backup-related sidebar navigation links, fixing 404 errors when navigating to BackupJob and Plan pages from the cluster-level dashboard view ([**@kvaps**](https://github.com/kvaps) in #2232). - -* **[dashboard] Fix StorageClass dropdown "Error" state by granting RBAC read access**: Added a ClusterRole/ClusterRoleBinding to grant authenticated users read access to StorageClass resources, resolving the "Error" state displayed in StorageClass dropdowns on application forms ([**@sircthulhu**](https://github.com/sircthulhu) in #2267). - -* **[postgres] Fix database deletion lifecycle management**: Added cleanup stages to delete databases and orphaned roles when removed from `values.databases`, enabling declarative database lifecycle management and preventing stale data retention ([**@sircthulhu**](https://github.com/sircthulhu) in #2247). - -* **[dashboard] Fix JSONPath crash on Tenant details with resourceQuotas**: Restored fallback protection for unresolved flatMap placeholders in the ResourceQuota "Used" column, preventing JSONPath parser crashes on the Tenant details page ([**@sircthulhu**](https://github.com/sircthulhu) in #2249). - -* **[system] Fix tenant RBAC for endpointslices read access**: Added `discovery.k8s.io/endpointslices` read permissions to tenant ClusterRoles, resolving 403 errors on the Service details page when displaying the "Pod serving" section ([**@sircthulhu**](https://github.com/sircthulhu) in #2257). - -* **[linstor] Fix swapped VMPodScrape job labels**: Corrected the `job` label relabeling in LINSTOR VictoriaMetrics PodScrape templates, fixing `linstorControllerOffline` alerts that incorrectly reported satellite endpoints as controller failures ([**@sasha-sup**](https://github.com/sasha-sup) in #2264). - -* **[piraeus-operator] Fix LINSTOR satellite alert labels and scrape flapping false positives**: Fixed non-existent `name` label in `linstorSatelliteErrorRate` alert annotations (changed to `hostname`) and prevented false positives caused by scrape flapping and stale metric counters ([**@sasha-sup**](https://github.com/sasha-sup) in #2265). - -* **[dashboard] Fix EndpointSlice column definitions for Pod serving table**: Added missing `CustomColumnsOverride` for the EndpointSlice table on service details page, replacing "Raw:" prefixes and "Invalid Date" values with proper Pod, Addresses, Ready, and Node columns ([**@sircthulhu**](https://github.com/sircthulhu) in #2266). - -## Dependencies & Version Updates - -* **[cilium] Update Cilium to v1.19.1**: Upgraded the Cilium CNI to v1.19.1 with latest bug fixes and performance improvements ([**@BROngineer**](https://github.com/BROngineer) in #2173). - -* **[keycloak-operator] Update to v1.32.0**: Updated the Keycloak Operator to v1.32.0 (based on epam/edp-keycloak-operator with upstream patches), bumping Keycloak to 26.5.2 ([**@lllamnyp**](https://github.com/lllamnyp) in #2206). - -* **[postgres-operator] Update to v1.27.3**: Upgraded the Postgres Operator (Patroni-based) to v1.27.3 with latest upstream fixes ([**@dmpopoff**](https://github.com/dmpopoff) in #2226). - -* **[objectstorage-controller] Update to v0.2.2, drop upstreamed patches**: Updated the object storage controller to v0.2.2 and removed patches that were accepted upstream, reducing the maintenance delta ([**@lexfrei**](https://github.com/lexfrei) in #2261). - -* **[kilo] Switch from fork to upstream squat/kilo**: Replaced the Cozystack-maintained Kilo fork with the upstream `squat/kilo` image now that required patches (`--internal-cidr`, allowed-location-ips fix, preferred source for WireGuard routes, Cilium IPIP overlay support) have been merged upstream ([**@lexfrei**](https://github.com/lexfrei) in #2259). - -* **[talos] Bump Talos to v1.12.6**: Updated the pinned Talos version to v1.12.6 ([**@kvaps**](https://github.com/kvaps) in #2254). - -* **[talm] Release v0.22.4** (github.com/cozystack/talm): Fixed `--file`/`--template` flag requirement to prevent ambiguous invocations ([**@kvaps**](https://github.com/kvaps) in cozystack/talm#112). - -* **[boot-to-talos] Release v0.7.0** (github.com/cozystack/boot-to-talos): Added support for ISO, RAW, and HTTP image sources ([**@lexfrei**](https://github.com/lexfrei) in cozystack/boot-to-talos#13); permanent MAC addresses for predictable interface names ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/boot-to-talos#14); detection and workaround for 5-level paging (LA57) incompatibility with kexec ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/boot-to-talos#15). - -* **[boot-to-talos] Release v0.7.1** (github.com/cozystack/boot-to-talos): Fixed EFI boot entry creation to use the target disk rather than relying on the installer disk, preventing boot failures on bare-metal systems ([**@kvaps**](https://github.com/kvaps) in cozystack/boot-to-talos#16). - -## Development, Testing, and CI/CD - -* **[tests] Stabilize E2E Kubernetes tests**: Comprehensive improvements to E2E test stability: pre-cleanup of leftover resources, fixes for port-forward race conditions and leaks, improved NFS PVC timeout and debug output, proper EXIT trap handling, and increased CAPI deployment timeouts ([**@lexfrei**](https://github.com/lexfrei) in #2262). - -* **[ci] Fix E2E check blocking docs-only PRs**: Moved path filtering to the job level so that documentation-only pull requests are not blocked by pending E2E CI checks ([**@IvanHunters**](https://github.com/IvanHunters) in #2170). - -* **[ci] Add timeout-minutes to Build and E2E jobs**: Added explicit `timeout-minutes` constraints to Build and E2E workflow jobs to prevent stuck runners from consuming CI resources indefinitely. - -## Documentation - -* **[website] Complete CA rotation documentation**: Added comprehensive CA certificate rotation procedures for all Cozystack system components ([**@kvaps**](https://github.com/kvaps) in cozystack/website#406). - -* **[website] Add Ansible automated installation guide**: Added a step-by-step guide for automated Cozystack installation using Ansible playbooks ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#442). - -* **[website] Add self-signed certificates configuration guide for OIDC**: Added documentation for configuring Cozystack to use self-signed TLS certificates with OIDC providers, covering certificate authority setup and kubeconfig integration ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#443). - -* **[website] Add custom metrics collection guide**: Added a guide explaining how to configure custom Prometheus scrape targets using the new `inlineScrapeConfig` feature of tenant VMAgent ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#444). - -* **[website] Add PackageSource/Package architecture to Key Concepts**: Documented the PackageSource and Package CRD architecture, explaining how operators extend the platform with custom application catalogs ([**@IvanHunters**](https://github.com/IvanHunters) in cozystack/website#445). - -* **[website] Add SchedulingClass operations guide**: Added a guide covering SchedulingClass CRD creation, tenant assignment, and workload placement verification ([**@lllamnyp**](https://github.com/lllamnyp) in cozystack/website#455). - -* **[website] Add VMInstance and VMDisk backups documentation**: Added user-facing documentation for backing up and restoring virtual machine instances and VM disk images using Velero ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#456). - -* **[website] Update developer guide**: Updated the developer guide with current build, test, and contribution workflows including OCIRepository and migration tooling ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#458). - -* **[website] Document keycloakInternalUrl platform value**: Added documentation explaining how to configure `keycloakInternalUrl` for backend-to-backend OIDC token introspection in cluster-internal environments ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#452). - -* **[website] Add DependenciesNotReady troubleshooting guide**: Added a troubleshooting article explaining how to diagnose and resolve the `DependenciesNotReady` package status condition ([**@kvaps**](https://github.com/kvaps) in cozystack/website#450). - -* **[website] Reorder installation steps for operator-before-platform**: Updated the installation guide to install the cozystack-operator before applying the platform package, reflecting the correct dependency order ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#449). - -* **[website] Update managed apps reference**: Updated the automatically generated managed applications reference documentation to reflect new apps and schema changes in this release ([**@app/github-actions**](https://github.com/apps/github-actions) in cozystack/website#448). - -* **[website] Update screenshots for Cozystack v1.1**: Refreshed dashboard screenshots to reflect the updated UI in Cozystack v1.1 ([**@kvaps**](https://github.com/kvaps) in cozystack/website#447). - -* **[website] Enhance operator backups guide**: Improved the backup and recovery guide for operators with additional recovery scenarios and procedures ([**@androndo**](https://github.com/androndo) in cozystack/website#440). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@androndo**](https://github.com/androndo) -* [**@BROngineer**](https://github.com/BROngineer) -* [**@dmpopoff**](https://github.com/dmpopoff) -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@lllamnyp**](https://github.com/lllamnyp) -* [**@mattia-eleuteri**](https://github.com/mattia-eleuteri) -* [**@matthieu-robin**](https://github.com/matthieu-robin) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@sasha-sup**](https://github.com/sasha-sup) -* [**@sircthulhu**](https://github.com/sircthulhu) -* [**@tym83**](https://github.com/tym83) -* [**@vnyakas**](https://github.com/vnyakas) - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.1.0...v1.2.0 diff --git a/docs/changelogs/v1.2.1.md b/docs/changelogs/v1.2.1.md deleted file mode 100644 index 29e3fdf6..00000000 --- a/docs/changelogs/v1.2.1.md +++ /dev/null @@ -1,31 +0,0 @@ - - -## Features and Improvements - -* **[postgres] Hardcode PostgreSQL 17 for monitoring databases and add migration**: CloudNativePG operator defaults to PostgreSQL 18.3 when no explicit image is specified, but monitoring queries in Grafana and Alerta rely on PostgreSQL 17 features such as `pg_stat_checkpointer` and the updated `pg_stat_bgwriter`. This mismatch could break monitoring after fresh installs or database recreation. PostgreSQL 17.7 images are now hardcoded for monitoring databases, and migration 37 is added to set version v17 for any existing PostgreSQL resources ([**@IvanHunters**](https://github.com/IvanHunters) in #2304, #2309). - -## Fixes - -* **[platform] Prevent installed packages deletion**: Added the `helm.sh/resource-policy: keep` annotation to all platform packages. Previously, moving a package to `disabledPackages` or removing it from `enabledPackages` caused Helm to automatically delete the corresponding resource, contradicting the documented behavior that requires the platform administrator to manually delete packages when needed ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2273, #2297). - -* **[linstor] Preserve TCP ports during toggle-disk operations**: During toggle-disk operations, `removeLayerData()` freed TCP ports from the number pool and `ensureStackDataExists()` could then allocate different ports. If a satellite missed the resulting update (e.g. due to a controller restart), it retained the old ports while peers received the new ones, causing DRBD connections to fail with StandAlone state. The fix adds `copyDrbdTcpPortsIfExists()` which saves existing TCP ports into the `LayerPayload` before `removeLayerData()` deletes them ([**@kvaps**](https://github.com/kvaps) in #2292, #2299). - -* **[platform] Fix resource allocation ratios not propagated to managed packages**: A regression introduced in the bundle restructure caused `cpuAllocationRatio`, `memoryAllocationRatio`, and `ephemeralStorageAllocationRatio` set in `platform/values.yaml` to become no-ops — they were never written to the `cozystack-values` Secret that cozy-lib reads in child packages. This meant all managed applications silently used the hardcoded defaults (10, 1, 40) regardless of operator-configured values. The fix restores propagation by writing the ratios into the `_cluster` section of the `cozystack-values` Secret and passing `cpuAllocationRatio` to the KubeVirt Package component ([**@sircthulhu**](https://github.com/sircthulhu) in #2296, #2301). - -* **[linstor] Fix DRBD connectivity failures on kernels without `crct10dif` by setting verify-alg to `crc32c`**: LINSTOR's auto-verify algorithm selection defaults to `crct10dif`, but this kernel crypto module is no longer available in newer kernels (e.g. Talos v1.12.6, kernel 6.18.18). When `crct10dif` is unavailable, DRBD peer connections fail with `VERIFYAlgNotAvail: failed to allocate crct10dif for verify`, causing all DRBD resources to enter Diskless state and lose quorum. `DrbdOptions/Net/verify-alg` is now set to `crc32c` at the controller level ([**@kvaps**](https://github.com/kvaps) in #2303, #2312). - -* **[multus] Fix stale sandbox reservations permanently blocking pod creation after CNI ADD failure**: After a node disruption (e.g. DRBD or kube-ovn issues during upgrade), containerd accumulated stale sandbox name reservations. Cleanup failed because multus called delegate plugins for DEL without cached state and they rejected the incomplete config, causing DEL to fail instead of succeeding. Stale entries were never released, permanently blocking new pod creation on the affected node. A custom multus-cni image is now built with a patch that returns success from DEL when CNI ADD never completed ([**@kvaps**](https://github.com/kvaps) in #2313, #2314). - -* **[multus] Pin master CNI to `05-cilium.conflist` to prevent race condition at boot**: During node boot or Talos upgrade, multus auto-detects the master CNI conflist by scanning the CNI config directory. If kube-ovn writes `10-kube-ovn.conflist` before Cilium writes `05-cilium.conflist`, multus selects the wrong file and pods bypass the Cilium chain entirely, have no Cilium endpoint, and their traffic is blocked by cluster-wide network policies. `multusMasterCNI` is now pinned to `05-cilium.conflist` ([**@kvaps**](https://github.com/kvaps) in #2315, #2316). - -## Documentation - -* **[website] Add custom Keycloak themes documentation**: Added documentation for custom Keycloak theme injection to the White Labeling guide, covering the theme image contract (`/themes/` directory structure), configuration via the `cozystack.keycloak` Package resource, `imagePullSecrets` for private registries, and theme activation in the Keycloak admin console ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#463). - -* **[website] Add documentation for Go types usage**: Added a guide for using the generated Go types for Cozystack managed applications as a Go module, including installation instructions, programmatic resource management examples, and deployment approaches ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#465). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.2.0...v1.2.1 diff --git a/docs/changelogs/v1.2.2.md b/docs/changelogs/v1.2.2.md deleted file mode 100644 index 2b6a1ae5..00000000 --- a/docs/changelogs/v1.2.2.md +++ /dev/null @@ -1,63 +0,0 @@ - - -## Features and Improvements - -* **[linstor] Update piraeus-server to v1.33.2 with selected backports**: Bumps LINSTOR server from v1.33.1 to v1.33.2 and adds backported patches for improved storage reliability: a stale bitmap adjust retry mechanism for automatic recovery after bitmap attach errors, LUKS2 header sizing and optimal I/O size detection improvements for more reliable disk formatting, and the maintainer implementation backport. All patches verified against upstream v1.33.2 with `git apply --check` and `gradlew compileJava` ([**@kvaps**](https://github.com/kvaps) in #2331, #2377). - -## Fixes - -* **[postgres] Fix system PostgreSQL images to 17.7-standard-trixie**: Hardcodes PostgreSQL 17.7-standard-trixie images for system PostgreSQL instances. This ensures system databases use the correct image variant consistent with the monitoring stack requirements introduced in v1.2.1 ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2364, #2369). - -* **[cilium] Opt-out of cri-containerd.apparmor.d for nsenter init containers**: On Ubuntu 22.04+, Debian, and other distributions that load the `cri-containerd.apparmor.d` AppArmor profile by default for containerd workloads, the kernel denied `nsenter` namespace entry in cilium-agent init containers (`mount-cgroup`, `apply-sysctl-overwrites`, `clean-cilium-state`), causing the agent to land in `Init:CrashLoopBackOff` and cascading platform failures. Per-container `container.apparmor.security.beta.kubernetes.io` annotations now opt the affected containers out of this profile, applied only on non-Talos cilium variants (`cilium-generic`, `kubeovn-cilium-generic`). The vendored daemonset template is also patched to strip the upstream `semverCompare "<1.30.0"` AppArmor block, preventing duplicate annotation keys. Talos variants are untouched as Talos does not load the AppArmor LSM ([**@lexfrei**](https://github.com/lexfrei) in #2370, #2378). - -* **[virtual-machine] Exclude external VM services from Cilium BPF LB**: Adds the `service.kubernetes.io/service-proxy-name: "cozy-proxy"` label to VM LoadBalancer services when `external: true`, telling Cilium to skip BPF processing entirely for these services. This fixes two issues: inter-tenant connectivity via public LB IPs (Cilium's DNAT caused cross-tenant pod-to-pod flow classification, triggering CiliumClusterwideNetworkPolicy blocks) and WholeIP broken on Cilium 1.19+ (wildcard service drop entries blocked traffic to LB IPs on undeclared ports before it reached netfilter/cozy-proxy). MetalLB L2 advertisement and kube-ovn routing remain unaffected ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2357, #2361). - -* **[monitoring] Fix infra dashboards missing in default variant**: The default platform variant deploys the monitoring chart to the `cozy-monitoring` namespace, but the dashboard rendering condition introduced in #2197 only checked for `tenant-root`. Infrastructure dashboards were not rendered in the default variant. The `cozy-monitoring` namespace is now included in the rendering condition, consistent with the existing pattern in `vmagent.yaml` ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2365, #2367). - -* **[build] Filter git describe to match only v* tags**: Adds `--match 'v*'` to all `git describe` calls in `hack/common-envs.mk`. The `api/apps/v1alpha1/*` subtags share the same commit as release tags, causing `git describe --exact-match` to pick `api/apps/v1alpha1/vX.Y.Z` instead of `vX.Y.Z`, producing invalid Docker image tags ([**@kvaps**](https://github.com/kvaps) in #2386, #2389). - -## Development, Testing, and CI/CD - -* **[ci] Replace cozystack-bot PAT with cozystack-ci GitHub App**: Replaces the long-lived `cozystack-bot` personal access token with short-lived, scoped tokens from the `cozystack-ci` GitHub App across all release workflows (`tags.yaml`, `auto-release.yaml`, `pull-requests-release.yaml`). Improves security and auditability of CI operations ([**@tym83**](https://github.com/tym83) in #2351). - -* **[ci] Use cozystack org noreply email for bot commits**: Updates CI workflows to use the cozystack organization noreply email for bot commits ([**@kvaps**](https://github.com/kvaps) in #2392, #2393). - -* **[ci] Replace GH_PAT with cozystack-ci GitHub App token in pull-requests workflow**: Switches the pull-requests release workflow to use the cozystack-ci GitHub App token instead of the personal access token ([**@kvaps**](https://github.com/kvaps) in #2383, #2384). - -## Documentation - -* **[website] Add ApplicationDefinition naming convention reference**: Added reference documentation on ApplicationDefinition naming conventions and how `cozystack-api` resolves kinds to their backing definitions ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#478). - -* **[website] Document Talos / talosctl / Cozystack version pairing**: Added documentation covering Talos, talosctl, and Cozystack version compatibility matrix for installation ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#484). - -* **[website] Fix KubeOVN MASTER_NODES example path and key in troubleshooting**: Corrected the MASTER_NODES example path and key in the KubeOVN troubleshooting guide ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#483). - -* **[website] Prefix bundle package names with cozystack. in v1 examples**: Updated documentation examples to use the correct `cozystack.` prefix for bundle package names in enabled/disabledPackages ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#482). - -* **[website] Finish isolated-field removal and document opt-in policy labels**: Removed the obsolete `isolated` field from tenant documentation and documented the new opt-in policy labels approach ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#481). - -* **[website] Add --take-ownership flag and describe networking.* fields**: Added documentation for the `--take-ownership` flag and described the `networking.*` fields in the installation guide ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#480). - -* **[website] Add bonding (LACP) configuration how-to guide**: Added a guide for configuring network bonding with LACP on Cozystack installations ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#459). - -* **[website] Improve registry mirrors for tenant Kubernetes in air-gapped guide**: Improved documentation for configuring registry mirrors in tenant Kubernetes clusters for air-gapped environments ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#461). - -* **[website] Update backup/restore documentation for VMI/VMDisk**: Updated backup documentation with information related to VM instance and VM disk restore improvements ([**@androndo**](https://github.com/androndo) in cozystack/website#466). - -* **[website] Add updated OpenAPI spec**: Updated the OpenAPI specification for managed applications reference ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#469). - -* **[website] Add OSS Health pages and OpenSSF badge**: Added OSS Health section with OpenSSF Scorecard and Best Practices badge to the website footer ([**@tym83**](https://github.com/tym83) in cozystack/website#470). - -* **[website] Add CozySummit Virtual 2026 program announcement**: Published the CozySummit Virtual 2026 program announcement blog post ([**@tym83**](https://github.com/tym83) in cozystack/website#472). - -* **[website] Add missing release announcements for v0.1–v0.41**: Backfilled missing release announcement blog posts for Cozystack versions v0.1 through v0.41 ([**@tym83**](https://github.com/tym83) in cozystack/website#468). - -* **[talm] Render templates online in apply to resolve lookups**: Fixed talm `apply` command to render templates online, resolving template lookup failures when using modeline templates ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/talm#119). - -* **[talm] Update default Talos image to v1.12.6**: Updated the default Talos image version to v1.12.6 in talm ([**@kvaps**](https://github.com/kvaps) in cozystack/talm@03e9b6e). - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.2.1...v1.2.2 diff --git a/docs/changelogs/v1.2.3.md b/docs/changelogs/v1.2.3.md deleted file mode 100644 index 6d1b3b74..00000000 --- a/docs/changelogs/v1.2.3.md +++ /dev/null @@ -1,58 +0,0 @@ - - -# v1.2.3 (2026-04-20) - -A patch release with bug fixes and documentation updates. - -## Features and Improvements - -_No notable features in this patch release._ - -## Fixes - -* **fix(kubernetes): set explicit ephemeral-storage on virt-launcher pods**: Prevents VM crashes caused by ephemeral-storage eviction by setting explicit `domain.resources` ephemeral-storage on the VirtualMachine spec. Uses sanitized limits and requests so virt-launcher pods do not inherit too-small namespace defaults. ([**@kvaps**](https://github.com/kvaps) in #2317, backport #2423). - -## Documentation - -* **[website] feat: add Telemetry page under OSS Health section**: Add Telemetry page and initial data seeding to OSS Health docs ([**@tym83**](https://github.com/tym83) in cozystack/website#471). -* **[website] Refactor docs versions to major.minor variants**: Move docs to major.minor versioning for v1.x series ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#477). -* **[website] docs(tenants): document namespace layout and parent/child derivation** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#479). -* **[website] docs(tenants): document the checkbox-then-edit-CR customization pattern** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#485). -* **[website] docs: fix 14 broken links and stale talm anchor across v1 docs** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#486). -* **[website] fix(og): update social badge image and title** ([**@tym83**](https://github.com/tym83) in cozystack/website#487). -* **[website] docs(external-apps): rewrite guide for ApplicationDefinition API** ([**@kitsunoff**](https://github.com/kitsunoff) in cozystack/website#488). -* **[website] docs: add CLAUDE.md for AI agent guidance** ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#489). -* **[website] fix: update /docs/v1/ redirect to latest v1.2** ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#492). -* **[website] fix(ci): add OpenAPI spec download to GitHub Pages build** ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#494). -* **[website] feat(blog): add managed PostgreSQL with synchronous replication post** ([**@tym83**](https://github.com/tym83) in cozystack/website#497). -* **[website] chore(blog): add images frontmatter for social preview on existing posts** ([**@tym83**](https://github.com/tym83) in cozystack/website#498). -* **[website] feat(blog): taxonomies and client-side filter UI** ([**@tym83**](https://github.com/tym83) in cozystack/website#499). -* **[website] style(oss-health): add breathing room between navbar and hero** ([**@tym83**](https://github.com/tym83) in cozystack/website#500). - -## Other repositories - -* **[talm] feat(config): migrate to Talos v1.12 multi-document config format**: Upgrade Talos config format and modernize configuration handling ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#116). -* **[talm] chore(deps): bump dependencies and modernize codebase** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#124). -* **[external-apps-example] feat: replace MongoDB example with Minecraft apps from cozylex** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/external-apps-example#2). -* **[ansible-cozystack] fix(examples): add v prefix to collection version in requirements.yml** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#23). -* **[ansible-cozystack] fix(plugins): replace ansible.utils.ipaddr with stdlib-based test plugin** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#24). -* **[ansible-cozystack] feat(examples): comprehensive node prerequisites audit (fixes #19)** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#27). -* **[ansible-cozystack] chore(deps): update dependency cozystack.installer to v1.2.3** ([**@app/renovate**](https://github.com/apps/renovate) in cozystack/ansible-cozystack#29). -* **[ansible-cozystack] feat(role): expose publishing.externalIPs and tenant-root ingress via role variables** ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#30). - -## Contributors - -Thanks to everyone who contributed to this patch release: - -* [**@app/github-actions**](https://github.com/apps/github-actions) -* [**@app/renovate**](https://github.com/apps/renovate) -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@tym83**](https://github.com/tym83) - - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.2.2...v1.2.3 diff --git a/docs/changelogs/v1.3.0-rc.1.md b/docs/changelogs/v1.3.0-rc.1.md deleted file mode 100644 index 9b63c106..00000000 --- a/docs/changelogs/v1.3.0-rc.1.md +++ /dev/null @@ -1,173 +0,0 @@ - - -# Cozystack v1.3.0-rc.1 - -Cozystack v1.3.0-rc.1 is the first release candidate for v1.3.0, bringing **storage-aware scheduling** via the LINSTOR scheduler extender, a managed **LINSTOR GUI** web UI with Keycloak SSO, a **VM Default Images** catalog for out-of-the-box virtual machine provisioning, **WorkloadsReady conditions** with a real-time Events tab in the dashboard, and **cross-namespace VM backup restore** capabilities. Additional highlights include stricter tenant name validation, VM network selector improvements, Keycloak theme injection and SMTP configuration, and a comprehensive host runtime preflight check. - -> **Note:** Fixes marked with *(backported to v1.2.x)* were also included in v1.2.1 or v1.2.2 patch releases. - -## Feature Highlights - -### Storage-Aware Scheduling via LINSTOR Extender - -The `cozystack-scheduler` now calls the **LINSTOR scheduler extender** for storage-locality-aware pod placement. When a pod declares both a `SchedulingClass` and LINSTOR-backed PVCs, the scheduler consults LINSTOR to prefer nodes where volume replicas already exist — reducing cross-node replication traffic and improving I/O latency for storage-heavy workloads ([**@lllamnyp**](https://github.com/lllamnyp) in #2330). - -### LINSTOR GUI: Managed Web UI for Storage Administration - -A new opt-in `linstor-gui` system package deploys **LINBIT's linstor-gui web UI** alongside the LINSTOR controller with mTLS client authentication, non-root security context, and ClusterIP-only service. An optional **Keycloak-protected Ingress** (via oauth2-proxy) can be enabled for SSO-authenticated browser access when OIDC is configured on the platform ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2382, #2390). - -### VM Default Images: Out-of-the-Box VM Provisioning - -The new `vm-default-images` package provides a curated set of **cluster-wide virtual machine images** (Ubuntu, Debian, CentOS Stream, and others) as pre-populated DataVolumes. The package is opt-in via the `iaas` bundle and defaults to replicated storage for high availability. A companion migration (migration 38) renames legacy `vm-image-*` DataVolumes to the new `vm-default-images-*` naming scheme. The `vm-disk` chart also gains a new "disk" source type for cloning from existing vm-disks in the same namespace ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2258). - -### WorkloadsReady Condition and Events Tab - -Applications now expose a **WorkloadsReady** condition on their status by querying associated WorkloadMonitor resources, giving operators a single place to check whether all underlying workloads (Deployments, StatefulSets, DaemonSets) are healthy. The dashboard gains a new **Events tab** showing namespace-scoped Kubernetes events for each application, with fallback to `.firstTimestamp` when `.eventTime` is absent. A bug where WorkloadMonitor's `Operational` status was never persisted is also fixed ([**@lexfrei**](https://github.com/lexfrei) in #2356). - -### Cross-Namespace VM Backup Restore - -The backup system now supports **restoring VMInstance backups into a different namespace** (cross-namespace copy restores), with IP/MAC preservation and safe rename semantics. In-place backup/restores for VMDisk and VMInstance are improved: HelmReleases and DataVolumes are properly handled, and Velero failure messages are propagated to the Application status. The backup status structure has been refactored to store underlying resources as a generic opaque JSON object, enabling arbitrary application-specific metadata ([**@androndo**](https://github.com/androndo) in #2251, #2329, #2319). - -## Major Features and Improvements - -* **[api] Reject tenant names with dashes at Create time**: Enforces alphanumeric-only naming for Tenants at the API level, preventing names with hyphens that would silently fail during Helm reconciliation. A corresponding regex tightening and regression test suite hardens the validation ([**@lexfrei**](https://github.com/lexfrei) in #2380). - -* **[platform] Validate computed tenant namespace length**: Rejects Tenant creation when the computed ancestor-chain namespace would exceed the 63-character Kubernetes namespace limit, preventing opaque HelmRelease reconcile errors downstream ([**@lexfrei**](https://github.com/lexfrei) in #2376). - -* **[vm-instance] Rename subnets to networks and add dropdown selector**: Renames the misleading `subnets` field to `networks` in VMInstance for clarity, adds a dropdown selector for available networks in the dashboard form, and includes a migration to copy existing `subnets` values. The old field remains supported for backward compatibility ([**@sircthulhu**](https://github.com/sircthulhu) in #2263). - -* **[keycloak] Enable injecting themes**: Cozystack administrators can now inject custom Keycloak themes via `initContainers` for UI white-labeling and customization ([**@lllamnyp**](https://github.com/lllamnyp) in #2142). - -* **[keycloak-configure] Add email verification and SMTP configuration**: Adds configurable Keycloak settings for user self-registration, email verification, and SMTP server configuration, enabling automated user onboarding flows ([**@BROngineer**](https://github.com/BROngineer) in #2318). - -* **[postgres] Hardcode PostgreSQL 17 for monitoring databases**: Pins PostgreSQL 17.7 images for system databases (Grafana, Alerta, Harbor, Keycloak, SeaweedFS) and adds migration 37 to backfill `spec.version=v17` for existing PostgreSQL resources, preventing CNPG from defaulting to PostgreSQL 18 *(backported to v1.2.1)* ([**@IvanHunters**](https://github.com/IvanHunters) in #2304). - -* **[hack] Add host runtime preflight check**: New `check-host-runtime.sh` script and `make preflight` target that warns operators when a standalone containerd or docker runtime is running alongside the embedded k3s runtime, helping diagnose container runtime conflicts ([**@lexfrei**](https://github.com/lexfrei) in #2371). - -* **[hack] Add check-readiness.sh diagnostic script**: A new diagnostic script for tracking platform reconciliation by checking readiness of Packages, ArtifactGenerators, ExternalArtifacts, and HelmReleases, with support for watch mode and continuous monitoring ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2294). - -* **[mariadb] Always enable replication for consistent service naming**: MariaDB now always enables replication, creating `-primary`/`-secondary` services even for single-replica instances. This fixes dashboard visibility and backup functionality for single-replica setups ([**@sircthulhu**](https://github.com/sircthulhu) in #2279). - -* **[platform] Prevent installed packages deletion**: Adds `helm.sh/resource-policy: keep` annotation to packages, preventing automatic deletion when packages are disabled and restoring documented behavior *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2273). - -## Bug Fixes - -* **[cilium] Opt-out of cri-containerd.apparmor.d for nsenter init containers**: Opts cilium-agent init containers out of the `cri-containerd.apparmor.d` AppArmor profile on non-Talos variants, fixing `Init:CrashLoopBackOff` on Ubuntu 22.04+ and Debian *(backported to v1.2.2)* ([**@lexfrei**](https://github.com/lexfrei) in #2370). - -* **[virtual-machine] Exclude external VM services from Cilium BPF LB**: Adds `service-proxy-name: cozy-proxy` label to VM LoadBalancer services, telling Cilium to skip BPF processing. Fixes inter-tenant connectivity via public LB IPs and WholeIP functionality on Cilium 1.19+ *(backported to v1.2.2)* ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2357). - -* **[monitoring] Fix infra dashboards missing in default variant**: Includes `cozy-monitoring` namespace in the dashboard rendering condition, fixing infrastructure Grafana dashboards not rendering in the default platform variant *(backported to v1.2.2)* ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2365). - -* **[postgres] Fix system PostgreSQL images to 17.7-standard-trixie**: Normalizes system PostgreSQL image tags to use `17.7-standard-trixie` variant with migration logic for existing CNPG clusters *(backported to v1.2.2)* ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2364). - -* **[build] Filter git describe to match only v\* tags**: Adds `--match 'v*'` to `git describe` calls, preventing API subtags from being picked up instead of release tags and producing invalid Docker image tags *(backported to v1.2.2)* ([**@kvaps**](https://github.com/kvaps) in #2386). - -* **[platform] Fix resource allocation ratios not propagated to packages**: Restores propagation of CPU, memory, and ephemeral-storage allocation ratios to managed applications and KubeVirt, which were silently ignored since the bundle restructure *(backported to v1.2.1)* ([**@sircthulhu**](https://github.com/sircthulhu) in #2296). - -* **[kubernetes] Set explicit ephemeral-storage on virt-launcher pods**: Sets explicit `domain.resources` with ephemeral-storage on VirtualMachine spec to prevent virt-launcher pods from being evicted due to LimitRange defaults being too low for actual emptyDisk capacity ([**@kvaps**](https://github.com/kvaps) in #2317). - -* **[multus] Pin master CNI to 05-cilium.conflist**: Prevents a boot-time race condition where multus could auto-detect kube-ovn's conflist instead of Cilium's *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2315). - -* **[multus] Build custom image with DEL cache fix**: Fixes sandbox cleanup deadlock when CNI ADD never completes, preventing stale sandbox name reservations from permanently blocking pod creation *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2313). - -* **[linstor] Set verify-alg to crc32c**: Prevents DRBD connection failures on kernels where `crct10dif` is unavailable (e.g., Talos v1.12.6 with kernel 6.18.18) *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2303). - -* **[linstor] Preserve TCP ports during toggle-disk operations**: Fixes TCP port mismatches after toggle-disk operations that could cause DRBD resources to enter StandAlone state *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2292). - -## Dependencies & Version Updates - -* **[linstor] Update piraeus-server to v1.33.2 with selected backports**: Bumps LINSTOR server from v1.33.1 to v1.33.2 with backported patches for stale bitmap adjust retry, LUKS2 header sizing, and optimal I/O size detection *(backported to v1.2.2)* ([**@kvaps**](https://github.com/kvaps) in #2331). - -* **[kamaji] Update to 26.3.5-edge, drop upstreamed patches**: Updates Kamaji from edge-26.2.4 to 26.3.5-edge and removes two patches accepted upstream. Adds configurable probe tuning and DataStore readiness conditions ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2260). - -* **[talm] Release v0.23.0, v0.23.1, v0.24.0** (github.com/cozystack/talm): Migrates to the Talos v1.12 multi-document machine config format ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#116); fixes template rendering in `apply` command to resolve lookups ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/talm#119); bumps dependencies and modernizes codebase ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#124). - -* **[ansible-cozystack] Release v1.2.1, v1.2.2** (github.com/cozystack/ansible-cozystack): Exposes `publishing.externalIPs` and tenant-root ingress via role variables ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#30); adds comprehensive node prerequisites audit ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#27); replaces `ansible.utils.ipaddr` with a stdlib-based test plugin ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#24). - -## Security - -* **docs: add SECURITY.md**: Adds vulnerability reporting procedures, disclosure expectations, and supported release lines ([**@kvaps**](https://github.com/kvaps) in #2230). - -* **docs: add OpenSSF Best Practices badge to README**: Adds the OpenSSF Best Practices passing badge to the project README ([**@lexfrei**](https://github.com/lexfrei) in #2320). - -## Development, Testing, and CI/CD - -* **[ci] Replace cozystack-bot PAT with cozystack-ci GitHub App**: Replaces the long-lived cozystack-bot personal access token with short-lived, scoped tokens from the cozystack-ci GitHub App across all CI release workflows ([**@tym83**](https://github.com/tym83) in #2351; [**@kvaps**](https://github.com/kvaps) in #2383, #2392). - -* **[ci] Add Gemini Code Assist and CodeRabbit configuration**: Adds repository-level configuration for AI code reviewers with ignore patterns for vendored/generated code and incremental review settings ([**@lexfrei**](https://github.com/lexfrei) in #2385). - -* **[ci] Make tags workflow idempotent on re-runs**: Fixes CI to force-update API subtags and handle re-runs gracefully ([**@kvaps**](https://github.com/kvaps)). - -* **[tests] Fix Kafka E2E test timeout and retry race condition**: Increases Kafka E2E test timeout from 60s to 300s and fixes a retry race condition where `kubectl apply` could hit a still-deleting resource ([**@lexfrei**](https://github.com/lexfrei) in #2358). - -* **docs: adopt Conventional Commits for commit and PR titles**: Standardizes commit and PR title format to `type(scope): description` across all contributing docs and the PR template ([**@lexfrei**](https://github.com/lexfrei) in #2395). - -* **docs(ci): require screenshots for UI changes in PR template**: Adds a mandatory screenshots section to the PR template for UI-related changes ([**@kitsunoff**](https://github.com/kitsunoff) in #2407). - -## Documentation - -* **[website] Add ApplicationDefinition naming convention reference**: Documents how `cozystack-api` resolves kinds to their backing definitions ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#478). - -* **[website] Document Talos / talosctl / Cozystack version pairing**: Adds version compatibility matrix for installation ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#484). - -* **[website] Document namespace layout and parent/child derivation**: Explains tenant namespace hierarchy and parent/child namespace derivation rules ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#479). - -* **[website] Document the checkbox-then-edit-CR customization pattern for tenants**: Describes the workflow for customizing tenant settings via the CR after initial checkbox-based creation ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#485). - -* **[website] Add custom Keycloak themes documentation**: Covers the theme image contract, configuration, `imagePullSecrets`, and theme activation in the Keycloak admin console ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#463). - -* **[website] Add bonding (LACP) configuration how-to guide**: Covers network bonding configuration for Cozystack installations ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#459). - -* **[website] Improve registry mirrors for tenant Kubernetes in air-gapped guide**: Improved documentation for configuring registry mirrors in air-gapped environments ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#461). - -* **[website] Rewrite guide for ApplicationDefinition API (external-apps)**: Comprehensive rewrite of the external apps guide using the ApplicationDefinition API ([**@kitsunoff**](https://github.com/kitsunoff) in cozystack/website#488). - -* **[website] Add documentation for Go types usage**: Guide for using generated Go types for Cozystack managed applications as a Go module ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#465). - -* **[website] Update backup/restore documentation for VMI/VMDisk**: Updated backup documentation with VM instance and VM disk restore improvements ([**@androndo**](https://github.com/androndo) in cozystack/website#466). - -* **[website] Add OSS Health pages and OpenSSF badge**: Added OSS Health section with OpenSSF Scorecard and Best Practices badge to the website ([**@tym83**](https://github.com/tym83) in cozystack/website#470). - -* **[website] Add CozySummit Virtual 2026 program announcement**: Published the CozySummit Virtual 2026 program announcement blog post ([**@tym83**](https://github.com/tym83) in cozystack/website#472). - -* **[website] Add missing release announcements for v0.1–v0.41**: Backfilled missing release announcement blog posts for historical Cozystack versions ([**@tym83**](https://github.com/tym83) in cozystack/website#468). - -* **[website] Fix broken links and stale anchors across v1 docs**: Fixes 14 broken links and stale talm anchors ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#486). - -* **[website] Prefix bundle package names with cozystack. in v1 examples**: Corrects package naming in documentation examples ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#482). - -* **[website] Finish isolated-field removal and document opt-in policy labels**: Removes obsolete `isolated` field from tenant documentation and documents the new approach ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#481). - -* **[website] Add --take-ownership flag and describe networking.* fields**: Documents the `--take-ownership` flag and `networking.*` fields in the installation guide ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#480). - -* **[website] Fix KubeOVN MASTER_NODES example path and key in troubleshooting**: Corrects the MASTER_NODES example path ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#483). - -* **[external-apps-example] Replace MongoDB example with Minecraft apps**: Refactors the external apps example to use ApplicationDefinition API with Minecraft server applications ([**@lexfrei**](https://github.com/lexfrei) in cozystack/external-apps-example#2). - -## Governance - -* **Add Mattia Eleuteri ([@mattia-eleuteri](https://github.com/mattia-eleuteri)) as Maintainer**: CSI, Storage, Networking & Security ([**@tym83**](https://github.com/tym83) in #2345). - -* **Add Matthieu Robin ([@matthieu-robin](https://github.com/matthieu-robin)) as Maintainer**: Managed applications, platform quality, and benchmarking ([**@tym83**](https://github.com/tym83) in #2346). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@androndo**](https://github.com/androndo) -* [**@BROngineer**](https://github.com/BROngineer) -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@lllamnyp**](https://github.com/lllamnyp) -* [**@mattia-eleuteri**](https://github.com/mattia-eleuteri) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@sircthulhu**](https://github.com/sircthulhu) -* [**@tym83**](https://github.com/tym83) - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.2.0...v1.3.0-rc.1 diff --git a/docs/changelogs/v1.3.0.md b/docs/changelogs/v1.3.0.md deleted file mode 100644 index 60c800a8..00000000 --- a/docs/changelogs/v1.3.0.md +++ /dev/null @@ -1,238 +0,0 @@ - - -# Cozystack v1.3.0 - -Cozystack v1.3.0 brings **storage-aware pod scheduling** via a LINSTOR scheduler extender, a managed **LINSTOR GUI** web console with Keycloak SSO, a curated **VM Default Images** catalog for out-of-the-box virtual-machine provisioning, a new **WorkloadsReady / Events** observability surface with S3 bucket metering, and **cross-namespace VMInstance backup restore** with a full **RestoreJob dashboard** flow. The release also ships stricter tenant-name validation, VMInstance network-selector improvements, Keycloak theme injection and SMTP configuration, a host-runtime preflight check, and rolls up every fix from the v1.2.1 → v1.2.4 patch line. - -> **Note:** Items marked *(backported to v1.2.x)* were also shipped in v1.2.1, v1.2.2, v1.2.3, or v1.2.4 patch releases. - -## Feature Highlights - -### Storage-Aware Scheduling via the LINSTOR Extender - -The `cozystack-scheduler` now calls a **LINSTOR scheduler extender** for storage-locality-aware pod placement. When a pod declares both a `SchedulingClass` and LINSTOR-backed PVCs, the scheduler consults LINSTOR to prefer nodes where volume replicas already exist — reducing cross-node replication traffic and improving I/O latency for storage-heavy workloads such as databases, object stores, and VMs. - -The integration builds on the existing `SchedulingClass` tenant workload placement system introduced in v1.2.0 and requires no tenant-side configuration — workloads simply benefit once a SchedulingClass is assigned. Administrators can mix storage locality with the existing data-center / hardware-generation constraints defined on SchedulingClass CRs ([**@lllamnyp**](https://github.com/lllamnyp) in #2330). - -### LINSTOR GUI: Managed Web Console for Storage Administration - -A new opt-in `linstor-gui` system package deploys **LINBIT's linstor-gui web UI** alongside the LINSTOR controller with mTLS client authentication, non-root security context, and a ClusterIP-only service by default. When OIDC is configured on the platform, an optional **Keycloak-protected Ingress** (via oauth2-proxy) exposes the UI for browser access. Access is restricted to members of the `cozystack-cluster-admin` Keycloak group, consistent with host-cluster admin RBAC, and the gatekeeper blocks in-app LINSTOR authentication setup at the nginx proxy layer so the managed configuration cannot be subverted through the UI. - -Operators who prefer CLI access keep the existing `linstor` command; the GUI is strictly additive and stays disabled by default ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2382, #2390, #2415, #2419). - -### VM Default Images: Out-of-the-Box VM Provisioning - -The new `vm-default-images` package provides a curated set of **cluster-wide virtual-machine images** (Ubuntu, Debian, CentOS Stream, and others) as pre-populated DataVolumes, so tenants can provision VMs against well-known base images without first having to upload them. The package is opt-in via the `iaas` bundle and defaults to replicated storage for high availability. Migration 38 renames legacy `vm-image-*` DataVolumes to the new `vm-default-images-*` naming scheme, and the `vm-disk` chart gains a new "disk" source type for cloning from existing vm-disks in the same namespace ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2258). - -### Application Observability: WorkloadsReady, Events, and S3 Bucket Metering - -Applications now expose a **WorkloadsReady** condition on their status by querying associated WorkloadMonitor resources, giving operators a single place to check whether all underlying workloads (Deployments, StatefulSets, DaemonSets, PVCs) are healthy. The dashboard gains a new **Events tab** showing namespace-scoped Kubernetes events per application, with fallback to `.firstTimestamp` when `.eventTime` is absent. A long-standing bug where WorkloadMonitor's `Operational` status was never persisted is fixed in the same change ([**@lexfrei**](https://github.com/lexfrei) in #2356). - -The WorkloadMonitor reconciler is extended to track **COSI BucketClaim** objects as first-class Workloads, and the bucket controller now queries SeaweedFS logical and physical bucket-size metrics from VictoriaMetrics via a namespace-scoped monitoring endpoint, enabling S3 billing integration on par with Pods and PVCs ([**@kitsunoff**](https://github.com/kitsunoff) in #2391). Workloads are also enriched with `workloads.cozystack.io/resource-preset` and source-object labels so downstream billing pipelines can correlate monitors with the tenant preset that produced them ([**@androndo**](https://github.com/androndo) in #2416). - -### Cross-Namespace VM Backup Restore and RestoreJob Dashboard - -The backup system now supports **restoring VMInstance backups into a different namespace** (cross-namespace copy restores) with IP/MAC preservation and safe rename semantics. In-place backup and restore flows for VMDisk and VMInstance are improved: HelmReleases and DataVolumes are properly handled, and Velero failure messages are propagated to the Application status. The backup status structure has been refactored to store underlying resources as a generic opaque JSON object, enabling arbitrary application-specific metadata without status-schema churn ([**@androndo**](https://github.com/androndo) in #2251, #2319, #2329). - -The dashboard now ships a complete **RestoreJob experience**: list view, details page, create form, and sidebar entry, with a "Same as backup" fallback rendering when `spec.targetApplicationRef` is omitted. Non-CRD-backed sidebar factories (`kube-*`, `plan`, `backupjob`, `backup`, `restorejob`) are marked static so they pick up consistent managed-by labels across reconciles ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2437). - -## Major Features and Improvements - -* **[api] Reject tenant names with dashes at Create time**: Enforces alphanumeric-only naming for Tenants at the API level, preventing names with hyphens that would silently fail during Helm reconciliation. A corresponding regex tightening and regression test suite hardens the validation ([**@lexfrei**](https://github.com/lexfrei) in #2380). - -* **[platform] Validate computed tenant namespace length**: Rejects Tenant creation when the computed ancestor-chain namespace would exceed the 63-character Kubernetes namespace limit, preventing opaque HelmRelease reconcile errors downstream ([**@lexfrei**](https://github.com/lexfrei) in #2376). - -* **[vm-instance] Rename subnets to networks and add dropdown selector**: Renames the misleading `subnets` field to `networks` in VMInstance for clarity, adds a dropdown selector for available networks in the dashboard form, and includes migration 36 to copy existing `subnets` values. The old field remains supported for backward compatibility ([**@sircthulhu**](https://github.com/sircthulhu) in #2263). - -* **[keycloak] Enable injecting themes**: Cozystack administrators can now inject custom Keycloak themes via `initContainers` for UI white-labeling and customization ([**@lllamnyp**](https://github.com/lllamnyp) in #2142). - -* **[keycloak-configure] Add email verification and SMTP configuration**: Adds configurable Keycloak settings for user self-registration, email verification, and SMTP server configuration, enabling automated user onboarding flows ([**@BROngineer**](https://github.com/BROngineer) in #2318). - -* **[postgres] Pin system PostgreSQL to 17.7-standard-trixie**: Pins the PostgreSQL image for system databases (Grafana, Alerta, Harbor, Keycloak, SeaweedFS) to `17.7-standard-trixie` across chart templates and `values.yaml`, and ships migration 37 to patch existing CNPG Cluster `imageName` fields to the same variant (handling unset, any PG 17 tag, and bare-version tags). This prevents CNPG from defaulting to PostgreSQL 18 and locks system databases to the trixie variant consistent with the monitoring stack requirements *(related backports shipped in v1.2.1 via #2309 and v1.2.2 via #2364)* ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2369). - -* **[platform] Prevent installed packages deletion**: Adds the `helm.sh/resource-policy: keep` annotation to platform packages so disabling a package no longer triggers automatic Helm deletion, restoring the documented behavior where operators must explicitly delete a package *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2273). - -* **[mariadb] Always enable replication for consistent service naming**: MariaDB now always enables replication, creating `-primary`/`-secondary` services even for single-replica instances. This fixes dashboard visibility and backup functionality for single-replica setups ([**@sircthulhu**](https://github.com/sircthulhu) in #2279). - -* **[hack] Add host runtime preflight check**: New `check-host-runtime.sh` script and `make preflight` target that warns operators when a standalone containerd or docker runtime is running alongside the embedded k3s runtime, helping diagnose container-runtime conflicts early in an installation ([**@lexfrei**](https://github.com/lexfrei) in #2371). - -* **[hack] Add check-readiness.sh diagnostic script**: A new diagnostic script for tracking platform reconciliation by checking readiness of Packages, ArtifactGenerators, ExternalArtifacts, and HelmReleases, with support for watch mode and continuous monitoring ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2294). - -* **[platform] Add resourcePreset labels to WorkloadMonitor labels**: WorkloadMonitor labels with the `workloads.cozystack.io/` prefix are now propagated onto created Workloads; created Workloads always include the reserved `workloads.cozystack.io/monitor` label, and Helm app charts add `workloads.cozystack.io/resource-preset` metadata to WorkloadMonitor manifests, enabling downstream billing pipelines to correlate monitors with the tenant preset that produced them ([**@androndo**](https://github.com/androndo) in #2416). - -## Bug Fixes - -* **[platform] Migrate ACME HTTP-01 to ingressClassName API**: Switches ACME HTTP-01 issuance from the deprecated `acme.cert-manager.io/http01-ingress-class` annotation to the modern `ingressClassName` field on `ClusterIssuer` and solver pods. Previously, ClusterIssuers referenced a non-existent `nginx` class while each Ingress individually overrode it via annotation — producing `ingressClassName and class cannot be set at the same time` errors when tenants attempted to migrate to the modern field. The migration is atomic: both the ClusterIssuer and consuming Ingresses are updated together *(backported to v1.2.4)* ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2436). - -* **[harbor] Remove incorrect tenant module flags**: Harbor is a PaaS service, not a tenant module. Incorrect `spec.dashboard.module: true` and `internal.cozystack.io/tenantmodule` flags caused Harbor to appear in the sidebar "Modules" section and be misclassified by controllers handling tenant modules. The flags are now removed so Harbor is displayed in its proper PaaS category and is no longer treated as a tenant-scoped HelmRelease ([**@kvaps**](https://github.com/kvaps) in #2444). - -* **[kube-ovn] Resolve kubeovn-plunger RBAC forbidden on deployments**: Grants `kube-ovn-plunger` the RBAC needed to list Deployments so it can reconcile `ovn-central`, fixing `deployments.apps is forbidden` errors in `cozy-kubeovn` ([**@kvaps**](https://github.com/kvaps) in #2441). - -* **[cilium] Opt-out of cri-containerd.apparmor.d for nsenter init containers**: Opts cilium-agent init containers out of the `cri-containerd.apparmor.d` AppArmor profile on non-Talos variants (`cilium-generic`, `kubeovn-cilium-generic`), fixing `Init:CrashLoopBackOff` on Ubuntu 22.04+ and Debian where the profile denies `nsenter` namespace entry. Talos variants are untouched as Talos does not load the AppArmor LSM *(backported to v1.2.2)* ([**@lexfrei**](https://github.com/lexfrei) in #2370). - -* **[virtual-machine] Exclude external VM services from Cilium BPF LB**: Adds the `service.kubernetes.io/service-proxy-name: cozy-proxy` label to VM LoadBalancer services with `external: true`, telling Cilium to skip BPF processing entirely. Fixes inter-tenant connectivity via public LB IPs (Cilium's DNAT caused cross-tenant pod-to-pod flow classification, triggering CiliumClusterwideNetworkPolicy blocks) and restores WholeIP behavior on Cilium 1.19+ where wildcard service drop entries previously blocked traffic to LB IPs on undeclared ports *(backported to v1.2.2)* ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2357). - -* **[monitoring] Fix infra dashboards missing in default variant**: Includes the `cozy-monitoring` namespace in the dashboard rendering condition, fixing infrastructure Grafana dashboards not rendering in the default platform variant (only the `tenant-root` namespace was previously checked) *(backported to v1.2.2)* ([**@mattia-eleuteri**](https://github.com/mattia-eleuteri) in #2365). - -* **[build] Filter git describe to match only v* tags**: Adds `--match 'v*'` to all `git describe` calls in `hack/common-envs.mk`, preventing the `api/apps/v1alpha1/vX.Y.Z` subtag from being picked up instead of the release tag and producing invalid Docker image tags *(backported to v1.2.2)* ([**@kvaps**](https://github.com/kvaps) in #2386). - -* **[platform] Fix resource allocation ratios not propagated to packages**: Restores propagation of `cpuAllocationRatio`, `memoryAllocationRatio`, and `ephemeralStorageAllocationRatio` from `platform/values.yaml` to the `cozystack-values` Secret that managed applications and KubeVirt read, fixing a regression introduced in the bundle restructure that silently ignored operator-configured ratios *(backported to v1.2.1)* ([**@sircthulhu**](https://github.com/sircthulhu) in #2296). - -* **[kubernetes] Set explicit ephemeral-storage on virt-launcher pods**: Sets explicit `domain.resources` ephemeral-storage on the VirtualMachine spec to prevent virt-launcher pods from being evicted because LimitRange defaults were too small for the actual emptyDisk capacity *(backported to v1.2.3)* ([**@kvaps**](https://github.com/kvaps) in #2317). - -* **[multus] Pin master CNI to 05-cilium.conflist**: Prevents a boot-time race where multus could auto-detect kube-ovn's conflist instead of Cilium's, which would cause pods to bypass the Cilium chain entirely and lose their endpoint *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2315). - -* **[multus] Build custom image with DEL cache fix**: Fixes sandbox cleanup deadlock when CNI ADD never completes, preventing stale sandbox name reservations from permanently blocking pod creation after a node disruption *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2313). - -* **[linstor] Set verify-alg to crc32c**: Prevents DRBD connection failures on kernels where `crct10dif` is unavailable (e.g., Talos v1.12.6 with kernel 6.18.18) by setting the LINSTOR verify-alg controller default to `crc32c` *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2303). - -* **[linstor] Preserve TCP ports during toggle-disk operations**: Saves existing TCP ports into the `LayerPayload` before `removeLayerData()` deletes them, preventing DRBD resources from entering StandAlone state when a satellite misses the resulting update *(backported to v1.2.1)* ([**@kvaps**](https://github.com/kvaps) in #2292). - -* **[linstor] Increase satellite startup probe failure threshold**: Raises the LINSTOR satellite `startupProbe` `failureThreshold` from 3 to 30 (30s → 300s) in the `LinstorSatelliteConfiguration` pod template, giving satellites with slow storage initialization enough time to come up without being killed and restarted ([**@Arsolitt**](https://github.com/Arsolitt) in #2425). - -## Security - -* **docs: add SECURITY.md**: Adds vulnerability reporting procedures, disclosure expectations, and supported release lines ([**@kvaps**](https://github.com/kvaps) in #2230). - -* **docs: add OpenSSF Best Practices badge to README**: Adds the OpenSSF Best Practices passing badge to the project README ([**@lexfrei**](https://github.com/lexfrei) in #2320). - -## Dependencies & Version Updates - -* **[kube-ovn] Bump kube-ovn to v1.15.10 with port-group regression fix**: Updates `packages/system/kubeovn` to upstream v1.15.10 (from v1.15.3) and carries a patch for `pkg/controller/pod.go` that preserves a VM LSP's port-group memberships when Kubernetes GCs a completed virt-launcher pod while another virt-launcher pod of the same VM is still running. Without the patch, the destination pod of a successful live migration lost its security groups, network policies, and node-scoped routing until `kube-ovn-controller` was restarted ([**@kvaps**](https://github.com/kvaps) in #2443). - -* **[monitoring] Upgrade victoria-metrics-operator to v0.68.4**: Bumps the vendored `victoria-metrics-operator` Helm chart from 0.59.1 to 0.61.0 (operator appVersion v0.68.1 → v0.68.4), picking up upstream fixes for `VMPodScrape` port routing on VMAgent/VLAgent and `StatefulSet` pod deletion (not eviction) when `maxUnavailable=100%` ([**@lexfrei**](https://github.com/lexfrei) in #2426). - -* **[linstor] Update piraeus-server to v1.33.2 with selected backports**: Bumps LINSTOR server from v1.33.1 to v1.33.2 with backported patches for stale bitmap adjust retry, LUKS2 header sizing, optimal I/O size detection, and the maintainer implementation. All patches verified against upstream v1.33.2 with `git apply --check` and `gradlew compileJava` *(backported to v1.2.2)* ([**@kvaps**](https://github.com/kvaps) in #2331). - -* **[kamaji] Update to 26.3.5-edge, drop upstreamed patches**: Updates Kamaji from edge-26.2.4 to 26.3.5-edge and removes two patches accepted upstream. Adds configurable probe tuning and DataStore readiness conditions ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2260). - -* **[talm] Release v0.23.0, v0.23.1, v0.24.0** (github.com/cozystack/talm): Migrates to the Talos v1.12 multi-document machine config format ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#116); renders templates online in `apply` to resolve lookups ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/talm#119); bumps dependencies and modernizes the codebase ([**@lexfrei**](https://github.com/lexfrei) in cozystack/talm#124). - -* **[ansible-cozystack] Release v1.2.1, v1.2.2, v1.2.4** (github.com/cozystack/ansible-cozystack): Exposes `publishing.externalIPs` and tenant-root ingress via role variables ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#30); adds a comprehensive node prerequisites audit ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#27); replaces `ansible.utils.ipaddr` with a stdlib-based test plugin ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#24); adds `v` prefix to collection version in requirements.yml examples ([**@lexfrei**](https://github.com/lexfrei) in cozystack/ansible-cozystack#23); tracks installer releases v1.2.1 through v1.2.4 ([**@app/renovate**](https://github.com/apps/renovate) in cozystack/ansible-cozystack#20, #22, #29, #31, #32). - -## Development, Testing, and CI/CD - -* **[ci] Replace cozystack-bot PAT with cozystack-ci GitHub App**: Replaces the long-lived `cozystack-bot` personal access token with short-lived, scoped tokens from the `cozystack-ci` GitHub App across all release workflows (`tags.yaml`, `auto-release.yaml`, `pull-requests-release.yaml`), improving security and auditability of CI operations ([**@tym83**](https://github.com/tym83) in #2351; [**@kvaps**](https://github.com/kvaps) in #2383, #2392). - -* **[ci] Add Gemini Code Assist and CodeRabbit configuration**: Adds repository-level configuration for AI code reviewers with ignore patterns for vendored/generated code and incremental review settings ([**@lexfrei**](https://github.com/lexfrei) in #2385). - -* **[ci] Promote next/ trunk on new minor/major releases**: Updates `update-website-docs` in `tags.yaml` to match the new docs-versioning contract — the website repo replaces the old "pre-create `vX.Y/` draft directory" scheme with a permanent `content/en/docs/next/` trunk, and released version directories are promoted explicitly by the release workflow ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2433). - -* **[tests] Fix Kafka E2E test timeout and retry race condition**: Increases Kafka E2E test timeout from 60s to 300s and fixes a retry race where `kubectl apply` could hit a still-deleting resource ([**@lexfrei**](https://github.com/lexfrei) in #2358). - -* **docs: adopt Conventional Commits for commit and PR titles**: Standardizes commit and PR title format to `type(scope): description` across all contributing docs and the PR template ([**@lexfrei**](https://github.com/lexfrei) in #2395). - -* **docs(ci): require screenshots for UI changes in PR template**: Adds a mandatory screenshots section to the PR template for UI-related changes ([**@kitsunoff**](https://github.com/kitsunoff) in #2407). - -* **chore(maintenance): add @myasnikovdaniil to CODEOWNERS**: Adds @myasnikovdaniil to the default owners in `.github/CODEOWNERS` for automatic review requests ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2434). - -## Documentation - -* **[website] Add ApplicationDefinition naming convention reference**: Documents how `cozystack-api` resolves kinds to their backing definitions ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#478). - -* **[website] Document Talos / talosctl / Cozystack version pairing**: Adds a version compatibility matrix for installation ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#484). - -* **[website] Document namespace layout and parent/child derivation**: Explains tenant namespace hierarchy and parent/child namespace derivation rules ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#479). - -* **[website] Document the checkbox-then-edit-CR customization pattern for tenants**: Describes the workflow for customizing tenant settings via the CR after initial checkbox-based creation ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#485). - -* **[website] Add custom Keycloak themes documentation**: Covers the theme image contract, configuration, `imagePullSecrets`, and theme activation in the Keycloak admin console ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#463). - -* **[website] Add bonding (LACP) configuration how-to guide**: Covers network bonding configuration for Cozystack installations ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#459). - -* **[website] Improve registry mirrors for tenant Kubernetes in air-gapped guide**: Improves documentation for configuring registry mirrors in air-gapped environments ([**@sircthulhu**](https://github.com/sircthulhu) in cozystack/website#461). - -* **[website] Rewrite guide for ApplicationDefinition API (external-apps)**: Comprehensive rewrite of the external apps guide using the ApplicationDefinition API with Minecraft server examples ([**@kitsunoff**](https://github.com/kitsunoff) in cozystack/website#488). - -* **[website] Add documentation for Go types usage**: Guide for using generated Go types for Cozystack managed applications as a Go module ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#465). - -* **[website] Update backup/restore documentation for VMI/VMDisk**: Updates backup documentation with VM instance and VM disk restore improvements ([**@androndo**](https://github.com/androndo) in cozystack/website#466). - -* **[website] Refactor docs versions to major.minor variants**: Moves docs to major.minor versioning for the v1.x series ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#477). - -* **[website] Trunk-based versioning with permanent next/ directory**: Replaces the old "pre-create `vX.Y/` draft directory" scheme with a permanent `content/en/docs/next/` trunk; released version directories are promoted explicitly by `hack/release_next.sh` on new minor/major releases, and routing between `next/` and `vX.Y/` is Makefile-driven ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#495). - -* **[website] Add updated OpenAPI spec**: Updates the OpenAPI specification for managed applications reference ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#469). - -* **[website] Add OpenAPI spec download to GitHub Pages build**: Fixes the GitHub Pages build to include the OpenAPI spec download ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#494). - -* **[website] Add OSS Health pages and OpenSSF badge**: Adds OSS Health section with OpenSSF Scorecard and Best Practices badges to the website ([**@tym83**](https://github.com/tym83) in cozystack/website#470). - -* **[website] Add Telemetry page under OSS Health section**: Adds the Telemetry page with initial data seeding to the OSS Health docs ([**@tym83**](https://github.com/tym83) in cozystack/website#471, cozystack/website#504). - -* **[website] Blog: OSS Health section launch announcement**: Publishes the announcement blog post for the OSS Health section ([**@tym83**](https://github.com/tym83) in cozystack/website#474). - -* **[website] Fix OpenSSF canonical status URL**: Changes the OpenSSF canonical status URL from pt-BR to en ([**@tym83**](https://github.com/tym83) in cozystack/website#475). - -* **[website] Add CozySummit Virtual 2026 program announcement**: Publishes the CozySummit Virtual 2026 program announcement blog post ([**@tym83**](https://github.com/tym83) in cozystack/website#472). - -* **[website] Add missing release announcements for v0.1–v0.41**: Backfills missing release announcement blog posts for historical Cozystack versions ([**@tym83**](https://github.com/tym83) in cozystack/website#468). - -* **[website] Blog: managed PostgreSQL with synchronous replication**: Adds a post covering the managed PostgreSQL synchronous-replication feature ([**@tym83**](https://github.com/tym83) in cozystack/website#497). - -* **[website] Blog taxonomies and client-side filter UI**: Registers article-type and topic taxonomies and adds a client-side filter on the blog list page ([**@tym83**](https://github.com/tym83) in cozystack/website#499). - -* **[website] Add images frontmatter for social preview on existing posts**: Adds images frontmatter for social preview on existing blog posts ([**@tym83**](https://github.com/tym83) in cozystack/website#498). - -* **[website] Fix broken links and stale anchors across v1 docs**: Fixes 14 broken links and stale talm anchors ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#486). - -* **[website] Prefix bundle package names with cozystack. in v1 examples**: Corrects package naming in documentation examples ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#482). - -* **[website] Finish isolated-field removal and document opt-in policy labels**: Removes the obsolete `isolated` field from tenant documentation and documents the new opt-in policy labels approach ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#481). - -* **[website] Add --take-ownership flag and describe networking.* fields**: Documents the `--take-ownership` flag and `networking.*` fields in the installation guide ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#480). - -* **[website] Fix KubeOVN MASTER_NODES example path and key in troubleshooting**: Corrects the MASTER_NODES example path and key ([**@lexfrei**](https://github.com/lexfrei) in cozystack/website#483). - -* **[website] Add CLAUDE.md for AI agent guidance**: Adds a CLAUDE.md file describing the trunk-based docs architecture for AI agent guidance ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#489). - -* **[website] Update /docs/v1/ redirect to latest v1.2**: Updates the `/docs/v1/` redirect target to point to the latest v1.2 docs on GitHub Pages ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#492). - -* **[website] Remove nbykov from CODEOWNERS and CLAUDE.md**: Cleans up CODEOWNERS and CLAUDE.md entries ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in cozystack/website#491). - -* **[website] Add Ahrefs Analytics tracker**: Adds the Ahrefs Analytics tracker to the website ([**@tym83**](https://github.com/tym83) in cozystack/website#503). - -* **[website] Add breathing room between navbar and hero on OSS Health**: Minor styling fix for the OSS Health section ([**@tym83**](https://github.com/tym83) in cozystack/website#500). - -* **[website] Fix og social badge image and title**: Updates the social badge image and title ([**@tym83**](https://github.com/tym83) in cozystack/website#487). - -* **[website] Update managed apps reference for v1.2.1**: Automated managed-apps reference update ([**@cozystack-bot**](https://github.com/cozystack-bot) in cozystack/website#464). - -* **[external-apps-example] Replace MongoDB example with Minecraft apps**: Refactors the external apps example to use the ApplicationDefinition API with Minecraft server applications ([**@lexfrei**](https://github.com/lexfrei) in cozystack/external-apps-example#2). - -* **docs: update README introductory description**: Refines the platform positioning and improves clarity on core capabilities in the main README ([**@tym83**](https://github.com/tym83) in #2409). - -## Governance - -* **Add Mattia Eleuteri ([@mattia-eleuteri](https://github.com/mattia-eleuteri)) as Maintainer**: CSI, Storage, Networking & Security ([**@tym83**](https://github.com/tym83) in #2345). - -* **Add Matthieu Robin ([@matthieu-robin](https://github.com/matthieu-robin)) as Maintainer**: Managed applications, platform quality, and benchmarking ([**@tym83**](https://github.com/tym83) in #2346). - -## Contributors - -We'd like to thank all contributors who made this release possible: - -* [**@androndo**](https://github.com/androndo) -* [**@Arsolitt**](https://github.com/Arsolitt) -* [**@BROngineer**](https://github.com/BROngineer) -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kitsunoff**](https://github.com/kitsunoff) -* [**@kvaps**](https://github.com/kvaps) -* [**@lexfrei**](https://github.com/lexfrei) -* [**@lllamnyp**](https://github.com/lllamnyp) -* [**@mattia-eleuteri**](https://github.com/mattia-eleuteri) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) -* [**@sircthulhu**](https://github.com/sircthulhu) -* [**@tym83**](https://github.com/tym83) - -### New Contributors - -We're excited to welcome our first-time contributors: - -* [**@Arsolitt**](https://github.com/Arsolitt) — First contribution! - ---- - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.2.0...v1.3.0 diff --git a/docs/changelogs/v1.3.1.md b/docs/changelogs/v1.3.1.md deleted file mode 100644 index 0f149d0d..00000000 --- a/docs/changelogs/v1.3.1.md +++ /dev/null @@ -1,37 +0,0 @@ - - -# v1.3.1 (2026-04-28) - -Patch release covering a TenantNamespace IDOR fix in the API, a destructive `post-upgrade` hook removed from the etcd chart, kamaji controller stability, a `linstor-csi` bump that fixes live migration on Protocol-A/B DRBD resources, the missing `linstor-gui` build wiring, and a velero RBAC fix that unblocked installs on bundles without Velero. - -## Security - -* **fix(api): prevent IDOR in TenantNamespace Get and Watch handlers**: Two IDOR (Insecure Direct Object Reference) vulnerabilities allowed authenticated users to read TenantNamespace metadata they had no RoleBinding for. The `Get` and `Watch` handlers now go through a new `hasAccessToNamespace()` helper that lists RoleBindings scoped only to the target namespace (orders of magnitude faster than the previous all-cluster scan), returns `NotFound` instead of leaking existence on unauthorized access, and applies the same check on the `Watch` filter path. Includes regression tests for the unauthorized paths. ([**@IvanHunters**](https://github.com/IvanHunters) in #2471, backport #2524) - -## Features - -* **feat(linstor): bump linstor-csi to v1.10.6 with Protocol-C dual-attach fix**: Live migration of KubeVirt VMs on Protocol-A/B (async) DRBD volumes no longer fails with `Protocol C required`. `linstor-csi` v1.10.6 now installs a `Protocol=C` override on the resource-definition during dual-attach and reverts it on detach, so `replicated-async` StorageClasses and other Protocol-A/B resource groups support live migration without manual `drbdadm adjust` intervention. ([**@kvaps**](https://github.com/kvaps) in #2496, backport #2505) - -## Fixes - -* **fix(backups): move velero-configmap Role to velero chart**: The `backupstrategy-controller` (a default package) declared a Role/RoleBinding scoped to the `cozy-velero` namespace for managing `ResourceModifier` ConfigMaps. On bundles where Velero was not enabled, that namespace did not exist and the HelmRelease failed with `namespaces "cozy-velero" not found`, blocking installation. The Role/RoleBinding now lives in the velero chart, so it is created only when velero is actually deployed. ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2459, backport #2467) - -* **fix(etcd): remove destructive post-upgrade cert-regeneration hook**: The etcd chart ran a `post-upgrade` Helm hook on every upgrade that deleted etcd TLS Secrets (`etcd-ca-tls`, `etcd-peer-ca-tls`, `etcd-client-tls`, `etcd-peer-tls`, `etcd-server-tls`) and then deleted etcd pods, forcing cert-manager to re-issue the entire etcd CA chain. On clusters with Kamaji-managed tenant control planes this put every tenant `kube-apiserver` into CrashLoopBackOff until each DataStore was manually re-reconciled. The hook was a one-shot `2.6.0 → 2.6.1` migration that became a permanent footgun once chart versioning moved to `0.0.0+` (always `< 2.6.1` per semver) and after the underlying `rotationPolicy: Always` issue was fixed in `47d81f70`. The hook is now removed entirely. ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2462, backport #2511) - -* **fix(kamaji): increase memory limits and add startup probe**: The kamaji controller frequently entered CrashLoopBackOff due to OOMKills (exit 137) within ~20–25 seconds of startup, with the readiness probe failing while the controller was still finishing initialization. Memory limit raised from 500Mi to 512Mi, request from 100Mi to 256Mi, and a 60-second startup probe (12 attempts × 5s periods) is added so the controller has room to boot before liveness/readiness probes engage. ([**@IvanHunters**](https://github.com/IvanHunters) in #2421, backport #2491) - -## Build - -* **build(linstor): include linstor-gui in root image build target**: The `linstor-gui` package (added in #2382) was never wired into the root `Makefile`'s `build:` target, so CI never built or published the image. `ghcr.io/cozystack/cozystack/linstor-gui` returned `NAME_UNKNOWN` and `values.yaml` stayed pinned to `tag: 2.3.0` without a digest. The missing build line is added so the next CI run publishes the image and the per-package `Makefile` digest-pins `values.yaml` automatically. ([**@myasnikovdaniil**](https://github.com/myasnikovdaniil) in #2498, backport #2518) - -## Contributors - -Thanks to everyone who contributed to this patch release: - -* [**@IvanHunters**](https://github.com/IvanHunters) -* [**@kvaps**](https://github.com/kvaps) -* [**@myasnikovdaniil**](https://github.com/myasnikovdaniil) - -**Full Changelog**: https://github.com/cozystack/cozystack/compare/v1.3.0...v1.3.1 diff --git a/examples/backups/vmi/00-helpers.sh b/examples/backups/vmi/00-helpers.sh deleted file mode 100755 index 38405495..00000000 --- a/examples/backups/vmi/00-helpers.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash -# Helper functions and variables for the VMInstance backup/restore demo -# Source this file in other scripts: source "$(dirname "$0")/00-helpers.sh" - -# ANSI color codes -export RED='\033[0;31m' -export GREEN='\033[0;32m' -export YELLOW='\033[1;33m' -export BLUE='\033[0;34m' -export MAGENTA='\033[0;35m' -export CYAN='\033[0;36m' -export WHITE='\033[1;37m' -export NC='\033[0m' # No Color -export BOLD='\033[1m' - -# Default settings -export NAMESPACE="${NAMESPACE:-tenant-root}" -export BACKUP_STORAGE_LOCATION="${BACKUP_STORAGE_LOCATION:-default}" - -# Logging functions (output to stderr to avoid polluting captured output) -log_info() { - echo -e "${BLUE}ℹ${NC} $*" >&2 -} - -log_success() { - echo -e "${GREEN}✔${NC} $*" >&2 -} - -log_warning() { - echo -e "${YELLOW}⚠${NC} $*" >&2 -} - -log_error() { - echo -e "${RED}✖${NC} $*" >&2 -} - -log_step() { - echo -e "\n${MAGENTA}${BOLD}▶ $*${NC}" >&2 -} - -log_substep() { - echo -e "${CYAN} → $*${NC}" >&2 -} - -log_command() { - echo -e "${WHITE} \$ $*${NC}" >&2 -} - -# Wait for user to press Enter -wait_for_enter() { - echo -e "\n${CYAN}Press Enter to continue...${NC}" >&2 - read -r -} - -# Check if a Kubernetes resource exists -resource_exists() { - local resource_type="$1" - local resource_name="$2" - local namespace="${3:-}" - - if [[ -n "$namespace" ]]; then - kubectl get "$resource_type" "$resource_name" -n "$namespace" &>/dev/null - else - kubectl get "$resource_type" "$resource_name" &>/dev/null - fi -} - -# Wait for a resource field to reach a desired value -wait_for_field() { - local resource_type="$1" - local resource_name="$2" - local jsonpath="$3" - local desired="$4" - local namespace="${5:-}" - local timeout="${6:-300}" - - log_substep "Waiting for $resource_type/$resource_name $jsonpath to become '$desired'..." - - local elapsed=0 - local ns_flag="" - [[ -n "$namespace" ]] && ns_flag="-n $namespace" - - while true; do - local current - # shellcheck disable=SC2086 - current=$(kubectl get "$resource_type" "$resource_name" $ns_flag -o jsonpath="$jsonpath" 2>/dev/null || true) - if [[ "$current" == "$desired" ]]; then - log_success "$resource_type/$resource_name reached '$desired'" - return 0 - fi - if [[ $elapsed -ge $timeout ]]; then - log_error "Timeout waiting for $resource_type/$resource_name (current: '$current', expected: '$desired')" - return 1 - fi - sleep 5 - elapsed=$((elapsed + 5)) - echo -n "." >&2 - done -} - -# Print a separator line -separator() { - echo -e "\n${CYAN}────────────────────────────────────────────────────────────${NC}\n" >&2 -} - -# Print script header -print_header() { - local title="$1" - echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${NC}" >&2 - echo -e "${MAGENTA}${BOLD}║${NC} ${WHITE}${BOLD}$title${NC}" >&2 - echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${NC}\n" >&2 -} diff --git a/examples/backups/vmi/01-create-strategies.sh b/examples/backups/vmi/01-create-strategies.sh deleted file mode 100755 index 78aa34d3..00000000 --- a/examples/backups/vmi/01-create-strategies.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash -# Step 01: Create Velero backup/restore strategies for VMInstance and VMDisk -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/00-helpers.sh" - -print_header "Step 1: Create Velero Strategies" - -log_step "Creating VMInstance strategy..." -log_command "kubectl apply -f - (Velero strategy: vminstance-strategy)" - -kubectl apply -f - <<'EOF' -apiVersion: strategy.backups.cozystack.io/v1alpha1 -kind: Velero -metadata: - name: vminstance-strategy -spec: - template: - # Symmetric restore filters: kubevirt-velero-plugin requires launcher pods in the backup, - # but restore orLabelSelectors limit what is applied from the tarball (e.g. skip another - # VM's pod that Velero added via PVC item action). VMDisk OR branches are appended by - # the controller from backup.status.underlyingResources or the Velero backup annotation. - restoreSpec: - existingResourcePolicy: update - includedNamespaces: - - '{{ .Application.metadata.namespace }}' - orLabelSelectors: - - matchLabels: - app.kubernetes.io/instance: 'vm-instance-{{ .Application.metadata.name }}' - - matchLabels: - apps.cozystack.io/application.kind: '{{ .Application.kind }}' - apps.cozystack.io/application.name: '{{ .Application.metadata.name }}' - includedResources: - - helmreleases.helm.toolkit.fluxcd.io - - virtualmachines.kubevirt.io - - virtualmachineinstances.kubevirt.io - - pods - - persistentvolumeclaims - - configmaps - - secrets - - controllerrevisions.apps - includeClusterResources: false - excludedResources: - # Required to avoid conflict with restored DV from HR VMDisk - - datavolumes.cdi.kubevirt.io - - spec: # see https://velero.io/docs/v1.17/api-types/backup/ - includedNamespaces: - - '{{ .Application.metadata.namespace }}' - orLabelSelectors: - # VM resources (VirtualMachine, DataVolume, PVC, etc.) - - matchLabels: - app.kubernetes.io/instance: 'vm-instance-{{ .Application.metadata.name }}' - # HelmRelease (the Cozystack app object) - - matchLabels: - apps.cozystack.io/application.kind: '{{ .Application.kind }}' - apps.cozystack.io/application.name: '{{ .Application.metadata.name }}' - includedResources: - - helmreleases.helm.toolkit.fluxcd.io - - virtualmachines.kubevirt.io - - virtualmachineinstances.kubevirt.io - # Required by kubevirt-velero-plugin for running VMs ("launcher pod must be in backup"). - - pods - # Required by kubevirt-velero-plugin requires DV to be in backup of VM, but it excludes in restores - - datavolumes.cdi.kubevirt.io - - persistentvolumeclaims - - configmaps - - secrets - - controllerrevisions.apps - includeClusterResources: false - storageLocation: '{{ .Parameters.backupStorageLocationName }}' - volumeSnapshotLocations: - - '{{ .Parameters.backupStorageLocationName }}' - snapshotVolumes: true - snapshotMoveData: true - ttl: 720h0m0s - itemOperationTimeout: 24h0m0s -EOF - -log_success "VMInstance strategy created" - -separator - -log_step "Creating VMDisk strategy..." -log_command "kubectl apply -f - (Velero strategy: vmdisk-strategy)" - -kubectl apply -f - <<'EOF' -apiVersion: strategy.backups.cozystack.io/v1alpha1 -kind: Velero -metadata: - name: vmdisk-strategy -spec: - template: - restoreSpec: - existingResourcePolicy: update - includedNamespaces: - - '{{ .Application.metadata.namespace }}' - orLabelSelectors: - - matchLabels: - app.kubernetes.io/instance: 'vm-disk-{{ .Application.metadata.name }}' - - matchLabels: - apps.cozystack.io/application.kind: '{{ .Application.kind }}' - apps.cozystack.io/application.name: '{{ .Application.metadata.name }}' - includedResources: - - helmreleases.helm.toolkit.fluxcd.io - - persistentvolumeclaims - - configmaps - includeClusterResources: false - - spec: - includedNamespaces: - - '{{ .Application.metadata.namespace }}' - orLabelSelectors: - - matchLabels: - app.kubernetes.io/instance: 'vm-disk-{{ .Application.metadata.name }}' - - matchLabels: - apps.cozystack.io/application.kind: '{{ .Application.kind }}' - apps.cozystack.io/application.name: '{{ .Application.metadata.name }}' - includedResources: - - helmreleases.helm.toolkit.fluxcd.io - - persistentvolumeclaims - - configmaps - includeClusterResources: false - storageLocation: '{{ .Parameters.backupStorageLocationName }}' - volumeSnapshotLocations: - - '{{ .Parameters.backupStorageLocationName }}' - snapshotVolumes: true - snapshotMoveData: true - ttl: 720h0m0s - itemOperationTimeout: 24h0m0s -EOF - -log_success "VMDisk strategy created" - -separator - -log_step "Verifying strategies..." -log_command "kubectl get velero.strategy.backups.cozystack.io" -kubectl get velero.strategy.backups.cozystack.io - -separator - -log_success "Velero strategies are ready" -echo -e "\n${GREEN}${BOLD}Next step:${NC} ./02-create-backupclass.sh" diff --git a/examples/backups/vmi/02-create-backupclass.sh b/examples/backups/vmi/02-create-backupclass.sh deleted file mode 100755 index 08c29fc1..00000000 --- a/examples/backups/vmi/02-create-backupclass.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -# Step 02: Create BackupClass that binds strategies to application types -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/00-helpers.sh" - -print_header "Step 2: Create BackupClass" - -log_step "Creating BackupClass 'velero'..." -log_info "BackupClass maps application kinds (VMInstance, VMDisk) to their Velero strategies" -log_command "kubectl apply -f - (BackupClass: velero)" - -kubectl apply -f - < - external: false - externalMethod: PortList - externalPorts: - - 22 -EOF - -log_success "VMInstance created" - -separator - -log_step "Verifying VMInstance..." -log_command "kubectl get vminstance test -n $NAMESPACE" -kubectl get vminstance test -n "$NAMESPACE" - -separator - -log_success "VMInstance is ready" -echo -e "\n${GREEN}${BOLD}Next step:${NC} ./05-create-backupjob.sh" diff --git a/examples/backups/vmi/05-create-backupjob.sh b/examples/backups/vmi/05-create-backupjob.sh deleted file mode 100755 index 581490a4..00000000 --- a/examples/backups/vmi/05-create-backupjob.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# Step 05: Create a BackupJob to back up the VMInstance -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/00-helpers.sh" - -print_header "Step 5: Create BackupJob" - -log_step "Creating BackupJob 'test-backup' in namespace $NAMESPACE..." -log_info "This triggers a Velero backup of VMInstance 'test' and all its disks" -log_command "kubectl apply -f - (BackupJob: test-backup)" - -kubectl apply -f - <-orig-`, only for in-place restore - keepOriginalIpAndMac: true # restores original IP and MAC address of VMI via OVN annotations -EOF - -log_success "RestoreJob created" - -separator - -log_step "Waiting for RestoreJob to complete..." -wait_for_field restorejob restore-in-place-test '{.status.phase}' Succeeded "$NAMESPACE" 600 - -separator - -log_step "Verifying RestoreJob result..." -log_command "kubectl get restorejob restore-in-place-test -n $NAMESPACE -o yaml" -kubectl get restorejob restore-in-place-test -n "$NAMESPACE" -o wide - -separator - -log_success "In-place restore completed successfully" -echo -e "\n${GREEN}${BOLD}Next step:${NC} ./07-restore-to-copy.sh" diff --git a/examples/backups/vmi/07-restore-to-copy.sh b/examples/backups/vmi/07-restore-to-copy.sh deleted file mode 100755 index 9b84ce55..00000000 --- a/examples/backups/vmi/07-restore-to-copy.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -# Step 07: Restore the VMInstance to a copy in a different namespace -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/00-helpers.sh" - -TARGET_NAMESPACE="${TARGET_NAMESPACE:-tenant-root-copy}" - -print_header "Step 7: Restore VMInstance to Copy (Cross-Namespace)" - -log_info "Restoring to the same namespace with a different app name is not supported" -log_info "due to Velero DataUpload limitations. Cross-namespace restore uses Velero's namespaceMapping." - -separator - -log_step "Ensuring target namespace '$TARGET_NAMESPACE' exists..." -kubectl create namespace "$TARGET_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - -log_success "Namespace '$TARGET_NAMESPACE' is ready" - -separator - -log_step "Creating RestoreJob 'restore-to-copy-test' in namespace $NAMESPACE..." -log_info "The backup will be restored into namespace '$TARGET_NAMESPACE' using Velero namespaceMapping" -log_command "kubectl apply -f - (RestoreJob: restore-to-copy-test)" - -kubectl apply -f - <-orig-`, only for in-place restore - keepOriginalIpAndMac: false # restores original IP and MAC address of VMI via OVN annotations -EOF - -log_success "RestoreJob created" - -separator - -log_step "Waiting for RestoreJob to complete..." -wait_for_field restorejob restore-to-copy-test '{.status.phase}' Succeeded "$NAMESPACE" 600 - -separator - -log_step "Verifying RestoreJob result..." -log_command "kubectl get restorejob restore-to-copy-test -n $NAMESPACE -o yaml" -kubectl get restorejob restore-to-copy-test -n "$NAMESPACE" -o wide - -separator - -log_step "Checking resources in target namespace..." -log_command "kubectl get all -n $TARGET_NAMESPACE" -kubectl get all -n "$TARGET_NAMESPACE" 2>/dev/null || log_warning "No resources found in $TARGET_NAMESPACE" - -separator - -log_success "Cross-namespace restore completed successfully" diff --git a/examples/backups/vmi/cleanup.sh b/examples/backups/vmi/cleanup.sh deleted file mode 100755 index 5965c3f0..00000000 --- a/examples/backups/vmi/cleanup.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash -# Clean up all resources created by the demo -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/00-helpers.sh" - -TARGET_NAMESPACE="${TARGET_NAMESPACE:-tenant-root-copy}" - -print_header "Cleanup Demo Resources" - -log_warning "This script will delete all resources created during the demo" -echo -e "\n${YELLOW}The following will be deleted:${NC}" -echo " - RestoreJobs (restore-in-place-test, restore-to-copy-test)" -echo " - BackupJob (test-backup) and associated Backup" -echo " - VMInstance (test)" -echo " - VMDisk (ubuntu-source)" -echo " - BackupClass (velero)" -echo " - Velero strategies (vminstance-strategy, vmdisk-strategy)" -echo " - Target namespace ($TARGET_NAMESPACE)" -echo "" - -read -p "Continue? (y/N): " -n 1 -r -echo -if [[ ! $REPLY =~ ^[Yy]$ ]]; then - log_info "Cancelled" - exit 0 -fi - -separator - -log_step "Deleting RestoreJobs..." -kubectl delete restorejob restore-to-copy-test -n "$NAMESPACE" 2>/dev/null || log_warning "RestoreJob restore-to-copy-test not found" -kubectl delete restorejob restore-in-place-test -n "$NAMESPACE" 2>/dev/null || log_warning "RestoreJob restore-in-place-test not found" - -separator - -log_step "Deleting BackupJob and Backup..." -kubectl delete backupjob test-backup -n "$NAMESPACE" 2>/dev/null || log_warning "BackupJob test-backup not found" -kubectl delete backup test-backup -n "$NAMESPACE" 2>/dev/null || log_warning "Backup test-backup not found" - -separator - -log_step "Deleting VMInstance..." -kubectl delete vminstance test -n "$NAMESPACE" 2>/dev/null || log_warning "VMInstance test not found" - -log_step "Deleting VMDisk..." -kubectl delete vmdisk ubuntu-source -n "$NAMESPACE" 2>/dev/null || log_warning "VMDisk ubuntu-source not found" - -separator - -log_step "Deleting BackupClass..." -kubectl delete backupclass velero 2>/dev/null || log_warning "BackupClass velero not found" - -separator - -log_step "Deleting Velero strategies..." -kubectl delete velero.strategy.backups.cozystack.io vminstance-strategy 2>/dev/null || log_warning "Strategy vminstance-strategy not found" -kubectl delete velero.strategy.backups.cozystack.io vmdisk-strategy 2>/dev/null || log_warning "Strategy vmdisk-strategy not found" - -separator - -log_step "Deleting target namespace..." -kubectl delete namespace "$TARGET_NAMESPACE" 2>/dev/null || log_warning "Namespace $TARGET_NAMESPACE not found" - -separator - -log_success "Cleanup complete" -log_info "All demo resources have been deleted" -echo -e "\n${GREEN}${BOLD}To re-run the demo:${NC} ./01-create-strategies.sh" diff --git a/examples/backups/vmi/run-all.sh b/examples/backups/vmi/run-all.sh deleted file mode 100755 index b58f4b9d..00000000 --- a/examples/backups/vmi/run-all.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash -# Run the full VMInstance backup/restore demo sequentially -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/00-helpers.sh" - -print_header "VMInstance Backup & Restore Demo" - -log_info "This script will run all demo steps sequentially" -log_info "There will be a pause between steps for observation" -echo "" - -SCRIPTS=( - "01-create-strategies.sh" - "02-create-backupclass.sh" - "03-create-vmdisk.sh" - "04-create-vminstance.sh" - "05-create-backupjob.sh" - "06-restore-in-place.sh" - "07-restore-to-copy.sh" -) - -echo -e "${CYAN}Demo steps:${NC}" -for i in "${!SCRIPTS[@]}"; do - echo " $((i+1)). ${SCRIPTS[$i]}" -done -echo "" - -read -p "Run demo? (y/N): " -n 1 -r -echo -if [[ ! $REPLY =~ ^[Yy]$ ]]; then - log_info "Cancelled" - exit 0 -fi - -separator - -for script in "${SCRIPTS[@]}"; do - if [[ -x "$SCRIPT_DIR/$script" ]]; then - "$SCRIPT_DIR/$script" - separator - wait_for_enter - else - log_error "Script not found or not executable: $script" - exit 1 - fi -done - -print_header "Demo Complete" - -log_success "All steps completed successfully!" -echo "" -log_info "What was demonstrated:" -echo " 1. Created Velero backup strategies for VMInstance and VMDisk" -echo " 2. Created BackupClass binding strategies to application types" -echo " 3. Provisioned a VMDisk and VMInstance" -echo " 4. Created a backup of the VMInstance via BackupJob" -echo " 5. Restored the VMInstance in-place" -echo " 6. Restored the VMInstance to a copy in a different namespace" -echo "" -log_info "To clean up resources: ./cleanup.sh" diff --git a/examples/backups/vmi/scenario-admin-prepare.md b/examples/backups/vmi/scenario-admin-prepare.md deleted file mode 100644 index edfca5d1..00000000 --- a/examples/backups/vmi/scenario-admin-prepare.md +++ /dev/null @@ -1,73 +0,0 @@ -# Scenario: Cluster Administrator Configures Backups - -This scenario walks through the cluster-level setup required before users can -back up and restore their virtual machines. A cluster administrator creates -Velero strategies and a BackupClass that binds those strategies to Cozystack -application types. - -## Prerequisites - -- A running Cozystack cluster with the backup-controller installed. -- Velero deployed in the `cozy-velero` namespace with a configured - BackupStorageLocation (default: `default`). -- `kubectl` access with cluster-admin privileges. - -## Steps - -### 1. Create Velero Strategies - -```bash -./01-create-strategies.sh -``` - -This creates two cluster-scoped `Velero` strategy objects: - -| Strategy | Purpose | -|---|---| -| `vminstance-strategy` | Defines backup and restore templates for `VMInstance` applications. Includes VirtualMachine, PVCs, HelmReleases, pods (required by kubevirt-velero-plugin), and supporting resources. Uses `snapshotMoveData: true` for portable volume snapshots. | -| `vmdisk-strategy` | Defines backup and restore templates for standalone `VMDisk` applications. Covers HelmReleases, PVCs, and ConfigMaps. | - -Both strategies use Go templates with `{{ .Application.metadata.name }}`, -`{{ .Application.metadata.namespace }}`, and `{{ .Parameters.backupStorageLocationName }}` -so they can be reused across any application instance. - -**Key design details:** - -- `orLabelSelectors` scope backups to only the resources belonging to a - specific application, preventing cross-contamination between VMs in the - same namespace. -- The restore spec excludes `datavolumes.cdi.kubevirt.io` to avoid conflicts - when the HelmRelease of VMDisk recreates DataVolumes after restore. -- `existingResourcePolicy: update` allows restoring over existing resources - during in-place restore. - -### 2. Create BackupClass - -```bash -./02-create-backupclass.sh -``` - -Creates a `BackupClass` named `velero` that maps application types to their -strategies: - -| Application Kind | Strategy | Parameters | -|---|---|---| -| `VMInstance` (`apps.cozystack.io`) | `vminstance-strategy` | `backupStorageLocationName: default` | -| `VMDisk` (`apps.cozystack.io`) | `vmdisk-strategy` | `backupStorageLocationName: default` | - -The `backupStorageLocationName` parameter can be overridden via the -`BACKUP_STORAGE_LOCATION` environment variable if your Velero installation -uses a non-default storage location. - -## Configuration - -| Variable | Default | Description | -|---|---|---| -| `BACKUP_STORAGE_LOCATION` | `default` | Velero BackupStorageLocation name | - -## Result - -After completing these steps the cluster is ready for users to create backups -of their `VMInstance` and `VMDisk` applications by referencing the `velero` -BackupClass. No further admin action is required for individual backup or -restore operations. diff --git a/examples/backups/vmi/scenario-user-backup.md b/examples/backups/vmi/scenario-user-backup.md deleted file mode 100644 index 31241fd9..00000000 --- a/examples/backups/vmi/scenario-user-backup.md +++ /dev/null @@ -1,91 +0,0 @@ -# Scenario: User Creates a VM Backup - -This scenario demonstrates how a tenant user provisions a virtual machine and -creates a backup of it. The backup captures the VM definition, its disks, and -network identity so it can be restored later. - -## Prerequisites - -- Cluster administrator has completed the setup from - [scenario-admin.md](scenario-admin.md) (strategies and BackupClass exist). -- A tenant namespace (default: `tenant-root`). -- `kubectl` access scoped to the tenant namespace. - -## Steps - -### 1. Create a VMDisk - -```bash -./03-create-vmdisk.sh -``` - -Creates a `VMDisk` named `ubuntu-source` that downloads the Ubuntu Noble cloud -image and provisions a 20Gi replicated PVC. The disk serves as the boot volume -for the virtual machine. - -Wait for the image download to complete before proceeding. You can monitor -progress with: - -```bash -kubectl get vmdisk ubuntu-source -n tenant-root -w -``` - -### 2. Create a VMInstance - -```bash -./04-create-vminstance.sh -``` - -Creates a `VMInstance` named `test` that references the `ubuntu-source` disk. -The VM boots with the `ubuntu` instance profile on a `u1.medium` instance type. - -Verify the VM is running: - -```bash -kubectl get vmi -n tenant-root -``` - -### 3. Create a BackupJob - -```bash -./05-create-backupjob.sh -``` - -Creates a `BackupJob` named `test-backup` that triggers a full backup of the -`test` VMInstance. The backup controller: - -1. Resolves the `velero` BackupClass to find the matching `vminstance-strategy`. -2. Discovers underlying resources (DataVolumes, OVN IP/MAC from the VM pod). -3. Creates a Velero Backup in the `cozy-velero` namespace with label selectors - scoped to this specific VM and its disks. -4. Velero snapshots and moves the volume data to the configured storage - location. - -The script waits up to 10 minutes for the BackupJob to reach the `Succeeded` -phase. On completion, a `Backup` object is created in the same namespace -containing: - -- `spec.applicationRef` — reference to the backed-up VMInstance. -- `spec.strategyRef` — reference to the Velero strategy used. -- `spec.driverMetadata` — Velero backup name for later restore. -- `status.underlyingResources` — captured DataVolume names and OVN IP/MAC - addresses. - -You can inspect the resulting Backup: - -```bash -kubectl get backups -n tenant-root -kubectl get backup test-backup -n tenant-root -o yaml -``` - -## Configuration - -| Variable | Default | Description | -|---|---|---| -| `NAMESPACE` | `tenant-root` | Tenant namespace for all resources | - -## Result - -After completing these steps you have a `Backup` artifact that can be used to -restore the VM either in-place or to a different namespace. See -[scenario-user-restore.md](scenario-user-restore.md) for restore options. diff --git a/examples/backups/vmi/scenario-user-restore.md b/examples/backups/vmi/scenario-user-restore.md deleted file mode 100644 index 1d35b22b..00000000 --- a/examples/backups/vmi/scenario-user-restore.md +++ /dev/null @@ -1,101 +0,0 @@ -# Scenario: User Restores a VM - -This scenario demonstrates two restore methods: in-place restore (rollback the -VM to a previous state) and cross-namespace restore (create a copy of the VM in -a different namespace). - -## Prerequisites - -- A completed backup from [scenario-user-backup.md](scenario-user-backup.md) - (the `test-backup` Backup object exists in the tenant namespace). -- `kubectl` access scoped to the tenant namespace. - -## Method 1: In-Place Restore - -```bash -./06-restore-in-place.sh -``` - -Creates a `RestoreJob` that restores the `test` VMInstance back to the state -captured in the `test-backup` Backup. The `targetApplicationRef` points to the -same application as the original backup. - -The backup controller performs the following steps automatically: - -1. **Suspends HelmReleases** — prevents Flux from reconciling the VM and its - disks during restore. -2. **Halts the VirtualMachine** — sets `runStrategy: Halted` and waits for the - VirtualMachineInstance (launcher pod) to terminate. -3. **Renames existing PVCs** — moves each PVC to `-orig-` to - preserve the current disk data as a safety net. -4. **Deletes DataVolumes** — removes DVs so CDI does not recreate PVCs before - Velero restores them. -5. **Creates Velero Restore** — restores resources from the backup with: - - `existingResourcePolicy: update` to overwrite existing objects. - - Resource modifier rules that add `cdi.kubevirt.io/allowClaimAdoption=true` - to restored PVCs so CDI can adopt them. - - OVN IP/MAC annotations to preserve the VM's network identity. - -After the Velero Restore completes, the HelmReleases resume and the VM boots -with the restored disk data while retaining its original IP and MAC addresses. - -## Method 2: Cross-Namespace Restore (Copy) - -```bash -./07-restore-to-copy.sh -``` - -Creates a `RestoreJob` with `spec.options.targetNamespace` set to a different namespace -(default: `tenant-root-copy`). This creates an independent copy of the VM -without affecting the original. - -Key differences from in-place restore: - -| Aspect | In-Place | Cross-Namespace | -|---|---|---| -| Source VM affected | Yes (halted, PVCs renamed) | No (untouched) | -| Velero namespaceMapping | Not used | Maps source NS to target NS | -| OVN IP/MAC | Preserved from backup | Skipped (new IP/MAC assigned) | -| Pre-restore preparation | Full (suspend, halt, rename, delete) | Skipped | - -The script ensures the target namespace exists before creating the RestoreJob. -Velero's `namespaceMapping` redirects all resources from the source namespace to -the target namespace during restore. - -### Important limitation - -Restoring to the **same namespace** with a **different application name** is not -supported. Velero's DataUpload always writes volume data to PVCs with the -original name regardless of resource modifiers, which causes conflicts. If you -attempt this, the RestoreJob will fail with an error message suggesting -cross-namespace restore instead. - -## Configuration - -| Variable | Default | Description | -|---|---|---| -| `NAMESPACE` | `tenant-root` | Source namespace (where the Backup lives) | -| `TARGET_NAMESPACE` | `tenant-root-copy` | Target namespace for cross-namespace restore | - -## Verify - -After either restore method, verify the VM is running: - -```bash -# In-place -kubectl get vmi -n tenant-root - -# Cross-namespace copy -kubectl get vmi -n tenant-root-copy -``` - -## Cleanup - -To remove all resources created by the demo: - -```bash -./cleanup.sh -``` - -This deletes RestoreJobs, BackupJobs, Backups, VMInstance, VMDisk, BackupClass, -strategies, and the target namespace. diff --git a/examples/desired-backup.yaml b/examples/desired-backup.yaml new file mode 100644 index 00000000..c06b8f82 --- /dev/null +++ b/examples/desired-backup.yaml @@ -0,0 +1,20 @@ +apiVersion: backups.cozystack.io/v1alpha1 +kind: BackupJob +metadata: + name: desired-backup + namespace: tenant-root + labels: + backups.cozystack.io/triggered-by: manual +spec: + applicationRef: + apiGroup: apps.cozystack.io + kind: VirtualMachine + name: vm1 + storageRef: + apiGroup: apps.cozystack.io + kind: Bucket + name: test-bucket + strategyRef: + apiGroup: strategy.backups.cozystack.io + kind: Velero + name: velero-strategy-default \ No newline at end of file diff --git a/go.mod b/go.mod index 7b7d5bc4..9944df16 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ module github.com/cozystack/cozystack go 1.25.0 require ( - github.com/cozystack/cozystack-scheduler/pkg/apis v0.1.1 github.com/emicklei/dot v1.10.0 github.com/fluxcd/helm-controller/api v1.4.3 github.com/fluxcd/source-controller/api v1.7.4 @@ -29,10 +28,8 @@ require ( k8s.io/klog/v2 v2.130.1 k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d - sigs.k8s.io/container-object-storage-interface-api v0.1.0 sigs.k8s.io/controller-runtime v0.22.4 - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 - sigs.k8s.io/yaml v1.6.0 + sigs.k8s.io/structured-merge-diff/v4 v4.7.0 ) require ( @@ -47,6 +44,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fluxcd/pkg/apis/acl v0.9.0 // indirect @@ -127,6 +125,8 @@ require ( sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) // See: issues.k8s.io/135537 diff --git a/go.sum b/go.sum index 81e1779f..d2cbc779 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,6 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cozystack/apimachinery v0.0.0-20251219010959-1f91eabae46c h1:C2wIfH/OzhU9XOK/e6Ik9cg7nZ1z6fN4lf6a3yFdik8= github.com/cozystack/apimachinery v0.0.0-20251219010959-1f91eabae46c/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -github.com/cozystack/cozystack-scheduler/pkg/apis v0.1.1 h1:9uLa/8J4lRx3sNuaVH8UZqgZvnskHATPo5GxEKh0iSM= -github.com/cozystack/cozystack-scheduler/pkg/apis v0.1.1/go.mod h1:kPeS9YPB4ENbvNINEkkp0SX8FB+gvwoOHGOHMT3Tg9Y= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -83,6 +81,7 @@ github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -321,15 +320,17 @@ k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPG k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/container-object-storage-interface-api v0.1.0 h1:8tB6JFQhbQIC1hwGQ+q4+tmSSNfjKemb7bFI6C0CK/4= -sigs.k8s.io/container-object-storage-interface-api v0.1.0/go.mod h1:YiB+i/UGkzqgODDhRG3u7jkbWkQcoUeLEJ7hwOT/2Qk= sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A= sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/admin-kubeconfig-invariant.bats b/hack/admin-kubeconfig-invariant.bats deleted file mode 100644 index a4b98b00..00000000 --- a/hack/admin-kubeconfig-invariant.bats +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env bats -# ----------------------------------------------------------------------------- -# Chart-wide invariant for packages/apps/kubernetes: -# -# Every Deployment in this chart that mounts -admin-kubeconfig as a -# Secret volume MUST: -# - declare that volume optional: true (so kubelet does not FailedMount -# while Kamaji is still provisioning the Secret), AND -# - include the wait-for-kubeconfig init container (so the pod becomes -# Ready only after Kamaji publishes the Secret). -# -# The per-template unittests in packages/apps/kubernetes/tests/ lock in -# today's three Deployments (cluster-autoscaler, kccm, csi controller) by -# name. This invariant is stricter: any future Deployment added to this -# chart that mounts the same Secret but forgets the guard will fail here. -# -# Requires: helm, yq (mikefarah v4+), jq. All three are available on the -# project's CI runners and on the maintainer workstation. -# ----------------------------------------------------------------------------- - -@test "every Deployment mounting admin-kubeconfig has optional:true and wait-for-kubeconfig init" { - values_file="packages/apps/kubernetes/tests/values-ci.yaml" - [ -f "$values_file" ] - - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - helm template invariant packages/apps/kubernetes \ - --namespace tenant-root \ - --values "$values_file" \ - 2>/dev/null > "$tmp/rendered.yaml" - - # yq streams one JSON object per input document. jq -s slurps the stream - # into an array so we can treat all Deployments as a single collection. - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s --raw-output ' - map(select(.kind == "Deployment")) | - map({ - name: .metadata.name, - volumes: (.spec.template.spec.volumes // []), - initNames: ((.spec.template.spec.initContainers // []) | map(.name)), - }) | - map( - .name as $n | - .initNames as $ins | - (.volumes[] | select(.secret.secretName | test("-admin-kubeconfig$")?)) - | { - name: $n, - optional: (.secret.optional == true), - hasInit: ($ins | index("wait-for-kubeconfig") != null), - } - ) - ' > "$tmp/summary.json" - - # At least one Deployment must match; if a refactor removes every - # admin-kubeconfig volume from this chart, the test must be updated - # deliberately rather than silently passing. - matched=$(jq 'length' "$tmp/summary.json") - [ "$matched" -ge 1 ] - - offenders=$(jq --raw-output '.[] | select(.optional != true or .hasInit != true) | .name' "$tmp/summary.json") - - if [ -n "$offenders" ]; then - echo "Deployments mounting *-admin-kubeconfig without optional:true + wait-for-kubeconfig init:" >&2 - echo "$offenders" >&2 - echo "Full summary:" >&2 - cat "$tmp/summary.json" >&2 - exit 1 - fi - - echo "Invariant holds for $matched Deployment(s)" -} - -@test "chart emits zero admin-kubeconfig Deployments when tenant has no etcd DataStore" { - # Without a DataStore (parent Tenant has not populated _namespace.etcd yet) - # the control-plane-side Deployments must NOT render at all. If they did, - # the wait-for-kubeconfig init would CrashLoopBackOff indefinitely - there - # would be no KamajiControlPlane to provision the Secret - consuming the - # HelmRelease wait budget and triggering exactly the remediation cycle the - # rest of this chart tries to avoid. This test renders the whole chart - # with etcd empty and asserts no Deployment references the admin-kubeconfig - # Secret. - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - helm template invariant packages/apps/kubernetes \ - --namespace tenant-root \ - --values packages/apps/kubernetes/tests/values-ci-no-etcd.yaml \ - 2>/dev/null > "$tmp/rendered.yaml" - - matched=$( - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s ' - map(select(.kind == "Deployment")) | - map(select( - (.spec.template.spec.volumes // []) - | any(.secret.secretName | test("-admin-kubeconfig$")?) - )) | - length - ' - ) - - if [ "$matched" -ne 0 ]; then - echo "Expected zero Deployments mounting *-admin-kubeconfig when etcd is empty, got $matched:" >&2 - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s 'map(select(.kind == "Deployment") | .metadata.name)' >&2 - exit 1 - fi - - echo "No admin-kubeconfig Deployments rendered for empty etcd (as expected)" -} - -@test "chart emits zero admin-kubeconfig HelmReleases when tenant has no etcd DataStore" { - # Same principle as the Deployment variant above, extended to every child - # HelmRelease (cilium, coredns, csi, cert-manager, ...). They reference - # *-admin-kubeconfig via kubeConfig.secretRef and would otherwise sit in - # NotReady forever on an etcd-less tenant, polluting the HelmRelease list - # the operator sees and contradicting the "awaiting-etcd beacon only" - # contract of the soft-skip path. - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - helm template invariant packages/apps/kubernetes \ - --namespace tenant-root \ - --values packages/apps/kubernetes/tests/values-ci-no-etcd.yaml \ - 2>/dev/null > "$tmp/rendered.yaml" - - matched=$( - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s ' - map(select(.kind == "HelmRelease")) | - map(select(.spec.kubeConfig.secretRef.name | test("-admin-kubeconfig$")?)) | - length - ' - ) - - if [ "$matched" -ne 0 ]; then - echo "Expected zero HelmReleases referencing *-admin-kubeconfig when etcd is empty, got $matched:" >&2 - yq --output-format=json eval-all '.' "$tmp/rendered.yaml" \ - | jq -s 'map(select(.kind == "HelmRelease") | .metadata.name)' >&2 - exit 1 - fi - - echo "No admin-kubeconfig HelmReleases rendered for empty etcd (as expected)" -} diff --git a/hack/cdi_golden_image_create.sh b/hack/cdi_golden_image_create.sh index f19f9970..be1558d0 100644 --- a/hack/cdi_golden_image_create.sh +++ b/hack/cdi_golden_image_create.sh @@ -16,7 +16,7 @@ kubectl create -f - <:(:)+ -# where each is [a-z0-9_]. Raw DCGM metrics (DCGM_FI_*), -# kube-state-metrics (kube_*) and similar uppercase / single-word metric -# names do not match because the leading segment must be lowercase and the -# whole expression must contain at least two ':' characters. -extract_refs() { - json_file=$1 - # Prometheus convention allows 2-segment rule names (level:metric); this - # regex is tuned to the 3+ segment convention used in this repo - # (level:metric:op — e.g. cluster:gpu_count:total). Update if future - # rules use 2 segments, otherwise they will be silently skipped. - grep -hoE '[a-z][a-z0-9_]*:[a-z0-9_]+:[a-z0-9_]+' "$json_file" | sort -u -} - -# Resolve "gpu/foo" -> "$DASHBOARDS_DIR/gpu/foo.json" -list_tracked_gpu_dashboards() { - awk '/^gpu\// { print $0 ".json" }' "$DASHBOARDS_LIST" -} - -# Extract the set of DCGM_FI_* metric names declared in a CSV file. Handles -# both the upstream-style default CSV (unindented) and the ConfigMap-style -# custom CSV (YAML-indented). A declaration line starts — after any leading -# whitespace — with "DCGM_FI_," ; comment lines begin with "#" and are -# skipped. Uses POSIX awk's match()+RSTART/RLENGTH so no GNU extensions -# are required. -extract_csv_metrics() { - file=$1 - awk ' - { - line = $0 - sub(/^[[:space:]]+/, "", line) - if (line ~ /^#/) next - if (match(line, /^DCGM_FI_[A-Z0-9_]+/)) { - print substr(line, RSTART, RLENGTH) - } - } - ' "$file" | sort -u -} - -# Extract the set of DCGM_FI_* metric references from a text file (dashboard -# JSON or rules YAML). A DCGM metric name has at least two underscore-delimited -# segments after the "DCGM_FI_" prefix (e.g. DCGM_FI_DEV_GPU_UTIL, DCGM_FI_PROF_ -# PIPE_TENSOR_ACTIVE, DCGM_FI_DRIVER_VERSION). Requiring two segments keeps -# the matcher from latching onto glob stubs like "DCGM_FI_DEV_*_VIOLATION" that -# appear in comments. -extract_dcgm_refs() { - file=$1 - grep -hoE 'DCGM_FI_[A-Z0-9]+(_[A-Z0-9]+)+' "$file" | sort -u -} - -@test "every recording rule reference in tracked GPU dashboards has a matching record" { - TMP=$(mktemp -d) - trap 'rm -rf "$TMP"' EXIT - - extract_rules > "$TMP/rules.txt" - [ -s "$TMP/rules.txt" ] || { echo "no recording rules extracted from $RULES_FILE" >&2; exit 1; } - - list_tracked_gpu_dashboards > "$TMP/dashboards.txt" - [ -s "$TMP/dashboards.txt" ] || { echo "no gpu/* dashboards listed in $DASHBOARDS_LIST" >&2; exit 1; } - - failed=0 - while IFS= read -r dashboard_rel; do - dashboard="$DASHBOARDS_DIR/$dashboard_rel" - if [ ! -f "$dashboard" ]; then - echo "ERROR: dashboard listed but file missing: $dashboard" >&2 - failed=1 - continue - fi - - extract_refs "$dashboard" > "$TMP/refs.txt" - # comm -23: lines unique to refs.txt (referenced but not defined) - # Both inputs must be sorted; extract_* helpers already sort. - comm -23 "$TMP/refs.txt" "$TMP/rules.txt" > "$TMP/missing.txt" - if [ -s "$TMP/missing.txt" ]; then - echo "ERROR: $dashboard_rel references undefined recording rules:" >&2 - sed 's/^/ - /' "$TMP/missing.txt" >&2 - failed=1 - fi - done < "$TMP/dashboards.txt" - - [ "$failed" -eq 0 ] -} - -@test "every DCGM metric referenced in tracked dashboards and rules is declared" { - TMP=$(mktemp -d) - trap 'rm -rf "$TMP"' EXIT - - [ -f "$DCGM_DEFAULT_CSV" ] || { echo "missing $DCGM_DEFAULT_CSV" >&2; exit 1; } - [ -f "$DCGM_CUSTOM_CSV" ] || { echo "missing $DCGM_CUSTOM_CSV" >&2; exit 1; } - - { - extract_csv_metrics "$DCGM_DEFAULT_CSV" - extract_csv_metrics "$DCGM_CUSTOM_CSV" - } | sort -u > "$TMP/declared.txt" - [ -s "$TMP/declared.txt" ] || { echo "no DCGM metrics extracted from CSVs" >&2; exit 1; } - - list_tracked_gpu_dashboards > "$TMP/dashboards.txt" - [ -s "$TMP/dashboards.txt" ] || { echo "no gpu/* dashboards listed in $DASHBOARDS_LIST" >&2; exit 1; } - - failed=0 - - # Dashboard coverage — every dashboard's DCGM references must resolve. - while IFS= read -r dashboard_rel; do - dashboard="$DASHBOARDS_DIR/$dashboard_rel" - [ -f "$dashboard" ] || continue # handled by the existence test - extract_dcgm_refs "$dashboard" > "$TMP/refs.txt" - [ -s "$TMP/refs.txt" ] || continue # dashboard relies entirely on recording rules - comm -23 "$TMP/refs.txt" "$TMP/declared.txt" > "$TMP/missing.txt" - if [ -s "$TMP/missing.txt" ]; then - echo "ERROR: $dashboard_rel references DCGM metrics not declared in any CSV:" >&2 - sed 's/^/ - /' "$TMP/missing.txt" >&2 - failed=1 - fi - done < "$TMP/dashboards.txt" - - # Rules coverage — recording rules consume DCGM directly, so their set - # must be declared too, otherwise derived series on every dashboard - # collapse to empty. - extract_dcgm_refs "$RULES_FILE" > "$TMP/rule-refs.txt" - if [ -s "$TMP/rule-refs.txt" ]; then - comm -23 "$TMP/rule-refs.txt" "$TMP/declared.txt" > "$TMP/rule-missing.txt" - if [ -s "$TMP/rule-missing.txt" ]; then - echo "ERROR: gpu-recording.rules.yaml references DCGM metrics not declared in any CSV:" >&2 - sed 's/^/ - /' "$TMP/rule-missing.txt" >&2 - failed=1 - fi - fi - - [ "$failed" -eq 0 ] -} - -@test "every tracked GPU dashboard listed in dashboards-infra.list exists on disk" { - TMP=$(mktemp -d) - trap 'rm -rf "$TMP"' EXIT - - list_tracked_gpu_dashboards > "$TMP/dashboards.txt" - [ -s "$TMP/dashboards.txt" ] || { echo "no gpu/* dashboards listed in $DASHBOARDS_LIST" >&2; exit 1; } - - failed=0 - while IFS= read -r dashboard_rel; do - dashboard="$DASHBOARDS_DIR/$dashboard_rel" - if [ ! -f "$dashboard" ]; then - echo "ERROR: $dashboard_rel listed in dashboards-infra.list but $dashboard does not exist" >&2 - failed=1 - fi - done < "$TMP/dashboards.txt" - - [ "$failed" -eq 0 ] -} diff --git a/hack/check-host-runtime.bats b/hack/check-host-runtime.bats deleted file mode 100644 index b121b31b..00000000 --- a/hack/check-host-runtime.bats +++ /dev/null @@ -1,415 +0,0 @@ -#!/usr/bin/env bats -# ----------------------------------------------------------------------------- -# Unit tests for hack/check-host-runtime.sh -# -# The script warns when a standalone containerd.service or docker.service is -# active alongside the embedded k3s runtime on Ubuntu hosts running the -# cozystack "generic" variant. Warnings go to stderr; exit code is always 0. -# -# Test strategy: each test builds its own temporary stub directory and prepends -# it to PATH to inject a fake `systemctl` (and optionally `du`) binary. The -# script itself honors a small set of COZYSTACK_PREFLIGHT_* environment -# variables to redirect socket/dir probes into the stub tree, so tests do not -# need root privileges or a real systemd host. -# -# Each test installs a `trap 'rm -rf "$STUB_DIR"' EXIT` immediately after -# creating the stub dir so cleanup runs even when an assertion fails mid-test -# under `set -e`. cozytest.sh runs each @test in its own subshell, so traps -# scope per test and do not leak across tests. -# -# Tests are otherwise self-contained — no shared setup/teardown helpers, -# because cozytest.sh's awk parser only recognizes @test blocks and treats a -# bare `}` on its own line as the end of a test function. -# -# Title syntax constraints (inherited from cozytest.sh's awk parser): -# - Titles must be delimited by ASCII double quotes; embedded literal -# double quotes are NOT escaped and will silently truncate the title. -# - Only alphanumeric characters from the title survive into the shell -# function name (everything else becomes '_'), so titles that differ -# only in punctuation collapse to the same function name. Keep titles -# distinctive in their alphanumeric run. -# -# Run with: hack/cozytest.sh hack/check-host-runtime.bats -# (or `bats hack/check-host-runtime.bats` if the bats binary is -# installed; cozytest.sh is the CI path.) -# ----------------------------------------------------------------------------- - -@test "clean host with no runtime services exits silently" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker1.sock $STUB_DIR/missing-docker2.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/missing-containerd-dir" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh >"$STUB_DIR/stdout" 2>"$STDERR_FILE" - - [ ! -s "$STDERR_FILE" ] - [ ! -s "$STUB_DIR/stdout" ] -} - -@test "standalone containerd service active prints warning" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -if [ "$1" = "is-active" ] && [ "$2" = "containerd.service" ]; then - echo active - exit 0 -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - - mkdir -p "$STUB_DIR/var-lib-containerd" - echo dummy >"$STUB_DIR/var-lib-containerd/dummy" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/var-lib-containerd" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - grep -q 'standalone containerd.service' "$STDERR_FILE" - if grep -q 'standalone docker.service' "$STDERR_FILE"; then - echo "unexpected docker warning found:" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi - # HINT line must name only the detected service, not advise disabling - # docker.service when only containerd.service is running. The sudo - # prefix is also required — without it the command silently no-ops - # for a non-root operator, so the prefix is part of the contract. - grep -q 'sudo systemctl disable --now containerd.service' "$STDERR_FILE" - if grep -q 'systemctl disable --now.*docker' "$STDERR_FILE"; then - echo "HINT unexpectedly mentions docker:" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi -} - -@test "standalone docker service active prints warning" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -if [ "$1" = "is-active" ] && [ "$2" = "docker.service" ]; then - echo active - exit 0 -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - - mkdir -p "$STUB_DIR/var-lib-docker" - echo dummy >"$STUB_DIR/var-lib-docker/dummy" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/missing-containerd-dir" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/var-lib-docker" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - grep -q 'standalone docker.service' "$STDERR_FILE" - if grep -q 'standalone containerd.service' "$STDERR_FILE"; then - echo "unexpected containerd warning found:" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi - # HINT line must name only the detected service. As in the - # containerd test, the sudo prefix is part of the contract. - grep -q 'sudo systemctl disable --now docker.service' "$STDERR_FILE" - if grep -q 'systemctl disable --now.*containerd' "$STDERR_FILE"; then - echo "HINT unexpectedly mentions containerd:" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi -} - -@test "both services active prints two warnings and the HINT block" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -if [ "$1" = "is-active" ]; then - case "$2" in - containerd.service|docker.service) echo active; exit 0 ;; - esac -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - - mkdir -p "$STUB_DIR/var-lib-containerd" "$STUB_DIR/var-lib-docker" - - STDERR_FILE="$STUB_DIR/stderr" - # Capture exit code explicitly: the script contract says exit 0 - # unconditionally (warning, not blocker). `set -e` in the test - # function body would already fail on a nonzero exit, but an - # explicit status check locks in the contract and makes a - # regression show up as "expected 0, got N" rather than as a - # generic test failure. - status=0 - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/var-lib-containerd" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/var-lib-docker" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" || status=$? - - [ "$status" -eq 0 ] - grep -q 'standalone containerd.service' "$STDERR_FILE" - grep -q 'standalone docker.service' "$STDERR_FILE" - # HINT block must fire whenever warnings exist; otherwise a future silent - # removal of the HINT would go unnoticed. When both services fire the HINT - # must list both in a single sudo systemctl disable invocation — the sudo - # prefix is as important as the systemctl verb, otherwise the operator - # would be told to run it as a non-root user and quietly fail. - grep -q 'HINT:' "$STDERR_FILE" - grep -q 'sudo systemctl disable --now containerd.service docker.service' "$STDERR_FILE" -} - -@test "failing du does not suppress the containerd warning" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -if [ "$1" = "is-active" ] && [ "$2" = "containerd.service" ]; then - echo active - exit 0 -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - cat >"$STUB_DIR/du" <<'DUEOF' -#!/bin/sh -exit 1 -DUEOF - chmod +x "$STUB_DIR/du" - - mkdir -p "$STUB_DIR/var-lib-containerd" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/var-lib-containerd" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - grep -q 'standalone containerd.service' "$STDERR_FILE" -} - -@test "containerd socket fallback fires when systemctl is unavailable" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - # The script uses `[ -e "$sock" ]`, not `[ -S ... ]`, so a regular - # file is a valid stand-in for a unix socket in tests. This also - # removes any optional runtime dependency on python3 and makes the - # test unconditional on every CI runner. - SOCK="$STUB_DIR/containerd.sock" - touch "$SOCK" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_PREFLIGHT_FORCE_NO_SYSTEMCTL=1 \ - COZYSTACK_CONTAINERD_SOCKET="$SOCK" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/missing-containerd-dir" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - grep -q 'standalone containerd.service' "$STDERR_FILE" -} - -@test "docker socket fallback fires when systemctl is unavailable" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - SOCK="$STUB_DIR/docker.sock" - touch "$SOCK" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_PREFLIGHT_FORCE_NO_SYSTEMCTL=1 \ - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$SOCK" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/missing-containerd-dir" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - grep -q 'standalone docker.service' "$STDERR_FILE" - if grep -q 'standalone containerd.service' "$STDERR_FILE"; then - echo "unexpected containerd warning found:" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi -} - -@test "clean host without systemctl exits silently" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_PREFLIGHT_FORCE_NO_SYSTEMCTL=1 \ - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker1.sock $STUB_DIR/missing-docker2.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/missing-containerd-dir" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - bash hack/check-host-runtime.sh >"$STUB_DIR/stdout" 2>"$STDERR_FILE" - - [ ! -s "$STDERR_FILE" ] - [ ! -s "$STUB_DIR/stdout" ] -} - -@test "docker service plus socket still emits exactly one warning" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -if [ "$1" = "is-active" ] && [ "$2" = "docker.service" ]; then - echo active - exit 0 -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - - SOCK="$STUB_DIR/docker.sock" - touch "$SOCK" - - mkdir -p "$STUB_DIR/var-lib-docker" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$SOCK" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/missing-containerd-dir" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/var-lib-docker" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - count=$(grep -c 'standalone docker.service' "$STDERR_FILE") - if [ "$count" != "1" ]; then - echo "expected exactly one docker warning, got $count" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi -} - -@test "docker socket paths with glob chars do not expand" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - # Create two directories that a naive `for sock in $PATHS` loop - # would glob-expand and treat as existing "sockets". With the - # array-based parsing the literal path "$STUB_DIR/var-lib-*" does - # not exist and no warning must fire. - mkdir -p "$STUB_DIR/var-lib-docker" "$STUB_DIR/var-lib-containerd" - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_CONTAINERD_SOCKET="$STUB_DIR/missing-containerd.sock" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/var-lib-*" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/missing-containerd-dir" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - if grep -q 'standalone docker.service' "$STDERR_FILE"; then - echo "glob pattern expanded — docker warning should not fire:" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi -} - -@test "containerd service plus socket still emits exactly one warning" { - STUB_DIR=$(mktemp -d) - trap 'rm -rf "$STUB_DIR"' EXIT - - cat >"$STUB_DIR/systemctl" <<'STUBEOF' -#!/bin/sh -if [ "$1" = "--version" ]; then - echo "systemd stub" - exit 0 -fi -if [ "$1" = "is-active" ] && [ "$2" = "containerd.service" ]; then - echo active - exit 0 -fi -exit 1 -STUBEOF - chmod +x "$STUB_DIR/systemctl" - - # The script uses `[ -e "$sock" ]`, not `[ -S ... ]`, so a regular - # file is a valid stand-in for a unix socket in tests. This also - # removes any optional runtime dependency on python3 and makes the - # test unconditional on every CI runner. - SOCK="$STUB_DIR/containerd.sock" - touch "$SOCK" - - mkdir -p "$STUB_DIR/var-lib-containerd" - - STDERR_FILE="$STUB_DIR/stderr" - COZYSTACK_CONTAINERD_SOCKET="$SOCK" \ - COZYSTACK_DOCKER_SOCKET_PATHS="$STUB_DIR/missing-docker.sock" \ - COZYSTACK_CONTAINERD_DIR="$STUB_DIR/var-lib-containerd" \ - COZYSTACK_DOCKER_DIR="$STUB_DIR/missing-docker-dir" \ - PATH="$STUB_DIR:$PATH" \ - bash hack/check-host-runtime.sh 2>"$STDERR_FILE" - - count=$(grep -c 'standalone containerd.service' "$STDERR_FILE") - if [ "$count" != "1" ]; then - echo "expected exactly one containerd warning, got $count" >&2 - cat "$STDERR_FILE" >&2 - exit 1 - fi -} diff --git a/hack/check-host-runtime.sh b/hack/check-host-runtime.sh deleted file mode 100755 index 917453d2..00000000 --- a/hack/check-host-runtime.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env bash -# ----------------------------------------------------------------------------- -# check-host-runtime.sh — operator preflight warning -# -# Purpose: -# Warn when a standalone containerd.service or docker.service is running on -# the host alongside the embedded k3s runtime. This mismatch is silent on -# day 0 (k3s uses its own containerd at /run/k3s/containerd/containerd.sock -# and /var/lib/rancher/k3s/agent/containerd) but over time the standalone -# runtime accumulates unpruned images and build cache in /var/lib/containerd -# — enough to trigger DiskPressure and crash cozystack-api with eviction -# loops. The script does NOT block install; it only prints a warning. -# -# When to run: -# Before `helm install cozy-installer` on an Ubuntu host prepared with k3s -# or kubeadm (cozystack "generic" variant). Irrelevant on Talos where the -# container runtime lifecycle is fully managed. Discoverable via -# `make preflight` from the repository root. -# -# Exit code: -# Always 0 (warning, not a blocker). Warnings go to stderr. -# -# Environment variables (test hooks — override default probe paths): -# COZYSTACK_CONTAINERD_SOCKET standalone containerd socket path -# COZYSTACK_DOCKER_SOCKET_PATHS space-separated list of docker socket paths -# COZYSTACK_CONTAINERD_DIR standalone containerd data directory -# COZYSTACK_DOCKER_DIR standalone docker data directory -# COZYSTACK_PREFLIGHT_FORCE_NO_SYSTEMCTL=1 pretend systemctl is absent -# ----------------------------------------------------------------------------- -set -euo pipefail - -if [ -t 2 ]; then - YELLOW=$'\033[1;33m' - RESET=$'\033[0m' -else - YELLOW='' - RESET='' -fi - -CONTAINERD_SOCKET=${COZYSTACK_CONTAINERD_SOCKET:-/run/containerd/containerd.sock} -DOCKER_SOCKET_PATHS=${COZYSTACK_DOCKER_SOCKET_PATHS:-/run/docker.sock /var/run/docker.sock} -CONTAINERD_DIR=${COZYSTACK_CONTAINERD_DIR:-/var/lib/containerd} -DOCKER_DIR=${COZYSTACK_DOCKER_DIR:-/var/lib/docker} - -CONTAINERD_WARN=0 -DOCKER_WARN=0 - -warn() { - printf '%sWARNING:%s %s\n' "$YELLOW" "$RESET" "$1" >&2 -} - -detect_systemctl() { - if [ "${COZYSTACK_PREFLIGHT_FORCE_NO_SYSTEMCTL:-0}" = "1" ]; then - return 1 - fi - if command -v systemctl >/dev/null 2>&1 && systemctl --version >/dev/null 2>&1; then - return 0 - fi - return 1 -} - -disk_usage() { - local path=$1 - local usage - if [ -d "$path" ]; then - # Wrap `du` in `timeout 5s` so a container data directory with - # millions of files (the exact scenario this script exists to - # warn about) cannot stall the preflight indefinitely. If the - # `timeout` binary is absent the pipeline still exits 0 via - # `|| true` and `usage` stays empty; the warning itself is - # still printed, just without the size detail. - usage=$(timeout 5s du -sh "$path" 2>/dev/null | awk '{print $1}' || true) - if [ -n "${usage:-}" ]; then - printf ' (%s uses %s)' "$path" "$usage" - fi - fi -} - -service_active() { - local service=$1 - if [ "$HAS_SYSTEMCTL" = "1" ]; then - if systemctl is-active "$service" >/dev/null 2>&1; then - return 0 - fi - fi - return 1 -} - -check_containerd() { - local detail="" - local found=0 - if service_active containerd.service; then - found=1 - fi - if [ "$found" -eq 0 ] && [ -e "$CONTAINERD_SOCKET" ]; then - found=1 - fi - if [ "$found" -eq 1 ]; then - detail=$(disk_usage "$CONTAINERD_DIR") - warn "standalone containerd.service detected alongside k3s embedded runtime${detail}" - CONTAINERD_WARN=1 - fi -} - -check_docker() { - local detail="" - local found=0 - if service_active docker.service; then - found=1 - fi - if [ "$found" -eq 0 ]; then - # DOCKER_SOCKET_PATHS is a space separated list of paths. Parse - # it into an array via `read -ra` so that word splitting is - # explicit AND glob expansion is suppressed — `for sock in - # $DOCKER_SOCKET_PATHS` would both word split and glob, so a - # path containing a literal `*` or `?` could expand into - # directory entries and produce false positives. - local -a _socks - read -ra _socks <<<"$DOCKER_SOCKET_PATHS" - for sock in "${_socks[@]}"; do - if [ -e "$sock" ]; then - found=1 - break - fi - done - fi - if [ "$found" -eq 1 ]; then - detail=$(disk_usage "$DOCKER_DIR") - warn "standalone docker.service detected alongside k3s embedded runtime${detail}" - DOCKER_WARN=1 - fi -} - -if detect_systemctl; then - HAS_SYSTEMCTL=1 -else - HAS_SYSTEMCTL=0 -fi - -check_containerd -check_docker - -if [ "$CONTAINERD_WARN" -eq 1 ] || [ "$DOCKER_WARN" -eq 1 ]; then - services="" - if [ "$CONTAINERD_WARN" -eq 1 ]; then - services="containerd.service" - fi - if [ "$DOCKER_WARN" -eq 1 ]; then - if [ -n "$services" ]; then - services="$services docker.service" - else - services="docker.service" - fi - fi - printf '%sHINT:%s cozystack runs its own containerd under k3s. To stop the shadow runtime:\n' "$YELLOW" "$RESET" >&2 - printf ' sudo systemctl disable --now %s\n' "$services" >&2 - printf 'Inspect and reclaim standalone runtime storage separately — it may contain container data\n' >&2 - printf 'that the operator still needs; do not delete it blindly.\n' >&2 -fi - -exit 0 diff --git a/hack/check-readiness.sh b/hack/check-readiness.sh deleted file mode 100755 index bd3a3ffc..00000000 --- a/hack/check-readiness.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash -# Check readiness of Packages, ArtifactGenerators, ExternalArtifacts, and HelmReleases -# Shows only non-ready resources -# -# Usage: check-readiness.sh [-w [INTERVAL]] -# -w [INTERVAL] Watch mode: refresh continuously every INTERVAL seconds (default: 5) - -set -euo pipefail - -KUBECTL="kubectl" -if [[ -n "${KUBECONFIG:-}" ]]; then - KUBECTL="kubectl --kubeconfig=${KUBECONFIG}" -fi - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BOLD='\033[1m' -RESET='\033[0m' - -WATCH=0 -INTERVAL=5 - -while [[ $# -gt 0 ]]; do - case "$1" in - -w|--watch) - WATCH=1 - if [[ $# -gt 1 && "$2" =~ ^[0-9]+$ ]]; then - INTERVAL="$2" - shift - fi - shift - ;; - *) echo "Unknown argument: $1"; exit 2 ;; - esac -done - -check_resource() { - local kind="$1" - local header_printed=0 - - while IFS= read -r line; do - if [[ "$line" =~ ^(NAME|NAMESPACE) ]]; then - continue - fi - if ! echo "$line" | awk '{for(i=1;i<=NF;i++) if($i=="True") exit 0; exit 1}'; then - if [[ $header_printed -eq 0 ]]; then - echo -e "${BOLD}${YELLOW}=== ${kind} (not ready) ===${RESET}" - header_printed=1 - fi - echo -e "${RED}${line}${RESET}" - found_issues=1 - fi - done < <($KUBECTL get "$kind" -A 2>/dev/null) - - return 0 -} - -run_once() { - found_issues=0 - - check_resource packages.cozystack.io - check_resource artifactgenerators.source.extensions.fluxcd.io - check_resource externalartifacts.source.toolkit.fluxcd.io - check_resource helmreleases.helm.toolkit.fluxcd.io - - if [[ $found_issues -eq 0 ]]; then - echo -e "${GREEN}${BOLD}All resources are ready.${RESET}" - fi -} - -if [[ $WATCH -eq 1 ]]; then - while true; do - output=$(run_once 2>&1) - clear - echo -e "${BOLD}Last updated: $(date) (refreshing every ${INTERVAL}s, Ctrl+C to stop)${RESET}\n" - echo -e "$output" - sleep "$INTERVAL" - done -else - run_once - [[ $found_issues -eq 0 ]] || exit 1 -fi diff --git a/hack/common-envs.mk b/hack/common-envs.mk index 9b8db5db..56eb5478 100644 --- a/hack/common-envs.mk +++ b/hack/common-envs.mk @@ -6,13 +6,13 @@ else endif REGISTRY ?= ghcr.io/cozystack/cozystack -TAG = $(shell git describe --tags --exact-match --match 'v*' 2>/dev/null || echo latest) +TAG = $(shell git describe --tags --exact-match 2>/dev/null || echo latest) PUSH := 1 LOAD := 0 BUILDER ?= PLATFORM ?= BUILDX_EXTRA_ARGS ?= -COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags --match 'v*')) +COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags)) BUILDX_ARGS := --provenance=false --push=$(PUSH) --load=$(LOAD) \ --label org.opencontainers.image.source=https://github.com/cozystack/cozystack \ @@ -28,6 +28,6 @@ endef ifeq ($(COZYSTACK_VERSION),) $(shell git remote add upstream https://github.com/cozystack/cozystack.git || true) $(shell git fetch upstream --tags) - COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags --match 'v*')) + COZYSTACK_VERSION = $(patsubst v%,%,$(shell git describe --tags)) endif diff --git a/hack/cozyreport.sh b/hack/cozyreport.sh index 565fd435..28fddfe9 100755 --- a/hack/cozyreport.sh +++ b/hack/cozyreport.sh @@ -57,23 +57,23 @@ kubectl get hr -A --no-headers | awk '$4 != "True"' | \ done echo "Collecting packages..." -kubectl get packages > $REPORT_DIR/kubernetes/packages.txt 2>&1 -kubectl get packages --no-headers | awk '$3 != "True"' | \ - while read NAME _; do - DIR=$REPORT_DIR/kubernetes/packages/$NAME +kubectl get packages -A > $REPORT_DIR/kubernetes/packages.txt 2>&1 +kubectl get packages -A --no-headers | awk '$4 != "True"' | \ + while read NAMESPACE NAME _; do + DIR=$REPORT_DIR/kubernetes/packages/$NAMESPACE/$NAME mkdir -p $DIR - kubectl get package $NAME -o yaml > $DIR/package.yaml 2>&1 - kubectl describe package $NAME > $DIR/describe.txt 2>&1 + kubectl get package -n $NAMESPACE $NAME -o yaml > $DIR/package.yaml 2>&1 + kubectl describe package -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1 done echo "Collecting packagesources..." -kubectl get packagesources > $REPORT_DIR/kubernetes/packagesources.txt 2>&1 -kubectl get packagesources --no-headers | awk '$3 != "True"' | \ - while read NAME _; do - DIR=$REPORT_DIR/kubernetes/packagesources/$NAME +kubectl get packagesources -A > $REPORT_DIR/kubernetes/packagesources.txt 2>&1 +kubectl get packagesources -A --no-headers | awk '$4 != "True"' | \ + while read NAMESPACE NAME _; do + DIR=$REPORT_DIR/kubernetes/packagesources/$NAMESPACE/$NAME mkdir -p $DIR - kubectl get packagesource $NAME -o yaml > $DIR/packagesource.yaml 2>&1 - kubectl describe packagesource $NAME > $DIR/describe.txt 2>&1 + kubectl get packagesource -n $NAMESPACE $NAME -o yaml > $DIR/packagesource.yaml 2>&1 + kubectl describe packagesource -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1 done echo "Collecting pods..." @@ -82,7 +82,7 @@ kubectl get pod -A --no-headers | awk '$4 !~ /Running|Succeeded|Completed/' | while read NAMESPACE NAME _ STATE _; do DIR=$REPORT_DIR/kubernetes/pods/$NAMESPACE/$NAME mkdir -p $DIR - CONTAINERS=$(kubectl get pod -o jsonpath='{.spec.containers[*].name} {.spec.initContainers[*].name}' -n $NAMESPACE $NAME) + CONTAINERS=$(kubectl get pod -o jsonpath='{.spec.containers[*].name}' -n $NAMESPACE $NAME) kubectl get pod -n $NAMESPACE $NAME -o yaml > $DIR/pod.yaml 2>&1 kubectl describe pod -n $NAMESPACE $NAME > $DIR/describe.txt 2>&1 if [ "$STATE" != "Pending" ]; then diff --git a/hack/cozytest.sh b/hack/cozytest.sh index a3955fd1..ff476e08 100755 --- a/hack/cozytest.sh +++ b/hack/cozytest.sh @@ -10,11 +10,7 @@ PATTERN=${2:-*} LINE='----------------------------------------------------------------' cols() { stty size 2>/dev/null | awk '{print $2}' || echo 80; } -if [ -t 1 ]; then - MAXW=$(( $(cols) - 12 )); [ "$MAXW" -lt 40 ] && MAXW=70 -else - MAXW=0 # no truncation when not a tty (e.g. CI) -fi +MAXW=$(( $(cols) - 12 )); [ "$MAXW" -lt 40 ] && MAXW=70 BEGIN=$(date +%s) timestamp() { s=$(( $(date +%s) - BEGIN )); printf '[%02d:%02d]' $((s/60)) $((s%60)); } @@ -49,7 +45,7 @@ run_one() { *) out=$line ;; esac now=$(( $(date +%s) - START )) - [ "$MAXW" -gt 0 ] && [ ${#out} -gt "$MAXW" ] && out="$(printf '%.*s…' "$MAXW" "$out")" + [ ${#out} -gt "$MAXW" ] && out="$(printf '%.*s…' "$MAXW" "$out")" printf '┊[%02d:%02d] %s\n' $((now/60)) $((now%60)) "$out" done @@ -65,7 +61,6 @@ run_one() { echo "----- captured output -----------------------------------------" grep -v '^__RC__' "$log" echo "$LINE" - rm -rf "$tmp" exit "$rc" fi diff --git a/hack/dcgm-default-counters.csv b/hack/dcgm-default-counters.csv deleted file mode 100644 index b5e94540..00000000 --- a/hack/dcgm-default-counters.csv +++ /dev/null @@ -1,104 +0,0 @@ -# Snapshot of the upstream DCGM Exporter default-counters.csv used as a -# fixture by hack/check-gpu-recording-rules.bats. The test verifies that -# every DCGM_FI_* metric referenced by a tracked GPU dashboard is either -# declared here (upstream defaults) or in -# packages/system/gpu-operator/examples/dcgm-custom-metrics.yaml -# (the project's custom CSV). -# -# Source: https://github.com/NVIDIA/dcgm-exporter/blob/4.1.1-4.0.4/etc/default-counters.csv -# Pinned to the DCGM Exporter image tag shipped by the gpu-operator -# chart under packages/system/gpu-operator/charts/gpu-operator/values.yaml -# (dcgmExporter.version = 4.1.1-4.0.4-ubuntu22.04). When that image is -# bumped, refresh this file from the matching tag in the NVIDIA/dcgm-exporter -# repo and re-run `./hack/cozytest.sh hack/check-gpu-recording-rules.bats`. - -# Format -# If line starts with a '#' it is considered a comment -# DCGM FIELD, Prometheus metric type, help message - -# Clocks -DCGM_FI_DEV_SM_CLOCK, gauge, SM clock frequency (in MHz). -DCGM_FI_DEV_MEM_CLOCK, gauge, Memory clock frequency (in MHz). - -# Temperature -DCGM_FI_DEV_MEMORY_TEMP, gauge, Memory temperature (in C). -DCGM_FI_DEV_GPU_TEMP, gauge, GPU temperature (in C). - -# Power -DCGM_FI_DEV_POWER_USAGE, gauge, Power draw (in W). -DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION, counter, Total energy consumption since boot (in mJ). - -# PCIE -# DCGM_FI_PROF_PCIE_TX_BYTES, counter, Total number of bytes transmitted through PCIe TX via NVML. -# DCGM_FI_PROF_PCIE_RX_BYTES, counter, Total number of bytes received through PCIe RX via NVML. -DCGM_FI_DEV_PCIE_REPLAY_COUNTER, counter, Total number of PCIe retries. - -# Utilization (the sample period varies depending on the product) -DCGM_FI_DEV_GPU_UTIL, gauge, GPU utilization (in %). -DCGM_FI_DEV_MEM_COPY_UTIL, gauge, Memory utilization (in %). -DCGM_FI_DEV_ENC_UTIL, gauge, Encoder utilization (in %). -DCGM_FI_DEV_DEC_UTIL , gauge, Decoder utilization (in %). - -# Errors and violations -DCGM_FI_DEV_XID_ERRORS, gauge, Value of the last XID error encountered. -# DCGM_FI_DEV_POWER_VIOLATION, counter, Throttling duration due to power constraints (in us). -# DCGM_FI_DEV_THERMAL_VIOLATION, counter, Throttling duration due to thermal constraints (in us). -# DCGM_FI_DEV_SYNC_BOOST_VIOLATION, counter, Throttling duration due to sync-boost constraints (in us). -# DCGM_FI_DEV_BOARD_LIMIT_VIOLATION, counter, Throttling duration due to board limit constraints (in us). -# DCGM_FI_DEV_LOW_UTIL_VIOLATION, counter, Throttling duration due to low utilization (in us). -# DCGM_FI_DEV_RELIABILITY_VIOLATION, counter, Throttling duration due to reliability constraints (in us). - -# Memory usage -DCGM_FI_DEV_FB_FREE, gauge, Framebuffer memory free (in MiB). -DCGM_FI_DEV_FB_USED, gauge, Framebuffer memory used (in MiB). - -# ECC -# DCGM_FI_DEV_ECC_SBE_VOL_TOTAL, counter, Total number of single-bit volatile ECC errors. -# DCGM_FI_DEV_ECC_DBE_VOL_TOTAL, counter, Total number of double-bit volatile ECC errors. -# DCGM_FI_DEV_ECC_SBE_AGG_TOTAL, counter, Total number of single-bit persistent ECC errors. -# DCGM_FI_DEV_ECC_DBE_AGG_TOTAL, counter, Total number of double-bit persistent ECC errors. - -# Retired pages -# DCGM_FI_DEV_RETIRED_SBE, counter, Total number of retired pages due to single-bit errors. -# DCGM_FI_DEV_RETIRED_DBE, counter, Total number of retired pages due to double-bit errors. -# DCGM_FI_DEV_RETIRED_PENDING, counter, Total number of pages pending retirement. - -# NVLink -# DCGM_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_TOTAL, counter, Total number of NVLink flow-control CRC errors. -# DCGM_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_TOTAL, counter, Total number of NVLink data CRC errors. -# DCGM_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_TOTAL, counter, Total number of NVLink retries. -# DCGM_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_TOTAL, counter, Total number of NVLink recovery errors. -DCGM_FI_DEV_NVLINK_BANDWIDTH_TOTAL, counter, Total number of NVLink bandwidth counters for all lanes. -# DCGM_FI_DEV_NVLINK_BANDWIDTH_L0, counter, The number of bytes of active NVLink rx or tx data including both header and payload. - -# VGPU License status -DCGM_FI_DEV_VGPU_LICENSE_STATUS, gauge, vGPU License status - -# Remapped rows -DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for uncorrectable errors -DCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWS, counter, Number of remapped rows for correctable errors -DCGM_FI_DEV_ROW_REMAP_FAILURE, gauge, Whether remapping of rows has failed - -# Static configuration information. These appear as labels on the other metrics -DCGM_FI_DRIVER_VERSION, label, Driver Version -# DCGM_FI_NVML_VERSION, label, NVML Version -# DCGM_FI_DEV_BRAND, label, Device Brand -# DCGM_FI_DEV_SERIAL, label, Device Serial Number -# DCGM_FI_DEV_OEM_INFOROM_VER, label, OEM inforom version -# DCGM_FI_DEV_ECC_INFOROM_VER, label, ECC inforom version -# DCGM_FI_DEV_POWER_INFOROM_VER, label, Power management object inforom version -# DCGM_FI_DEV_INFOROM_IMAGE_VER, label, Inforom image version -# DCGM_FI_DEV_VBIOS_VERSION, label, VBIOS version of the device - -# Datacenter Profiling (DCP) metrics -# NOTE: supported on Nvidia datacenter Volta GPUs and newer -DCGM_FI_PROF_GR_ENGINE_ACTIVE, gauge, Ratio of time the graphics engine is active. -# DCGM_FI_PROF_SM_ACTIVE, gauge, The ratio of cycles an SM has at least 1 warp assigned. -# DCGM_FI_PROF_SM_OCCUPANCY, gauge, The ratio of number of warps resident on an SM. -DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active. -DCGM_FI_PROF_DRAM_ACTIVE, gauge, Ratio of cycles the device memory interface is active sending or receiving data. -# DCGM_FI_PROF_PIPE_FP64_ACTIVE, gauge, Ratio of cycles the fp64 pipes are active. -# DCGM_FI_PROF_PIPE_FP32_ACTIVE, gauge, Ratio of cycles the fp32 pipes are active. -# DCGM_FI_PROF_PIPE_FP16_ACTIVE, gauge, Ratio of cycles the fp16 pipes are active. -DCGM_FI_PROF_PCIE_TX_BYTES, gauge, The rate of data transmitted over the PCIe bus - including both protocol headers and data payloads - in bytes per second. -DCGM_FI_PROF_PCIE_RX_BYTES, gauge, The rate of data received over the PCIe bus - including both protocol headers and data payloads - in bytes per second. diff --git a/hack/download-dashboards.sh b/hack/download-dashboards.sh index d761f71c..a1a6082a 100755 --- a/hack/download-dashboards.sh +++ b/hack/download-dashboards.sh @@ -83,8 +83,6 @@ modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//flux/flux-stats modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//kafka/strimzi-kafka.json modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//seaweedfs/seaweedfs.json modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//goldpinger/goldpinger.json -modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//nats/nats-jetstream.json -modules/340-monitoring-kubernetes/monitoring/grafana-dashboards//nats/nats-server.json EOT diff --git a/hack/e2e-apps/bucket.bats b/hack/e2e-apps/bucket.bats index 31e7efb0..2621812a 100644 --- a/hack/e2e-apps/bucket.bats +++ b/hack/e2e-apps/bucket.bats @@ -1,39 +1,29 @@ #!/usr/bin/env bats @test "Create and Verify Seeweedfs Bucket" { - # Create the bucket resource with readwrite and readonly users + # Create the bucket resource name='test' - kubectl -n tenant-test delete bucket.apps.cozystack.io $name --ignore-not-found --timeout=2m || true - pkill -f "port-forward.*8333:" 2>/dev/null || true kubectl apply -f - < bucket-admin-credentials.json - ADMIN_ACCESS_KEY=$(jq -r '.spec.secretS3.accessKeyID' bucket-admin-credentials.json) - ADMIN_SECRET_KEY=$(jq -r '.spec.secretS3.accessSecretKey' bucket-admin-credentials.json) - BUCKET_NAME=$(jq -r '.spec.bucketName' bucket-admin-credentials.json) + # Get and decode credentials + kubectl -n tenant-test get secret bucket-${name} -ojsonpath='{.data.BucketInfo}' | base64 -d > bucket-test-credentials.json - # Get viewer (readonly) credentials - kubectl -n tenant-test get secret bucket-${name}-viewer -ojsonpath='{.data.BucketInfo}' | base64 -d > bucket-viewer-credentials.json - VIEWER_ACCESS_KEY=$(jq -r '.spec.secretS3.accessKeyID' bucket-viewer-credentials.json) - VIEWER_SECRET_KEY=$(jq -r '.spec.secretS3.accessSecretKey' bucket-viewer-credentials.json) + # Get credentials from the secret + ACCESS_KEY=$(jq -r '.spec.secretS3.accessKeyID' bucket-test-credentials.json) + SECRET_KEY=$(jq -r '.spec.secretS3.accessSecretKey' bucket-test-credentials.json) + BUCKET_NAME=$(jq -r '.spec.bucketName' bucket-test-credentials.json) # Start port-forwarding bash -c 'timeout 100s kubectl port-forward service/seaweedfs-s3 -n tenant-root 8333:8333 > /dev/null 2>&1 &' @@ -41,33 +31,17 @@ EOF # Wait for port-forward to be ready timeout 30 sh -ec 'until nc -z localhost 8333; do sleep 1; done' - # --- Test readwrite user (admin) --- - mc alias set rw-user https://localhost:8333 $ADMIN_ACCESS_KEY $ADMIN_SECRET_KEY --insecure + # Set up MinIO alias with error handling + mc alias set local https://localhost:8333 $ACCESS_KEY $SECRET_KEY --insecure - # Admin can upload - echo "readwrite test" > /tmp/rw-test.txt - mc cp --insecure /tmp/rw-test.txt rw-user/$BUCKET_NAME/rw-test.txt + # Upload file to bucket + mc cp bucket-test-credentials.json $BUCKET_NAME/bucket-test-credentials.json - # Admin can list - mc ls --insecure rw-user/$BUCKET_NAME/rw-test.txt + # Verify file was uploaded + mc ls $BUCKET_NAME/bucket-test-credentials.json - # Admin can download - mc cp --insecure rw-user/$BUCKET_NAME/rw-test.txt /tmp/rw-test-download.txt + # Clean up uploaded file + mc rm $BUCKET_NAME/bucket-test-credentials.json - # --- Test readonly user (viewer) --- - mc alias set ro-user https://localhost:8333 $VIEWER_ACCESS_KEY $VIEWER_SECRET_KEY --insecure - - # Viewer can list - mc ls --insecure ro-user/$BUCKET_NAME/rw-test.txt - - # Viewer can download - mc cp --insecure ro-user/$BUCKET_NAME/rw-test.txt /tmp/ro-test-download.txt - - # Viewer cannot upload (must fail with Access Denied) - echo "readonly test" > /tmp/ro-test.txt - ! mc cp --insecure /tmp/ro-test.txt ro-user/$BUCKET_NAME/ro-test.txt - - # --- Cleanup --- - mc rm --insecure rw-user/$BUCKET_NAME/rw-test.txt kubectl -n tenant-test delete bucket.apps.cozystack.io ${name} } diff --git a/hack/e2e-apps/clickhouse.bats b/hack/e2e-apps/clickhouse.bats index fbc9f906..1684c0c4 100644 --- a/hack/e2e-apps/clickhouse.bats +++ b/hack/e2e-apps/clickhouse.bats @@ -2,7 +2,6 @@ @test "Create DB ClickHouse" { name='test' - kubectl -n tenant-test delete clickhouse.apps.cozystack.io $name --ignore-not-found --timeout=2m || true kubectl apply -f- </dev/null || true -} - -@test "Create and Verify ExternalDNS with inmemory provider" { - name='test' - kubectl apply -f - <" + s3SecretKey: "" + schedule: "0 2 * * * *" + bootstrap: + enabled: false + external: false + quorum: + maxSyncReplicas: 0 + minSyncReplicas: 0 + replicas: 2 + resources: {} + resourcesPreset: "micro" + size: "10Gi" + users: + testuser: + password: xai7Wepo +EOF + sleep 5 + kubectl -n tenant-test wait hr ferretdb-$name --timeout=100s --for=condition=ready + timeout 40 sh -ec "until kubectl -n tenant-test get svc ferretdb-$name-postgres-r -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done" + timeout 40 sh -ec "until kubectl -n tenant-test get svc ferretdb-$name-postgres-ro -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done" + timeout 40 sh -ec "until kubectl -n tenant-test get svc ferretdb-$name-postgres-rw -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done" + timeout 120 sh -ec "until kubectl -n tenant-test get endpoints ferretdb-$name-postgres-r -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done" + # for some reason it takes longer for the read-only endpoint to be ready + #timeout 120 sh -ec "until kubectl -n tenant-test get endpoints ferretdb-$name-postgres-ro -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done" + timeout 120 sh -ec "until kubectl -n tenant-test get endpoints ferretdb-$name-postgres-rw -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done" + kubectl -n tenant-test delete ferretdb.apps.cozystack.io $name +} diff --git a/hack/e2e-apps/foundationdb.bats b/hack/e2e-apps/foundationdb.bats index 199bda11..4c8d1b53 100644 --- a/hack/e2e-apps/foundationdb.bats +++ b/hack/e2e-apps/foundationdb.bats @@ -2,7 +2,6 @@ @test "Create DB FoundationDB" { name='test' - kubectl -n tenant-test delete foundationdb.apps.cozystack.io $name --ignore-not-found --timeout=2m || true kubectl apply -f - </dev/null || true - kubectl -n tenant-test wait hr $release --timeout=60s --for=delete 2>/dev/null || true - - kubectl apply -f- <&1 || true - echo "=== Pods ===" - kubectl -n tenant-test get pods 2>&1 || true - echo "=== Events ===" - kubectl -n tenant-test get events --sort-by='.lastTimestamp' 2>&1 | tail -30 || true - echo "=== ExternalArtifact ===" - kubectl -n cozy-system get externalartifact cozystack-harbor-application-default-harbor-system -o yaml 2>&1 || true - echo "=== BucketClaim status ===" - kubectl -n tenant-test get bucketclaims.objectstorage.k8s.io $release-registry -o yaml 2>&1 || true - echo "=== BucketAccess status ===" - kubectl -n tenant-test get bucketaccesses.objectstorage.k8s.io $release-registry -o yaml 2>&1 || true - echo "=== BucketAccess Secret ===" - kubectl -n tenant-test get secret $release-registry-bucket -o jsonpath='{.data.BucketInfo}' 2>&1 | base64 -d 2>&1 || true - false - } - kubectl -n tenant-test wait deploy $release-core --timeout=120s --for=condition=available - kubectl -n tenant-test wait deploy $release-registry --timeout=120s --for=condition=available - kubectl -n tenant-test wait deploy $release-portal --timeout=120s --for=condition=available - kubectl -n tenant-test get secret $release-credentials -o jsonpath='{.data.admin-password}' | base64 --decode | grep -q '.' - kubectl -n tenant-test get secret $release-credentials -o jsonpath='{.data.url}' | base64 --decode | grep -q 'https://' - kubectl -n tenant-test get svc $release -o jsonpath='{.spec.ports[0].port}' | grep -q '80' - kubectl -n tenant-test delete harbor.apps.cozystack.io $name -} diff --git a/hack/e2e-apps/kafka.bats b/hack/e2e-apps/kafka.bats index d85837bd..ceaf2cde 100644 --- a/hack/e2e-apps/kafka.bats +++ b/hack/e2e-apps/kafka.bats @@ -2,8 +2,6 @@ @test "Create Kafka" { name='test' - kubectl -n tenant-test delete kafka.apps.cozystack.io $name --ignore-not-found --timeout=2m || true - kubectl -n tenant-test wait kafka.apps.cozystack.io $name --for=delete --timeout=2m 2>/dev/null || true kubectl apply -f- </dev/null | grep -q true; do sleep 5; done"; then - echo "=== DEBUG: Container did not start in time ===" >&2 - kubectl -n tenant-test describe pod openbao-$name-0 >&2 || true - kubectl -n tenant-test logs openbao-$name-0 --previous >&2 || true - kubectl -n tenant-test logs openbao-$name-0 >&2 || true - return 1 - fi - - # Wait for OpenBAO API to accept connections - # bao status exit codes: 0 = unsealed, 1 = error/not ready, 2 = sealed but responsive - if ! timeout 60 sh -ec "until kubectl -n tenant-test exec openbao-$name-0 -- bao status >/dev/null 2>&1; rc=\$?; test \$rc -eq 0 -o \$rc -eq 2; do sleep 3; done"; then - echo "=== DEBUG: OpenBAO API did not become responsive ===" >&2 - kubectl -n tenant-test describe pod openbao-$name-0 >&2 || true - kubectl -n tenant-test logs openbao-$name-0 --previous >&2 || true - kubectl -n tenant-test logs openbao-$name-0 >&2 || true - return 1 - fi - - # Initialize OpenBAO (single key share for testing simplicity) - init_output=$(kubectl -n tenant-test exec openbao-$name-0 -- bao operator init -key-shares=1 -key-threshold=1 -format=json) - unseal_key=$(echo "$init_output" | jq -r '.unseal_keys_b64[0]') - if [ -z "$unseal_key" ] || [ "$unseal_key" = "null" ]; then - echo "Failed to extract unseal key. Init output: $init_output" >&2 - return 1 - fi - - # Unseal OpenBAO - kubectl -n tenant-test exec openbao-$name-0 -- bao operator unseal "$unseal_key" - - # Now wait for pod to become ready (readiness probe checks seal status) - kubectl -n tenant-test wait sts openbao-$name --timeout=90s --for=jsonpath='{.status.readyReplicas}'=1 - kubectl -n tenant-test wait pvc data-openbao-$name-0 --timeout=50s --for=jsonpath='{.status.phase}'=Bound - kubectl -n tenant-test delete openbao.apps.cozystack.io $name - kubectl -n tenant-test delete pvc data-openbao-$name-0 --ignore-not-found -} diff --git a/hack/e2e-apps/postgres.bats b/hack/e2e-apps/postgres.bats index b86bc664..024ce086 100644 --- a/hack/e2e-apps/postgres.bats +++ b/hack/e2e-apps/postgres.bats @@ -2,7 +2,6 @@ @test "Create DB PostgreSQL" { name='test' - kubectl -n tenant-test delete postgreses.apps.cozystack.io $name --ignore-not-found --timeout=2m || true kubectl apply -f - </dev/null || true - kubectl -n tenant-test wait kuberneteses.apps.cozystack.io "${test_name}" --for=delete --timeout=2m 2>/dev/null || true - kubectl apply -f - < "tenantkubeconfig-${test_name}" + kubectl get secret kubernetes-${test_name}-admin-kubeconfig -ojsonpath='{.data.super-admin\.conf}' -n tenant-test | base64 -d > tenantkubeconfig-${test_name} # Update the kubeconfig to use localhost for the API server - yq -i ".clusters[0].cluster.server = \"https://localhost:${port}\"" "tenantkubeconfig-${test_name}" + yq -i ".clusters[0].cluster.server = \"https://localhost:${port}\"" tenantkubeconfig-${test_name} - # Kill any stale port-forward on this port from a previous retry - pkill -f "port-forward.*${port}:" 2>/dev/null || true - sleep 1 - - # Set up port forwarding to the Kubernetes API server - # No timeout — process is killed at end of test or by job-level timeout-minutes - kubectl port-forward service/kubernetes-"${test_name}" -n tenant-test "${port}":6443 > /dev/null 2>&1 & - # Wait for port-forward to be ready before using it - timeout 15 sh -ec 'until curl -sk https://localhost:'"${port}"' >/dev/null 2>&1; do sleep 1; done' + # Set up port forwarding to the Kubernetes API server for a 200 second timeout + bash -c 'timeout 500s kubectl port-forward service/kubernetes-'"${test_name}"' -n tenant-test '"${port}"':6443 > /dev/null 2>&1 &' # Verify the Kubernetes version matches what we expect (retry for up to 20 seconds) - timeout 20 sh -ec 'until kubectl --kubeconfig tenantkubeconfig-'"${test_name}"' version 2>/dev/null | grep -Fq "Server Version: ${k8s_version}"; do sleep 1; done' + timeout 20 sh -ec 'until kubectl --kubeconfig tenantkubeconfig-'"${test_name}"' version 2>/dev/null | grep -Fq "Server Version: ${k8s_version}"; do sleep 5; done' - # Wait for at least 2 nodes to join (timeout after 8 minutes) - timeout 8m bash -c ' - until [ "$(kubectl --kubeconfig tenantkubeconfig-'"${test_name}"' get nodes -o jsonpath="{.items[*].metadata.name}" | wc -w)" -ge 2 ]; do + # Wait for the nodes to be ready (timeout after 2 minutes) + timeout 3m bash -c ' + until [ "$(kubectl --kubeconfig tenantkubeconfig-'"${test_name}"' get nodes -o jsonpath="{.items[*].metadata.name}" | wc -w)" -eq 2 ]; do sleep 2 done ' # Verify the nodes are ready - if ! kubectl --kubeconfig "tenantkubeconfig-${test_name}" wait node --all --timeout=3m --for=condition=Ready; then - # Dump debug info and fail fast — no point running LB/NFS tests without Ready nodes - kubectl --kubeconfig "tenantkubeconfig-${test_name}" describe nodes - kubectl -n tenant-test get hr - exit 1 - fi - kubectl --kubeconfig "tenantkubeconfig-${test_name}" get nodes -o wide + kubectl --kubeconfig tenantkubeconfig-${test_name} wait node --all --timeout=2m --for=condition=Ready + kubectl --kubeconfig tenantkubeconfig-${test_name} get nodes -o wide # Verify the kubelet version matches what we expect versions=$(kubectl --kubeconfig "tenantkubeconfig-${test_name}" \ get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}') - + node_ok=true - + for v in $versions; do case "$v" in "${k8s_version}" | "${k8s_version}".* | "${k8s_version}"-*) @@ -143,21 +125,15 @@ EOF fi - kubectl --kubeconfig "tenantkubeconfig-${test_name}" apply -f - <&2 - exit 1 - fi +if [ -z "$LB_ADDR" ]; then + echo "LoadBalancer address is empty" >&2 + exit 1 +fi - lb_ok=false for i in $(seq 1 20); do echo "Attempt $i" - if curl --silent --fail "http://${LB_ADDR}"; then - lb_ok=true - break - fi + curl --silent --fail "http://${LB_ADDR}" && break sleep 3 done - if [ "$lb_ok" != true ]; then + if [ "$i" -eq 20 ]; then echo "LoadBalancer not reachable" >&2 exit 1 fi # Cleanup - kubectl delete deployment --kubeconfig "tenantkubeconfig-${test_name}" "${test_name}-backend" -n tenant-test - kubectl delete service --kubeconfig "tenantkubeconfig-${test_name}" "${test_name}-backend" -n tenant-test - - # Clean up NFS test resources from any previous failed attempt - kubectl --kubeconfig "tenantkubeconfig-${test_name}" delete pod nfs-test-pod \ - -n tenant-test --ignore-not-found --timeout=60s || true - kubectl --kubeconfig "tenantkubeconfig-${test_name}" delete pvc nfs-test-pvc \ - -n tenant-test --ignore-not-found --timeout=60s || true - - # Test RWX NFS mount in tenant cluster (uses kubevirt CSI driver with RWX support) - kubectl --kubeconfig "tenantkubeconfig-${test_name}" apply -f - < /data/test.txt && cat /data/test.txt"] - volumeMounts: - - name: nfs-vol - mountPath: /data - volumes: - - name: nfs-vol - persistentVolumeClaim: - claimName: nfs-test-pvc - restartPolicy: Never -EOF - - # Wait for Pod to complete successfully - if ! kubectl --kubeconfig "tenantkubeconfig-${test_name}" wait pod nfs-test-pod -n tenant-test --timeout=5m --for=jsonpath='{.status.phase}'=Succeeded; then - echo "=== NFS test pod did not complete ===" >&2 - kubectl --kubeconfig "tenantkubeconfig-${test_name}" describe pod nfs-test-pod -n tenant-test >&2 || true - kubectl --kubeconfig "tenantkubeconfig-${test_name}" get events -n tenant-test --sort-by='.lastTimestamp' >&2 || true - exit 1 - fi - - # Verify NFS data integrity - nfs_result=$(kubectl --kubeconfig "tenantkubeconfig-${test_name}" logs nfs-test-pod -n tenant-test) - if [ "$nfs_result" != "nfs-mount-ok" ]; then - echo "NFS mount test failed: expected 'nfs-mount-ok', got '$nfs_result'" >&2 - kubectl --kubeconfig "tenantkubeconfig-${test_name}" delete pod nfs-test-pod -n tenant-test --wait=false 2>/dev/null || true - kubectl --kubeconfig "tenantkubeconfig-${test_name}" delete pvc nfs-test-pvc -n tenant-test --wait=false 2>/dev/null || true - exit 1 - fi - - # Cleanup NFS test resources in tenant cluster - kubectl --kubeconfig "tenantkubeconfig-${test_name}" delete pod nfs-test-pod -n tenant-test --wait - kubectl --kubeconfig "tenantkubeconfig-${test_name}" delete pvc nfs-test-pvc -n tenant-test + kubectl delete deployment --kubeconfig tenantkubeconfig-${test_name} "${test_name}-backend" -n tenant-test + kubectl delete service --kubeconfig tenantkubeconfig-${test_name} "${test_name}-backend" -n tenant-test # Wait for all machine deployment replicas to be ready (timeout after 10 minutes) kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=10m --for=jsonpath='{.status.v1beta2.readyReplicas}'=2 - for component in cilium coredns csi vsnap-crd; do + for component in cilium coredns csi ingress-nginx vsnap-crd; do kubectl wait hr kubernetes-${test_name}-${component} -n tenant-test --timeout=1m --for=condition=ready done - kubectl wait hr kubernetes-${test_name}-ingress-nginx -n tenant-test --timeout=5m --for=condition=ready - # Guard: parent HelmRelease must not have entered an install/upgrade remediation cycle. - # A non-zero installFailures/upgradeFailures indicates the helm-wait budget expired while - # admin-kubeconfig was still being provisioned, which would trigger uninstall remediation - # and churn the Cluster CR. - # Flux helm-controller v2 retains per-revision release Snapshots in - # .status.history; each Snapshot's .status reflects the Helm release - # state (deployed/superseded/failed/uninstalled). A remediation cycle - # leaves a "failed" or "uninstalled" entry behind that survives a later - # successful reinstall, unlike the installFailures/upgradeFailures - # counters (which ClearFailures zeroes on every successful reconcile). - # The shape is pinned by hack/remediation-guard.bats; the upstream - # types are github.com/fluxcd/helm-controller/api v2 Snapshot. - history_statuses=$(kubectl get hr -n tenant-test "kubernetes-${test_name}" \ - -ojsonpath='{range .status.history[*]}{.status}{"\n"}{end}') - # Always emit the raw value so a silent future-Flux field rename shows - # up as "empty history on a Ready HR" in CI logs rather than vanishing. - echo "Parent HelmRelease history statuses:" - printf '%s\n' "${history_statuses:-}" - if [ -z "${history_statuses}" ]; then - echo "Unexpected empty .status.history on a Ready HelmRelease - Flux API shape may have changed." >&2 - kubectl -n tenant-test describe hr "kubernetes-${test_name}" >&2 - exit 1 - fi - if helmrelease_has_remediation_cycle "${history_statuses}"; then - echo "Parent HelmRelease entered remediation cycle." >&2 - kubectl -n tenant-test describe hr "kubernetes-${test_name}" >&2 - exit 1 - fi - - # Clean up - pkill -f "port-forward.*${port}:" 2>/dev/null || true - rm -f "tenantkubeconfig-${test_name}" - kubectl -n tenant-test delete kuberneteses.apps.cozystack.io "${test_name}" --ignore-not-found --wait=false 2>/dev/null || true + # Clean up by deleting the Kubernetes resource + kubectl -n tenant-test delete kuberneteses.apps.cozystack.io $test_name } diff --git a/hack/e2e-apps/virtualmachine.bats b/hack/e2e-apps/virtualmachine.bats new file mode 100644 index 00000000..33e87b53 --- /dev/null +++ b/hack/e2e-apps/virtualmachine.bats @@ -0,0 +1,45 @@ +#!/usr/bin/env bats + +@test "Create a Virtual Machine" { + name='test' + kubectl apply -f - <&2 +@test "Required installer assets exist" { + if [ ! -f _out/assets/cozystack-crds.yaml ]; then + echo "Missing: _out/assets/cozystack-crds.yaml" >&2 + exit 1 + fi + if [ ! -f _out/assets/cozystack-operator.yaml ]; then + echo "Missing: _out/assets/cozystack-operator.yaml" >&2 exit 1 fi } @test "Install Cozystack" { - # Install cozy-installer chart (operator installs CRDs on startup via --install-crds) - helm upgrade installer packages/core/installer \ - --install \ - --namespace cozy-system \ - --create-namespace \ - --wait \ - --timeout 2m + # Create namespace + kubectl create namespace cozy-system --dry-run=client -o yaml | kubectl apply -f - - # Verify the operator deployment is available + # Apply installer manifests (CRDs + operator) + kubectl apply -f _out/assets/cozystack-crds.yaml + kubectl apply -f _out/assets/cozystack-operator.yaml + + # Wait for the operator deployment to become available kubectl wait deployment/cozystack-operator -n cozy-system --timeout=1m --for=condition=Available - # Wait for operator to install CRDs (happens at startup before reconcile loop). - # kubectl wait fails immediately if the CRD does not exist yet, so poll until it appears first. - timeout 120 sh -ec 'until kubectl wait crd/packages.cozystack.io --for=condition=Established --timeout=10s 2>/dev/null; do sleep 2; done' - timeout 120 sh -ec 'until kubectl wait crd/packagesources.cozystack.io --for=condition=Established --timeout=10s 2>/dev/null; do sleep 2; done' - - # Wait for operator to create the platform PackageSource - timeout 120 sh -ec 'until kubectl get packagesource cozystack.cozystack-platform >/dev/null 2>&1; do sleep 2; done' - # Create platform Package with isp-full variant kubectl apply -f - </dev/null 2>&1; do sleep 1; done' - kubectl wait deployment/capi-controller-manager deployment/capi-kamaji-controller-manager deployment/capi-kubeadm-bootstrap-controller-manager deployment/capi-operator-cluster-api-operator deployment/capk-controller-manager -n cozy-cluster-api --timeout=2m --for=condition=available + timeout 60 sh -ec 'until kubectl get deploy -n cozy-cluster-api capi-controller-manager capi-kamaji-controller-manager capi-kubeadm-bootstrap-controller-manager capi-operator-cluster-api-operator capk-controller-manager >/dev/null 2>&1; do sleep 1; done' + kubectl wait deployment/capi-controller-manager deployment/capi-kamaji-controller-manager deployment/capi-kubeadm-bootstrap-controller-manager deployment/capi-operator-cluster-api-operator deployment/capk-controller-manager -n cozy-cluster-api --timeout=1m --for=condition=available } @test "Wait for LINSTOR and configure storage" { @@ -178,8 +170,8 @@ EOF # VictoriaMetrics components kubectl wait vmalert/vmalert-shortterm vmalertmanager/alertmanager -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=15m - kubectl wait vlclusters/generic -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=5m - kubectl wait vmcluster/shortterm vmcluster/longterm -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=5m + kubectl wait vlogs/generic -n tenant-root --for=jsonpath='{.status.updateStatus}'=operational --timeout=5m + kubectl wait vmcluster/shortterm vmcluster/longterm -n tenant-root --for=jsonpath='{.status.clusterStatus}'=operational --timeout=5m # Grafana kubectl wait clusters.postgresql.cnpg.io/grafana-db -n tenant-root --for=condition=ready --timeout=5m @@ -200,60 +192,8 @@ EOF kubectl wait hr/keycloak hr/keycloak-configure hr/keycloak-operator -n cozy-keycloak --timeout=10m --for=condition=ready } -@test "Aggregated API rejects Tenant name with dashes" { - # Regression guard: the tenant Helm chart's tenant.name helper splits the - # Release.Name on "-" and fails unless the result is exactly - # ["tenant", ""]. The aggregated API must catch tenant names - # containing dashes up-front with a tenant-specific error, instead of - # silently accepting the Application and letting Flux fail later. - - # Defensive cleanup: if a prior regression left foo-bar in the cluster, - # remove it before exercising the validation so we are not observing - # stale state. Safe even in the happy path because of --ignore-not-found. - kubectl delete tenants.apps.cozystack.io foo-bar -n tenant-root --ignore-not-found - - # Preflight: tenant-root is created by earlier tests in this suite. Fail - # loudly if it is missing so this test does not silently trigger an - # unrelated "namespace not found" error and misreport as a pass. - kubectl get namespace tenant-root - - # --validate=ignore forces kubectl to skip client-side OpenAPI validation - # and send the payload straight to the aggregated API. This guarantees the - # server-side name check runs and the error we grep for is the tenant - # contract error, not a kubectl schema rejection. (--validate=false is the - # deprecated alias.) - local output rc - # Run the apply in its own subshell so we can capture BOTH stdout+stderr - # AND the exit code explicitly, without `|| true` swallowing a real failure - # mode (e.g. network error, auth failure) that should also fail the test. - output=$( - kubectl apply --validate=ignore -f - 2>&1 < /dev/null; then exit 1 fi -# Step 0: Annotate critical resources to prevent Helm from deleting them -echo "Step 0: Protect critical resources from Helm deletion" -echo "" -echo "The following resources will be annotated with helm.sh/resource-policy=keep" -echo "to prevent Helm from deleting them when the installer release is removed:" -echo " - Namespace: $NAMESPACE" -echo " - ConfigMap: $NAMESPACE/cozystack-version" -echo "" -read -p "Do you want to annotate these resources? (y/N) " -n 1 -r -echo "" - -if [[ $REPLY =~ ^[Yy]$ ]]; then - echo "Annotating namespace $NAMESPACE..." - kubectl annotate namespace "$NAMESPACE" helm.sh/resource-policy=keep --overwrite - echo "Annotating ConfigMap cozystack-version..." - kubectl annotate configmap -n "$NAMESPACE" cozystack-version helm.sh/resource-policy=keep --overwrite 2>/dev/null || echo " ConfigMap cozystack-version not found, skipping." - echo "" - echo "Resources annotated successfully." -else - echo "WARNING: Skipping annotation. If you remove the Helm installer release," - echo "the namespace and its contents may be deleted!" -fi -echo "" - -# Step 1: Check for cozy-proxy HelmRelease with conflicting releaseName -# In v0.41.x, cozy-proxy was incorrectly configured with releaseName "cozystack", -# which conflicts with the installer helm release name. If not suspended, cozy-proxy -# HelmRelease will overwrite the installer release and delete cozystack-operator. -COZY_PROXY_RELEASE_NAME=$(kubectl get hr -n "$NAMESPACE" cozy-proxy -o jsonpath='{.spec.releaseName}' 2>/dev/null || true) -if [ "$COZY_PROXY_RELEASE_NAME" = "cozystack" ]; then - echo "WARNING: HelmRelease cozy-proxy has releaseName 'cozystack', which conflicts" - echo "with the installer release. It must be suspended before proceeding, otherwise" - echo "it will overwrite the installer and delete cozystack-operator." - echo "" - read -p "Suspend HelmRelease cozy-proxy? (y/N) " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Yy]$ ]]; then - kubectl -n "$NAMESPACE" patch hr cozy-proxy --type=merge --field-manager=flux-client-side-apply -p '{"spec":{"suspend":true}}' - echo "HelmRelease cozy-proxy suspended." - else - echo "ERROR: Cannot proceed with conflicting cozy-proxy HelmRelease active." - echo "Please suspend it manually:" - echo " kubectl -n $NAMESPACE patch hr cozy-proxy --type=merge -p '{\"spec\":{\"suspend\":true}}'" - exit 1 - fi - echo "" -fi - # Read ConfigMap cozystack echo "Reading ConfigMap cozystack..." COZYSTACK_CM=$(kubectl get configmap -n "$NAMESPACE" cozystack -o json 2>/dev/null || echo "{}") @@ -100,43 +52,6 @@ OIDC_ENABLED=$(echo "$COZYSTACK_CM" | jq -r '.data["oidc-enabled"] // "false"') KEYCLOAK_REDIRECTS=$(echo "$COZYSTACK_CM" | jq -r '.data["extra-keycloak-redirect-uri-for-dashboard"] // ""' ) TELEMETRY_ENABLED=$(echo "$COZYSTACK_CM" | jq -r '.data["telemetry-enabled"] // "true"') BUNDLE_NAME=$(echo "$COZYSTACK_CM" | jq -r '.data["bundle-name"] // "paas-full"') -BUNDLE_DISABLE=$(echo "$COZYSTACK_CM" | jq -r '.data["bundle-disable"] // ""') -BUNDLE_ENABLE=$(echo "$COZYSTACK_CM" | jq -r '.data["bundle-enable"] // ""') -EXPOSE_INGRESS=$(echo "$COZYSTACK_CM" | jq -r '.data["expose-ingress"] // "tenant-root"') -EXPOSE_SERVICES=$(echo "$COZYSTACK_CM" | jq -r '.data["expose-services"] // ""') - -# Certificate issuer configuration (old undocumented field: clusterissuer) -OLD_CLUSTER_ISSUER=$(echo "$COZYSTACK_CM" | jq -r '.data["clusterissuer"] // ""') - -# Convert old clusterissuer value to new solver/issuerName fields -SOLVER="" -ISSUER_NAME="" -case "$OLD_CLUSTER_ISSUER" in - cloudflare) - SOLVER="dns01" - ISSUER_NAME="letsencrypt-prod" - ;; - http01) - SOLVER="http01" - ISSUER_NAME="letsencrypt-prod" - ;; - "") - # Field not set; omit from Package so chart defaults apply - ;; - *) - # Unrecognised value — treat as custom ClusterIssuer name with no solver override - ISSUER_NAME="$OLD_CLUSTER_ISSUER" - ;; -esac - -# Build certificates YAML block (empty string when no override needed) -if [ -n "$SOLVER" ] || [ -n "$ISSUER_NAME" ]; then - CERTIFICATES_SECTION=" certificates: - solver: \"${SOLVER}\" - issuerName: \"${ISSUER_NAME}\"" -else - CERTIFICATES_SECTION="" -fi # Network configuration POD_CIDR=$(echo "$COZYSTACK_CM" | jq -r '.data["ipv4-pod-cidr"] // "10.244.0.0/16"') @@ -151,38 +66,35 @@ else EXTERNAL_IPS=$(echo "$EXTERNAL_IPS" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - "$0}') fi -# Convert comma-separated lists to YAML arrays -if [ -z "$BUNDLE_DISABLE" ]; then - DISABLED_PACKAGES="[]" -else - DISABLED_PACKAGES=$(echo "$BUNDLE_DISABLE" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - cozystack."$0}') -fi - -if [ -z "$BUNDLE_ENABLE" ]; then - ENABLED_PACKAGES="[]" -else - ENABLED_PACKAGES=$(echo "$BUNDLE_ENABLE" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - cozystack."$0}') -fi - -if [ -z "$EXPOSE_SERVICES" ]; then - EXPOSED_SERVICES_YAML="[]" -else - EXPOSED_SERVICES_YAML=$(echo "$EXPOSE_SERVICES" | sed 's/,/\n/g' | awk 'BEGIN{print}{print " - "$0}') -fi +# Determine bundle type +case "$BUNDLE_NAME" in + paas-full|distro-full) + SYSTEM_ENABLED="true" + SYSTEM_TYPE="full" + ;; + paas-hosted|distro-hosted) + SYSTEM_ENABLED="false" + SYSTEM_TYPE="hosted" + ;; + *) + SYSTEM_ENABLED="false" + SYSTEM_TYPE="hosted" + ;; +esac # Update bundle naming BUNDLE_NAME=$(echo "$BUNDLE_NAME" | sed 's/paas/isp/') # Extract branding if available BRANDING=$(echo "$BRANDING_CM" | jq -r '.data // {} | to_entries[] | "\(.key): \"\(.value)\""') -if [ -z "$BRANDING" ]; then +if [ -z "$BRANDING" ]; then BRANDING="{}" else BRANDING=$(echo "$BRANDING" | awk 'BEGIN{print}{print " " $0}') fi # Extract scheduling if available -SCHEDULING_CONSTRAINTS=$(echo "$SCHEDULING_CM" | jq -r '.data["globalAppTopologySpreadConstraints"] // ""') +SCHEDULING_CONSTRAINTS=$(echo "$SCHEDULING_CM" | jq -r '.data.["globalAppTopologySpreadConstraints"] // ""') if [ -z "$SCHEDULING_CONSTRAINTS" ]; then SCHEDULING_CONSTRAINTS='""' else @@ -196,8 +108,8 @@ echo " Root Host: $ROOT_HOST" echo " API Server Endpoint: $API_SERVER_ENDPOINT" echo " OIDC Enabled: $OIDC_ENABLED" echo " Bundle Name: $BUNDLE_NAME" -echo " Certificate Solver: ${SOLVER:-http01 (default)}" -echo " Issuer Name: ${ISSUER_NAME:-letsencrypt-prod (default)}" +echo " System Enabled: $SYSTEM_ENABLED" +echo " System Type: $SYSTEM_TYPE" echo "" # Generate Package YAML @@ -213,8 +125,15 @@ spec: platform: values: bundles: - disabledPackages: $DISABLED_PACKAGES - enabledPackages: $ENABLED_PACKAGES + system: + enabled: $SYSTEM_ENABLED + type: "$SYSTEM_TYPE" + iaas: + enabled: true + paas: + enabled: true + naas: + enabled: true networking: clusterDomain: "$CLUSTER_DOMAIN" podCIDR: "$POD_CIDR" @@ -223,11 +142,8 @@ spec: joinCIDR: "$JOIN_CIDR" publishing: host: "$ROOT_HOST" - ingressName: "$EXPOSE_INGRESS" - exposedServices: $EXPOSED_SERVICES_YAML apiServerEndpoint: "$API_SERVER_ENDPOINT" externalIPs: $EXTERNAL_IPS -${CERTIFICATES_SECTION} authentication: oidc: enabled: $OIDC_ENABLED diff --git a/hack/remediation-guard.bats b/hack/remediation-guard.bats deleted file mode 100644 index 092fe06d..00000000 --- a/hack/remediation-guard.bats +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bats -# ----------------------------------------------------------------------------- -# Unit tests for hack/e2e-apps/remediation-guard.sh -# -# helmrelease_has_remediation_cycle takes a newline-delimited list of -# HelmRelease history snapshot status values (deployed/superseded/failed/ -# uninstalled/...) and returns 0 when any entry is "failed" or "uninstalled" -# (meaning flux helm-controller performed install/upgrade remediation). -# -# This is used by the e2e script after the HelmRelease reaches Ready. The -# failure/upgrade counters (.status.installFailures / .status.upgradeFailures) -# are useless there because flux's ClearFailures zeroes them on successful -# reconciliation; .status.history retains the snapshot trail. -# -# cozytest.sh's awk parser recognizes only @test blocks and a bare `}` on -# its own line; there is no bats `run` or `$status`. Assertions are -# expressed as direct shell tests that exit non-zero on failure. -# -# Run with: hack/cozytest.sh hack/remediation-guard.bats -# ----------------------------------------------------------------------------- - -@test "empty history returns not-detected" { - . hack/e2e-apps/remediation-guard.sh - if helmrelease_has_remediation_cycle ""; then - echo "expected not-detected for empty history" >&2 - exit 1 - fi -} - -@test "single deployed snapshot returns not-detected" { - . hack/e2e-apps/remediation-guard.sh - if helmrelease_has_remediation_cycle "deployed"; then - echo "expected not-detected for deployed-only history" >&2 - exit 1 - fi -} - -@test "deployed then superseded returns not-detected" { - . hack/e2e-apps/remediation-guard.sh - statuses=$(printf 'deployed\nsuperseded\n') - if helmrelease_has_remediation_cycle "${statuses}"; then - echo "expected not-detected for deployed+superseded history" >&2 - exit 1 - fi -} - -@test "single failed snapshot returns detected" { - . hack/e2e-apps/remediation-guard.sh - if ! helmrelease_has_remediation_cycle "failed"; then - echo "expected detected when history contains failed snapshot" >&2 - exit 1 - fi -} - -@test "single uninstalled snapshot returns detected" { - # The exact signature of the install-remediation race: the first install - # exceeded flux's wait budget, remediation uninstalled, the next retry - # eventually succeeded. History still carries the uninstalled snapshot. - . hack/e2e-apps/remediation-guard.sh - if ! helmrelease_has_remediation_cycle "uninstalled"; then - echo "expected detected when history contains uninstalled snapshot" >&2 - exit 1 - fi -} - -@test "uninstalled then deployed still returns detected" { - . hack/e2e-apps/remediation-guard.sh - statuses=$(printf 'uninstalled\ndeployed\n') - if ! helmrelease_has_remediation_cycle "${statuses}"; then - echo "expected detected despite later successful deploy" >&2 - exit 1 - fi -} - -@test "deployed then failed still returns detected" { - . hack/e2e-apps/remediation-guard.sh - statuses=$(printf 'deployed\nfailed\n') - if ! helmrelease_has_remediation_cycle "${statuses}"; then - echo "expected detected when any entry is failed" >&2 - exit 1 - fi -} - -@test "status.history extraction pins HR v2 status.history shape" { - # Pins the Flux HelmRelease v2 .status.history[].status shape that - # run-kubernetes.sh relies on. If a future flux release renames the - # field, the jsonpath returns nothing, the guard reports no cycle, - # and real remediation loops slip past the e2e assertion. This test - # uses yq to read the exact path used in the e2e script; the upstream - # Snapshot type lives at - # github.com/fluxcd/helm-controller/api/v2.Snapshot (via go.mod). - tmp=$(mktemp -d) - trap 'rm -rf "$tmp"' EXIT - - cat > "$tmp/hr.yaml" <<'YAML' -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: kubernetes-test - namespace: tenant-test -status: - history: - - name: kubernetes-test - namespace: tenant-test - version: 1 - status: uninstalled - - name: kubernetes-test - namespace: tenant-test - version: 2 - status: deployed -YAML - - # Default yq output is yaml scalar format, which for string values emits - # bare unquoted tokens - matching what kubectl -o jsonpath produces in - # e2e. Do not switch to JSON output here; that would quote the values - # and break the loop in helmrelease_has_remediation_cycle. - statuses=$(yq '.status.history[].status' "$tmp/hr.yaml") - - [ -n "$statuses" ] - echo "$statuses" | grep --quiet '^uninstalled$' - - . hack/e2e-apps/remediation-guard.sh - if ! helmrelease_has_remediation_cycle "$statuses"; then - echo "expected detected for pinned HR snippet with uninstalled + deployed history" >&2 - exit 1 - fi -} diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index f3a47e78..4023db3c 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -19,22 +19,21 @@ set -o nounset set -o pipefail SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. -CODEGEN_PKG=${CODEGEN_PKG:-~/go/pkg/mod/k8s.io/code-generator@v0.34.1} +CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} API_KNOWN_VIOLATIONS_DIR="${API_KNOWN_VIOLATIONS_DIR:-"${SCRIPT_ROOT}/api/api-rules"}" UPDATE_API_KNOWN_VIOLATIONS="${UPDATE_API_KNOWN_VIOLATIONS:-true}" CONTROLLER_GEN="go run sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.4" TMPDIR=$(mktemp -d) -OPERATOR_CRDDIR=internal/crdinstall/manifests +OPERATOR_CRDDIR=packages/core/installer/definitions COZY_CONTROLLER_CRDDIR=packages/system/cozystack-controller/definitions COZY_RD_CRDDIR=packages/system/application-definition-crd/definition BACKUPS_CORE_CRDDIR=packages/system/backup-controller/definitions -BACKUPSTRATEGY_CRDDIR=packages/system/backupstrategy-controller/definitions trap 'rm -rf ${TMPDIR}' EXIT source "${CODEGEN_PKG}/kube_codegen.sh" -THIS_PKG="github.com/cozystack/cozystack" +THIS_PKG="k8s.io/sample-apiserver" kube::codegen::gen_helpers \ --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ @@ -60,15 +59,8 @@ kube::codegen::gen_openapi \ --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ "${SCRIPT_ROOT}/pkg/apis" -kube::codegen::gen_client \ - --with-applyconfig \ - --output-dir "${SCRIPT_ROOT}/pkg/generated" \ - --output-pkg "${THIS_PKG}/pkg/generated" \ - --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ - "${SCRIPT_ROOT}/pkg/apis" - $CONTROLLER_GEN object:headerFile="hack/boilerplate.go.txt" paths="./api/..." -$CONTROLLER_GEN rbac:roleName=manager-role crd paths="./api/v1alpha1/..." paths="./api/backups/..." paths="./api/dashboard/..." output:crd:artifacts:config=${TMPDIR} +$CONTROLLER_GEN rbac:roleName=manager-role crd paths="./api/..." output:crd:artifacts:config=${TMPDIR} mv ${TMPDIR}/cozystack.io_packages.yaml ${OPERATOR_CRDDIR}/cozystack.io_packages.yaml mv ${TMPDIR}/cozystack.io_packagesources.yaml ${OPERATOR_CRDDIR}/cozystack.io_packagesources.yaml @@ -77,15 +69,6 @@ mv ${TMPDIR}/cozystack.io_applicationdefinitions.yaml \ ${COZY_RD_CRDDIR}/cozystack.io_applicationdefinitions.yaml mv ${TMPDIR}/backups.cozystack.io*.yaml ${BACKUPS_CORE_CRDDIR}/ -mv ${TMPDIR}/strategy.backups.cozystack.io*.yaml ${BACKUPSTRATEGY_CRDDIR}/ +mv ${TMPDIR}/strategy.backups.cozystack.io*.yaml ${BACKUPS_CORE_CRDDIR}/ mv ${TMPDIR}/*.yaml ${COZY_CONTROLLER_CRDDIR}/ - -# Tidy dependencies for standalone api/apps/v1alpha1 submodule -(cd "${SCRIPT_ROOT}/api/apps/v1alpha1" && go mod tidy) - -# Generate deepcopy for standalone api/apps/v1alpha1 submodule (separate Go module) -# Use absolute path for headerFile since we cd into the submodule directory -APPS_API_ROOT="$(cd "${SCRIPT_ROOT}" && pwd)" -(cd "${APPS_API_ROOT}/api/apps/v1alpha1" && $CONTROLLER_GEN object:headerFile="${APPS_API_ROOT}/hack/boilerplate.go.txt" paths="./...") - diff --git a/hack/upload-assets.sh b/hack/upload-assets.sh index 2f7f9813..e846261c 100755 --- a/hack/upload-assets.sh +++ b/hack/upload-assets.sh @@ -4,7 +4,7 @@ set -xe version=${VERSION:-$(git describe --tags)} gh release upload --clobber $version _out/assets/cozystack-crds.yaml -gh release upload --clobber $version _out/assets/cozystack-operator-talos.yaml +gh release upload --clobber $version _out/assets/cozystack-operator.yaml gh release upload --clobber $version _out/assets/cozystack-operator-generic.yaml gh release upload --clobber $version _out/assets/cozystack-operator-hosted.yaml gh release upload --clobber $version _out/assets/metal-amd64.iso @@ -14,4 +14,3 @@ gh release upload --clobber $version _out/assets/kernel-amd64 gh release upload --clobber $version _out/assets/initramfs-metal-amd64.xz gh release upload --clobber $version _out/assets/cozypkg-*.tar.gz gh release upload --clobber $version _out/assets/cozypkg-checksums.txt -gh release upload --clobber $version _out/assets/openapi.json diff --git a/internal/backupcontroller/backup_controller.go b/internal/backupcontroller/backup_controller.go deleted file mode 100644 index 486a24ae..00000000 --- a/internal/backupcontroller/backup_controller.go +++ /dev/null @@ -1,136 +0,0 @@ -package backupcontroller - -import ( - "context" - "fmt" - - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/record" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/log" - - backupsv1alpha1 "github.com/cozystack/cozystack/api/backups/v1alpha1" - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" -) - -const backupFinalizer = "backups.cozystack.io/cleanup-velero" - -// BackupReconciler reconciles Backup objects. -// It manages a finalizer that ensures the underlying Velero backup is deleted -// when the cozystack Backup resource is deleted. -type BackupReconciler struct { - client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder -} - -func (r *BackupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - logger.V(1).Info("reconciling Backup", "namespace", req.Namespace, "name", req.Name) - - backup := &backupsv1alpha1.Backup{} - if err := r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: req.Name}, backup); err != nil { - if apierrors.IsNotFound(err) { - return ctrl.Result{}, nil - } - return ctrl.Result{}, err - } - - // Handle deletion: clean up Velero backup - if !backup.DeletionTimestamp.IsZero() { - if controllerutil.ContainsFinalizer(backup, backupFinalizer) { - if err := r.cleanupVeleroBackup(ctx, backup); err != nil { - logger.Error(err, "failed to clean up Velero backup") - return ctrl.Result{}, err - } - - controllerutil.RemoveFinalizer(backup, backupFinalizer) - if err := r.Update(ctx, backup); err != nil { - return ctrl.Result{}, err - } - logger.V(1).Info("removed finalizer and cleaned up Velero backup", "backup", backup.Name) - } - return ctrl.Result{}, nil - } - - // Ensure finalizer is present - if !controllerutil.ContainsFinalizer(backup, backupFinalizer) { - controllerutil.AddFinalizer(backup, backupFinalizer) - if err := r.Update(ctx, backup); err != nil { - return ctrl.Result{}, err - } - logger.V(1).Info("added finalizer to Backup", "backup", backup.Name) - } - - return ctrl.Result{}, nil -} - -// cleanupVeleroBackup deletes the Velero backup and its data from storage -// by creating a Velero DeleteBackupRequest. A direct Delete of the -// backup.velero.io resource only removes the Kubernetes object; Velero's -// BSL sync will recreate it from the object store. The DeleteBackupRequest -// tells Velero to also purge the data, preventing resurrection. -func (r *BackupReconciler) cleanupVeleroBackup(ctx context.Context, backup *backupsv1alpha1.Backup) error { - logger := log.FromContext(ctx) - - veleroBackupName, ok := backup.Spec.DriverMetadata[veleroBackupNameMetadataKey] - if !ok || veleroBackupName == "" { - logger.V(1).Info("no Velero backup name in driverMetadata, nothing to clean up") - return nil - } - - veleroBackupNamespace := backup.Spec.DriverMetadata[veleroBackupNamespaceMetadataKey] - if veleroBackupNamespace == "" { - veleroBackupNamespace = veleroNamespace - } - - // Check if the Velero Backup still exists - veleroBackup := &velerov1.Backup{} - err := r.Get(ctx, types.NamespacedName{ - Namespace: veleroBackupNamespace, - Name: veleroBackupName, - }, veleroBackup) - if err != nil { - if apierrors.IsNotFound(err) { - logger.V(1).Info("Velero backup already deleted", "name", veleroBackupName) - return nil - } - return fmt.Errorf("failed to get Velero backup %s/%s: %w", veleroBackupNamespace, veleroBackupName, err) - } - - // Create a DeleteBackupRequest so Velero removes backup data from storage. - // Without this, BSL sync will recreate the backup.velero.io resource. - dbr := &velerov1.DeleteBackupRequest{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: veleroBackupName + "-", - Namespace: veleroBackupNamespace, - }, - Spec: velerov1.DeleteBackupRequestSpec{ - BackupName: veleroBackupName, - }, - } - if err := r.Create(ctx, dbr); err != nil { - if apierrors.IsAlreadyExists(err) { - logger.V(1).Info("DeleteBackupRequest already exists", "backup", veleroBackupName) - return nil - } - return fmt.Errorf("failed to create DeleteBackupRequest for %s/%s: %w", veleroBackupNamespace, veleroBackupName, err) - } - - logger.Info("created DeleteBackupRequest for Velero backup", - "name", veleroBackupName, "namespace", veleroBackupNamespace, - "deleteRequest", dbr.Name) - return nil -} - -// SetupWithManager registers the BackupReconciler with the Manager. -func (r *BackupReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&backupsv1alpha1.Backup{}). - Complete(r) -} diff --git a/internal/backupcontroller/backupclass_resolver_test.go b/internal/backupcontroller/backupclass_resolver_test.go index cd65f22a..a606f241 100644 --- a/internal/backupcontroller/backupclass_resolver_test.go +++ b/internal/backupcontroller/backupclass_resolver_test.go @@ -141,13 +141,13 @@ func TestResolveBackupClass(t *testing.T) { StrategyRef: corev1.TypedLocalObjectReference{ APIGroup: stringPtr("strategy.backups.cozystack.io"), Kind: "Velero", - Name: "velero-strategy-mariadb", + Name: "velero-strategy-mysql", }, Application: backupsv1alpha1.ApplicationSelector{ - Kind: "MariaDB", + Kind: "MySQL", }, Parameters: map[string]string{ - "backupStorageLocationName": "mariadb-storage", + "backupStorageLocationName": "mysql-storage", }, }, }, @@ -169,7 +169,7 @@ func TestResolveBackupClass(t *testing.T) { }, }, { - name: "successful resolution - matches MariaDB strategy with explicit apiGroup", + name: "successful resolution - matches MySQL strategy with explicit apiGroup", backupClass: &backupsv1alpha1.BackupClass{ ObjectMeta: metav1.ObjectMeta{ Name: "velero", @@ -180,14 +180,14 @@ func TestResolveBackupClass(t *testing.T) { StrategyRef: corev1.TypedLocalObjectReference{ APIGroup: stringPtr("strategy.backups.cozystack.io"), Kind: "Velero", - Name: "velero-strategy-mariadb", + Name: "velero-strategy-mysql", }, Application: backupsv1alpha1.ApplicationSelector{ APIGroup: stringPtr("apps.cozystack.io"), - Kind: "MariaDB", + Kind: "MySQL", }, Parameters: map[string]string{ - "backupStorageLocationName": "mariadb-storage", + "backupStorageLocationName": "mysql-storage", }, }, }, @@ -195,18 +195,18 @@ func TestResolveBackupClass(t *testing.T) { }, applicationRef: corev1.TypedLocalObjectReference{ APIGroup: stringPtr("apps.cozystack.io"), - Kind: "MariaDB", - Name: "mariadb1", + Kind: "MySQL", + Name: "mysql1", }, backupClassName: "velero", wantErr: false, expectedStrategyRef: &corev1.TypedLocalObjectReference{ APIGroup: stringPtr("strategy.backups.cozystack.io"), Kind: "Velero", - Name: "velero-strategy-mariadb", + Name: "velero-strategy-mysql", }, expectedParams: map[string]string{ - "backupStorageLocationName": "mariadb-storage", + "backupStorageLocationName": "mysql-storage", }, }, { @@ -369,3 +369,7 @@ func TestResolveBackupClass(t *testing.T) { }) } } + +func stringPtr(s string) *string { + return &s +} diff --git a/internal/backupcontroller/backupjob_controller.go b/internal/backupcontroller/backupjob_controller.go index b926722f..58294972 100644 --- a/internal/backupcontroller/backupjob_controller.go +++ b/internal/backupcontroller/backupjob_controller.go @@ -6,7 +6,6 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/dynamic" @@ -21,8 +20,8 @@ import ( backupsv1alpha1 "github.com/cozystack/cozystack/api/backups/v1alpha1" ) -// BackupJobReconciler reconciles BackupJob with a strategy from the -// strategy.backups.cozystack.io API group. +// BackupVeleroStrategyReconciler reconciles BackupJob with a strategy referencing +// Velero.strategy.backups.cozystack.io objects. type BackupJobReconciler struct { client.Client dynamic.Interface @@ -116,27 +115,3 @@ func (r *BackupJobReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&backupsv1alpha1.BackupJob{}). Complete(r) } - -func (r *BackupJobReconciler) markBackupJobFailed(ctx context.Context, backupJob *backupsv1alpha1.BackupJob, message string) (ctrl.Result, error) { - logger := getLogger(ctx) - now := metav1.Now() - backupJob.Status.CompletedAt = &now - backupJob.Status.Phase = backupsv1alpha1.BackupJobPhaseFailed - backupJob.Status.Message = message - - // Add condition - backupJob.Status.Conditions = append(backupJob.Status.Conditions, metav1.Condition{ - Type: "Ready", - Status: metav1.ConditionFalse, - Reason: "BackupFailed", - Message: message, - LastTransitionTime: now, - }) - - if err := r.Status().Update(ctx, backupJob); err != nil { - logger.Error(err, "failed to update BackupJob status to Failed") - return ctrl.Result{}, err - } - logger.Debug("BackupJob failed", "message", message) - return ctrl.Result{}, nil -} diff --git a/internal/backupcontroller/factory/backupjob_test.go b/internal/backupcontroller/factory/backupjob_test.go index afe1f155..2fab5ff8 100644 --- a/internal/backupcontroller/factory/backupjob_test.go +++ b/internal/backupcontroller/factory/backupjob_test.go @@ -67,8 +67,8 @@ func TestBackupJob(t *testing.T) { Spec: backupsv1alpha1.PlanSpec{ ApplicationRef: corev1.TypedLocalObjectReference{ // No APIGroup specified - Kind: "MariaDB", - Name: "mariadb1", + Kind: "MySQL", + Name: "mysql1", }, BackupClassName: "velero", Schedule: backupsv1alpha1.PlanSchedule{ diff --git a/internal/backupcontroller/jobstrategy_controller.go b/internal/backupcontroller/jobstrategy_controller.go index aaa54c19..04b814dd 100644 --- a/internal/backupcontroller/jobstrategy_controller.go +++ b/internal/backupcontroller/jobstrategy_controller.go @@ -14,8 +14,3 @@ func (r *BackupJobReconciler) reconcileJob(ctx context.Context, j *backupsv1alph _ = resolved // Use resolved BackupClass parameters when implementing your job strategy return ctrl.Result{}, nil } - -func (r *RestoreJobReconciler) reconcileJobRestore(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, backup *backupsv1alpha1.Backup) (ctrl.Result, error) { - _ = log.FromContext(ctx) - return ctrl.Result{}, nil -} diff --git a/internal/backupcontroller/restorejob_controller.go b/internal/backupcontroller/restorejob_controller.go deleted file mode 100644 index f0062064..00000000 --- a/internal/backupcontroller/restorejob_controller.go +++ /dev/null @@ -1,194 +0,0 @@ -package backupcontroller - -import ( - "context" - "fmt" - "net/http" - - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/log" - - strategyv1alpha1 "github.com/cozystack/cozystack/api/backups/strategy/v1alpha1" - backupsv1alpha1 "github.com/cozystack/cozystack/api/backups/v1alpha1" - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" -) - -const restoreJobFinalizer = "backups.cozystack.io/cleanup-velero-restore" - -// RestoreJobReconciler reconciles RestoreJob objects. -// It routes RestoreJobs to strategy-specific handlers based on the strategy -// referenced in the Backup that the RestoreJob is restoring from. -type RestoreJobReconciler struct { - client.Client - dynamic.Interface - meta.RESTMapper - Scheme *runtime.Scheme - Recorder record.EventRecorder -} - -func (r *RestoreJobReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - logger.Info("reconciling RestoreJob", "namespace", req.Namespace, "name", req.Name) - - restoreJob := &backupsv1alpha1.RestoreJob{} - err := r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: req.Name}, restoreJob) - if err != nil { - if apierrors.IsNotFound(err) { - logger.V(1).Info("RestoreJob not found, skipping") - return ctrl.Result{}, nil - } - logger.Error(err, "failed to get RestoreJob") - return ctrl.Result{}, err - } - - // Handle deletion: clean up Velero Restore - if !restoreJob.DeletionTimestamp.IsZero() { - if controllerutil.ContainsFinalizer(restoreJob, restoreJobFinalizer) { - r.cleanupVeleroRestore(ctx, restoreJob) - controllerutil.RemoveFinalizer(restoreJob, restoreJobFinalizer) - if err := r.Update(ctx, restoreJob); err != nil { - return ctrl.Result{}, err - } - logger.V(1).Info("removed finalizer and cleaned up Velero Restore", "restoreJob", restoreJob.Name) - } - return ctrl.Result{}, nil - } - - // Ensure finalizer is present - if !controllerutil.ContainsFinalizer(restoreJob, restoreJobFinalizer) { - controllerutil.AddFinalizer(restoreJob, restoreJobFinalizer) - if err := r.Update(ctx, restoreJob); err != nil { - return ctrl.Result{}, err - } - } - - // If already completed, no need to reconcile - if restoreJob.Status.Phase == backupsv1alpha1.RestoreJobPhaseSucceeded || - restoreJob.Status.Phase == backupsv1alpha1.RestoreJobPhaseFailed { - logger.V(1).Info("RestoreJob already completed, skipping", "phase", restoreJob.Status.Phase) - return ctrl.Result{}, nil - } - - // Step 1: Fetch the referenced Backup - backup := &backupsv1alpha1.Backup{} - backupKey := types.NamespacedName{Namespace: req.Namespace, Name: restoreJob.Spec.BackupRef.Name} - if err := r.Get(ctx, backupKey, backup); err != nil { - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("failed to get Backup: %v", err)) - } - - // Step 2: Determine effective strategy from backup.spec.strategyRef - if backup.Spec.StrategyRef.APIGroup == nil { - return r.markRestoreJobFailed(ctx, restoreJob, "Backup has nil StrategyRef.APIGroup") - } - - if *backup.Spec.StrategyRef.APIGroup != strategyv1alpha1.GroupVersion.Group { - return r.markRestoreJobFailed(ctx, restoreJob, - fmt.Sprintf("StrategyRef.APIGroup doesn't match: %s", *backup.Spec.StrategyRef.APIGroup)) - } - - logger.Info("processing RestoreJob", "restorejob", restoreJob.Name, "backup", backup.Name, "strategyKind", backup.Spec.StrategyRef.Kind) - switch backup.Spec.StrategyRef.Kind { - case strategyv1alpha1.JobStrategyKind: - return r.reconcileJobRestore(ctx, restoreJob, backup) - case strategyv1alpha1.VeleroStrategyKind: - return r.reconcileVeleroRestore(ctx, restoreJob, backup) - default: - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("StrategyRef.Kind not supported: %s", backup.Spec.StrategyRef.Kind)) - } -} - -// SetupWithManager registers our controller with the Manager and sets up watches. -func (r *RestoreJobReconciler) SetupWithManager(mgr ctrl.Manager) error { - cfg := mgr.GetConfig() - var err error - if r.Interface, err = dynamic.NewForConfig(cfg); err != nil { - return err - } - var h *http.Client - if h, err = rest.HTTPClientFor(cfg); err != nil { - return err - } - if r.RESTMapper, err = apiutil.NewDynamicRESTMapper(cfg, h); err != nil { - return err - } - return ctrl.NewControllerManagedBy(mgr). - For(&backupsv1alpha1.RestoreJob{}). - Complete(r) -} - -// markRestoreJobFailed updates the RestoreJob status to Failed with the given message. -func (r *RestoreJobReconciler) markRestoreJobFailed(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, message string) (ctrl.Result, error) { - logger := getLogger(ctx) - now := metav1.Now() - restoreJob.Status.CompletedAt = &now - restoreJob.Status.Phase = backupsv1alpha1.RestoreJobPhaseFailed - restoreJob.Status.Message = message - - // Add condition - restoreJob.Status.Conditions = append(restoreJob.Status.Conditions, metav1.Condition{ - Type: "Ready", - Status: metav1.ConditionFalse, - Reason: "RestoreFailed", - Message: message, - LastTransitionTime: now, - }) - - if err := r.Status().Update(ctx, restoreJob); err != nil { - logger.Error(err, "failed to update RestoreJob status to Failed") - return ctrl.Result{}, err - } - logger.Debug("RestoreJob failed", "message", message) - return ctrl.Result{}, nil -} - -// cleanupResourceModifierConfigMaps deletes resource modifier ConfigMaps owned -// by this RestoreJob. Called on completion (success or failure) to avoid leaking -// ConfigMaps in cozy-velero when RestoreJobs are not immediately deleted. -func (r *RestoreJobReconciler) cleanupResourceModifierConfigMaps(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob) { - logger := log.FromContext(ctx) - opts := []client.DeleteAllOfOption{ - client.InNamespace(veleroNamespace), - client.MatchingLabels{ - backupsv1alpha1.OwningJobNameLabel: restoreJob.Name, - backupsv1alpha1.OwningJobNamespaceLabel: restoreJob.Namespace, - }, - } - if err := r.DeleteAllOf(ctx, &corev1.ConfigMap{}, opts...); err != nil { - logger.Error(err, "failed to clean up resourceModifiers ConfigMap(s)") - } -} - -// cleanupVeleroRestore deletes all Velero Restores and resourceModifier -// ConfigMaps owned by this RestoreJob (identified by labels). -func (r *RestoreJobReconciler) cleanupVeleroRestore(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob) { - logger := log.FromContext(ctx) - opts := []client.DeleteAllOfOption{ - client.InNamespace(veleroNamespace), - client.MatchingLabels{ - backupsv1alpha1.OwningJobNameLabel: restoreJob.Name, - backupsv1alpha1.OwningJobNamespaceLabel: restoreJob.Namespace, - }, - } - - if err := r.DeleteAllOf(ctx, &velerov1.Restore{}, opts...); err != nil { - logger.Error(err, "failed to delete Velero Restore(s)") - r.Recorder.Event(restoreJob, corev1.EventTypeWarning, "CleanupFailed", - fmt.Sprintf("Failed to delete Velero Restore: %v", err)) - } - - if err := r.DeleteAllOf(ctx, &corev1.ConfigMap{}, opts...); err != nil { - logger.Error(err, "failed to delete resourceModifiers ConfigMap(s)") - } -} diff --git a/internal/backupcontroller/velerostrategy_controller.go b/internal/backupcontroller/velerostrategy_controller.go index 8b063519..0986d648 100644 --- a/internal/backupcontroller/velerostrategy_controller.go +++ b/internal/backupcontroller/velerostrategy_controller.go @@ -2,21 +2,13 @@ package backupcontroller import ( "context" - "crypto/sha256" - "encoding/hex" - "encoding/json" "fmt" - "strings" "time" - "sigs.k8s.io/yaml" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -45,172 +37,27 @@ func (l loggerWithDebug) Debug(msg string, keysAndValues ...interface{}) { l.Logger.V(1).Info(msg, keysAndValues...) } +// S3Credentials holds the discovered S3 credentials from a Bucket storageRef +type S3Credentials struct { + BucketName string + Endpoint string + Region string + AccessKeyID string + AccessSecretKey string +} + const ( - defaultRequeueAfter = 5 * time.Second - defaultActiveJobPollingInterval = defaultRequeueAfter - defaultRestoreRequeueAfter = 5 * time.Second - defaultActiveRestorePollingInterval = defaultRestoreRequeueAfter + defaultRequeueAfter = 5 * time.Second + defaultActiveJobPollingInterval = defaultRequeueAfter // Velero requires API objects and secrets to be in the cozy-velero namespace - veleroNamespace = "cozy-velero" - veleroBackupNameMetadataKey = "velero.io/backup-name" - veleroBackupNamespaceMetadataKey = "velero.io/backup-namespace" - - // Annotation key for persisting underlying resources on the Velero Backup object - underlyingResourcesAnnotation = "backups.cozystack.io/underlying-resources" - - // VM-specific constants - vmInstanceKind = "VMInstance" - vmDiskAppKind = "VMDisk" - vmNamePrefix = "vm-instance-" - vmDiskNamePrefix = "vm-disk-" - appKindLabel = "apps.cozystack.io/application.kind" - appNameLabel = "apps.cozystack.io/application.name" - vmPodNameLabel = "vm.kubevirt.io/name" - ovnIPAnnotation = "ovn.kubernetes.io/ip_address" - ovnMACAnnotation = "ovn.kubernetes.io/mac_address" - cdiAllowClaimAdoption = "cdi.kubevirt.io/allowClaimAdoption" + veleroNamespace = "cozy-velero" + virtualMachinePrefix = "virtual-machine-" ) -func stringPtr(s string) *string { - return &s -} - -// boolPtr returns a pointer to a bool value. func boolPtr(b bool) *bool { return &b } -// boolDefault returns the value of a *bool pointer, or the given default if nil. -func boolDefault(p *bool, def bool) bool { - if p != nil { - return *p - } - return def -} - -// CommonRestoreOptions contains driver-agnostic restore options shared across -// all application kinds. -type CommonRestoreOptions struct { - // TargetNamespace is the namespace to restore into. When set (and differs - // from the backup namespace), a cross-namespace restore (copy) is performed - // using Velero's namespaceMapping. - TargetNamespace string `json:"targetNamespace,omitempty"` - // FailIfTargetExists makes the restore fail if the target resource already - // exists. Defaults to true when omitted. - FailIfTargetExists *bool `json:"failIfTargetExists,omitempty"` -} - -// RestoreOptions is the typed representation of RestoreJob.Spec.Options for the -// Velero driver. The struct is deserialized from runtime.RawExtension and used -// for all application kinds. VMInstance-specific fields (KeepOriginalPVC, -// KeepOriginalIpAndMac) are only effective when the application kind is VMInstance. -type RestoreOptions struct { - CommonRestoreOptions `json:",inline"` - // KeepOriginalPVC renames the original PVC to -orig- before restore. - // Only effective for in-place VMInstance restore (no targetNamespace). Defaults to true when omitted. - KeepOriginalPVC *bool `json:"keepOriginalPVC,omitempty"` - // KeepOriginalIpAndMac preserves the original IP and MAC address via OVN - // annotations. Only effective for VMInstance restores. Defaults to true when omitted. - KeepOriginalIpAndMac *bool `json:"keepOriginalIpAndMac,omitempty"` -} - -// GetFailIfTargetExists returns the effective value (default: true). -func (o *CommonRestoreOptions) GetFailIfTargetExists() bool { - return boolDefault(o.FailIfTargetExists, true) -} - -// GetKeepOriginalPVC returns the effective value (default: true). -func (o *RestoreOptions) GetKeepOriginalPVC() bool { - return boolDefault(o.KeepOriginalPVC, true) -} - -// GetKeepOriginalIpAndMac returns the effective value (default: true). -func (o *RestoreOptions) GetKeepOriginalIpAndMac() bool { - return boolDefault(o.KeepOriginalIpAndMac, true) -} - -// parseRestoreOptions deserializes RestoreJob.Spec.Options into RestoreOptions. -// Returns zero-value RestoreOptions if options is nil. -func parseRestoreOptions(opts *runtime.RawExtension) (RestoreOptions, error) { - var ro RestoreOptions - if opts == nil || len(opts.Raw) == 0 { - return ro, nil - } - if err := json.Unmarshal(opts.Raw, &ro); err != nil { - return ro, fmt.Errorf("failed to parse restore options: %w", err) - } - return ro, nil -} - -// restoreTarget holds the resolved target namespace and app identity for a restore operation. -type restoreTarget struct { - Namespace string - AppName string - AppKind string - IsCopy bool // true when targetNamespace differs from backup namespace - IsRenamed bool // true when target app name differs from source app name -} - -// resolveRestoreTarget computes the effective restore target from RestoreJob, Backup, and options. -func resolveRestoreTarget(restoreJob *backupsv1alpha1.RestoreJob, backup *backupsv1alpha1.Backup, opts RestoreOptions) restoreTarget { - targetNS := backup.Namespace - isCopy := false - if opts.TargetNamespace != "" && opts.TargetNamespace != backup.Namespace { - targetNS = opts.TargetNamespace - isCopy = true - } - targetAppName := backup.Spec.ApplicationRef.Name - if restoreJob.Spec.TargetApplicationRef != nil && restoreJob.Spec.TargetApplicationRef.Name != "" { - targetAppName = restoreJob.Spec.TargetApplicationRef.Name - } - targetAppKind := backup.Spec.ApplicationRef.Kind - if restoreJob.Spec.TargetApplicationRef != nil && restoreJob.Spec.TargetApplicationRef.Kind != "" { - targetAppKind = restoreJob.Spec.TargetApplicationRef.Kind - } - return restoreTarget{ - Namespace: targetNS, - AppName: targetAppName, - AppKind: targetAppKind, - IsCopy: isCopy, - IsRenamed: targetAppName != backup.Spec.ApplicationRef.Name, - } -} - -// vmInstanceResources contains VM-specific underlying resources discovered during backup. -type vmInstanceResources struct { - DataVolumes []backupsv1alpha1.DataVolumeResource `json:"dataVolumes,omitempty"` - IP string `json:"ip,omitempty"` - MAC string `json:"mac,omitempty"` -} - -// marshalUnderlyingResources serializes application-specific data into a -// runtime.RawExtension suitable for Backup.Status.UnderlyingResources. -func marshalUnderlyingResources(data interface{}) (*runtime.RawExtension, error) { - raw, err := json.Marshal(data) - if err != nil { - return nil, err - } - return &runtime.RawExtension{Raw: raw}, nil -} - -// getVMInstanceResources extracts VMInstance-specific resources from the opaque blob. -// The caller is responsible for checking that the application kind is VMInstance -// (via backup.Spec.ApplicationRef.Kind) before calling this function. -// Returns nil if ur is nil or has no VM-specific data. -func getVMInstanceResources(ur *runtime.RawExtension) *vmInstanceResources { - if ur == nil || len(ur.Raw) == 0 { - return nil - } - var res vmInstanceResources - if err := json.Unmarshal(ur.Raw, &res); err != nil { - return nil - } - if len(res.DataVolumes) == 0 && res.IP == "" && res.MAC == "" { - return nil - } - return &res -} - func (r *BackupJobReconciler) reconcileVelero(ctx context.Context, j *backupsv1alpha1.BackupJob, resolved *ResolvedBackupConfig) (ctrl.Result, error) { logger := getLogger(ctx) logger.Debug("reconciling Velero strategy", "backupjob", j.Name, "phase", j.Status.Phase) @@ -253,6 +100,7 @@ func (r *BackupJobReconciler) reconcileVelero(ctx context.Context, j *backupsv1a // Step 3: Execute backup logic // Check if we already created a Velero Backup + // Use human-readable timestamp: YYYY-MM-DD-HH-MM-SS if j.Status.StartedAt == nil { logger.Error(nil, "StartedAt is nil after status update, this should not happen") return ctrl.Result{RequeueAfter: defaultRequeueAfter}, nil @@ -347,7 +195,10 @@ func (r *BackupJobReconciler) reconcileVelero(ctx context.Context, j *backupsv1a // Step 5: On failure if phase == "Failed" || phase == "PartiallyFailed" { - message := formatVeleroBackupFailureMessageForBackupJob(ctx, r.Client, veleroBackup) + message := fmt.Sprintf("Velero Backup failed with phase: %s", phase) + if len(veleroBackup.Status.ValidationErrors) > 0 { + message = fmt.Sprintf("%s: %v", message, veleroBackup.Status.ValidationErrors) + } return r.markBackupJobFailed(ctx, j, message) } @@ -355,74 +206,28 @@ func (r *BackupJobReconciler) reconcileVelero(ctx context.Context, j *backupsv1a return ctrl.Result{RequeueAfter: 5 * time.Second}, nil } -// collectUnderlyingResources discovers resources associated with an application -// that need to be backed up and restored. Returns a map keyed by application kind. -// Returns nil if the application type has no underlying resources to collect. -func (r *BackupJobReconciler) collectUnderlyingResources(ctx context.Context, app *unstructured.Unstructured, appKind, ns string) (*runtime.RawExtension, error) { +func (r *BackupJobReconciler) markBackupJobFailed(ctx context.Context, backupJob *backupsv1alpha1.BackupJob, message string) (ctrl.Result, error) { logger := getLogger(ctx) + now := metav1.Now() + backupJob.Status.CompletedAt = &now + backupJob.Status.Phase = backupsv1alpha1.BackupJobPhaseFailed + backupJob.Status.Message = message - if appKind != vmInstanceKind { - logger.Debug("application is not a VMInstance, skipping underlying resource collection", "kind", appKind) - return nil, nil - } - - appName := app.GetName() - - // Extract disk names from VMInstance spec.disks[].name - disks, found, err := unstructured.NestedSlice(app.Object, "spec", "disks") - if err != nil { - return nil, fmt.Errorf("failed to read spec.disks from application: %w", err) - } - - var dataVolumes []backupsv1alpha1.DataVolumeResource - if found { - for _, d := range disks { - disk, ok := d.(map[string]interface{}) - if !ok { - continue - } - name, ok := disk["name"].(string) - if !ok || name == "" { - continue - } - dataVolumes = append(dataVolumes, backupsv1alpha1.DataVolumeResource{ - DataVolumeName: vmDiskNamePrefix + name, - ApplicationName: name, - }) - } - } - logger.Debug("collected dataVolumes from VMInstance", "count", len(dataVolumes), "appName", appName) - - // Find VM Pod to extract OVN IP/MAC addresses - vmName := vmNamePrefix + appName - podList := &corev1.PodList{} - if err := r.List(ctx, podList, - client.InNamespace(ns), - client.MatchingLabels{vmPodNameLabel: vmName}, - ); err != nil { - logger.Error(err, "failed to list VM pods for IP/MAC collection", "vmName", vmName) - // Non-fatal: we can still proceed without IP/MAC - } - - var ip, mac string - if len(podList.Items) > 0 { - pod := podList.Items[0] - ip = pod.Annotations[ovnIPAnnotation] - mac = pod.Annotations[ovnMACAnnotation] - logger.Debug("collected OVN network info from VM pod", "ip", ip, "mac", mac, "pod", pod.Name) - } else { - logger.Debug("no VM pod found for OVN info", "vmName", vmName) - } - - if len(dataVolumes) == 0 && ip == "" && mac == "" { - return nil, nil - } - - return marshalUnderlyingResources(vmInstanceResources{ - DataVolumes: dataVolumes, - IP: ip, - MAC: mac, + // Add condition + backupJob.Status.Conditions = append(backupJob.Status.Conditions, metav1.Condition{ + Type: "Ready", + Status: metav1.ConditionFalse, + Reason: "BackupFailed", + Message: message, + LastTransitionTime: now, }) + + if err := r.Status().Update(ctx, backupJob); err != nil { + logger.Error(err, "failed to update BackupJob status to Failed") + return ctrl.Result{}, err + } + logger.Debug("BackupJob failed", "message", message) + return ctrl.Result{}, nil } func (r *BackupJobReconciler) createVeleroBackup(ctx context.Context, backupJob *backupsv1alpha1.BackupJob, strategy *strategyv1alpha1.Velero, resolved *ResolvedBackupConfig) error { @@ -442,13 +247,6 @@ func (r *BackupJobReconciler) createVeleroBackup(ctx context.Context, backupJob return err } - // Collect underlying resources (VM disks, IP/MAC) - underlyingResources, err := r.collectUnderlyingResources(ctx, app, backupJob.Spec.ApplicationRef.Kind, backupJob.Namespace) - if err != nil { - logger.Error(err, "failed to collect underlying resources, proceeding without them") - // Non-fatal: proceed with backup even if collection fails - } - templateContext := map[string]interface{}{ "Application": app.Object, "Parameters": resolved.Parameters, @@ -458,28 +256,6 @@ func (r *BackupJobReconciler) createVeleroBackup(ctx context.Context, backupJob if err != nil { return err } - - // Add label selectors for underlying VMDisk HelmReleases - if vmRes := getVMInstanceResources(underlyingResources); vmRes != nil { - for _, dv := range vmRes.DataVolumes { - veleroBackupSpec.OrLabelSelectors = append(veleroBackupSpec.OrLabelSelectors, &metav1.LabelSelector{ - MatchLabels: map[string]string{ - appKindLabel: vmDiskAppKind, - appNameLabel: dv.ApplicationName, - }, - }) - } - if len(vmRes.DataVolumes) > 0 { - logger.Debug("added VMDisk label selectors to Velero backup", "count", len(vmRes.DataVolumes)) - } - } - - // Serialize underlying resources as annotation to persist across reconcile cycles - annotations := map[string]string{} - if underlyingResources != nil && len(underlyingResources.Raw) > 0 { - annotations[underlyingResourcesAnnotation] = string(underlyingResources.Raw) - } - veleroBackup := &velerov1.Backup{ ObjectMeta: metav1.ObjectMeta{ GenerateName: fmt.Sprintf("%s.%s-", backupJob.Namespace, backupJob.Name), @@ -488,7 +264,6 @@ func (r *BackupJobReconciler) createVeleroBackup(ctx context.Context, backupJob backupsv1alpha1.OwningJobNameLabel: backupJob.Name, backupsv1alpha1.OwningJobNamespaceLabel: backupJob.Namespace, }, - Annotations: annotations, }, Spec: *veleroBackupSpec, } @@ -522,8 +297,8 @@ func (r *BackupJobReconciler) createBackupResource(ctx context.Context, backupJo // Extract driver metadata (e.g., Velero backup name) driverMetadata := map[string]string{ - veleroBackupNameMetadataKey: veleroBackup.Name, - veleroBackupNamespaceMetadataKey: veleroBackup.Namespace, + "velero.io/backup-name": veleroBackup.Name, + "velero.io/backup-namespace": veleroBackup.Namespace, } // Create a basic artifact referencing the Velero backup @@ -531,18 +306,19 @@ func (r *BackupJobReconciler) createBackupResource(ctx context.Context, backupJo URI: fmt.Sprintf("velero://%s/%s", veleroBackup.Namespace, veleroBackup.Name), } - // Read underlying resources from Velero Backup annotation - var underlyingResources *runtime.RawExtension - if urJSON, ok := veleroBackup.Annotations[underlyingResourcesAnnotation]; ok && urJSON != "" { - underlyingResources = &runtime.RawExtension{Raw: []byte(urJSON)} - } - - // Note: No OwnerReferences set on Backup. The Backup must survive BackupJob deletion - // so users don't lose their backup artifacts when cleaning up completed jobs. backup := &backupsv1alpha1.Backup{ ObjectMeta: metav1.ObjectMeta{ Name: backupJob.Name, Namespace: backupJob.Namespace, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: backupJob.APIVersion, + Kind: backupJob.Kind, + Name: backupJob.Name, + UID: backupJob.UID, + Controller: boolPtr(true), + }, + }, }, Spec: backupsv1alpha1.BackupSpec{ ApplicationRef: backupJob.Spec.ApplicationRef, @@ -551,9 +327,8 @@ func (r *BackupJobReconciler) createBackupResource(ctx context.Context, backupJo DriverMetadata: driverMetadata, }, Status: backupsv1alpha1.BackupStatus{ - Phase: backupsv1alpha1.BackupPhaseReady, - Artifact: artifact, - UnderlyingResources: underlyingResources, + Phase: backupsv1alpha1.BackupPhaseReady, + Artifact: artifact, }, } @@ -566,916 +341,6 @@ func (r *BackupJobReconciler) createBackupResource(ctx context.Context, backupJo return nil, err } - logger.Debug("created Backup resource", "name", backup.Name, - "hasUnderlyingResources", underlyingResources != nil) + logger.Debug("created Backup resource", "name", backup.Name) return backup, nil } - -// reconcileVeleroRestore handles restore operations for Velero strategy. -func (r *RestoreJobReconciler) reconcileVeleroRestore(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, backup *backupsv1alpha1.Backup) (ctrl.Result, error) { - logger := getLogger(ctx) - logger.Debug("reconciling Velero strategy restore", "restorejob", restoreJob.Name, "backup", backup.Name) - - // Parse restore options from the opaque blob - restoreOpts, err := parseRestoreOptions(restoreJob.Spec.Options) - if err != nil { - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("invalid restore options: %v", err)) - } - - target := resolveRestoreTarget(restoreJob, backup, restoreOpts) - logger.Debug("resolved restore target", "targetNS", target.Namespace, "targetApp", target.AppName, "isCopy", target.IsCopy) - - // Validate: target namespace must exist for cross-namespace copies - if target.IsCopy { - targetNS := &corev1.Namespace{} - if err := r.Get(ctx, client.ObjectKey{Name: target.Namespace}, targetNS); err != nil { - if errors.IsNotFound(err) { - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf( - "target namespace %q does not exist; create it before requesting a cross-namespace restore", - target.Namespace)) - } - return ctrl.Result{}, fmt.Errorf("failed to check target namespace %q: %w", target.Namespace, err) - } - } - - // Validate: same-namespace restore with a different app name is not supported - // due to Velero DataUpload always writing to PVCs with the original name. - if !target.IsCopy && target.AppName != backup.Spec.ApplicationRef.Name { - return r.markRestoreJobFailed(ctx, restoreJob, - "restoring to the same namespace with a different application name is not supported "+ - "due to Velero DataUpload limitations: data is always uploaded to PVCs with the original name. "+ - "Use options.targetNamespace to restore into a different namespace") - } - - // Step 1: On first reconcile, set startedAt and phase = Running - if restoreJob.Status.StartedAt == nil { - logger.Debug("setting RestoreJob StartedAt and phase to Running") - now := metav1.Now() - restoreJob.Status.StartedAt = &now - restoreJob.Status.Phase = backupsv1alpha1.RestoreJobPhaseRunning - if err := r.Status().Update(ctx, restoreJob); err != nil { - logger.Error(err, "failed to update RestoreJob status") - return ctrl.Result{}, err - } - return ctrl.Result{RequeueAfter: defaultRestoreRequeueAfter}, nil - } - - // Step 2: Resolve inputs - Read Strategy, Storage, target Application - logger.Debug("fetching Velero strategy", "strategyName", backup.Spec.StrategyRef.Name) - veleroStrategy := &strategyv1alpha1.Velero{} - if err := r.Get(ctx, client.ObjectKey{Name: backup.Spec.StrategyRef.Name}, veleroStrategy); err != nil { - if errors.IsNotFound(err) { - logger.Error(err, "Velero strategy not found", "strategyName", backup.Spec.StrategyRef.Name) - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("Velero strategy not found: %s", backup.Spec.StrategyRef.Name)) - } - logger.Error(err, "failed to get Velero strategy") - return ctrl.Result{}, err - } - logger.Debug("fetched Velero strategy", "strategyName", veleroStrategy.Name) - - // Get Velero backup name from Backup's driverMetadata - veleroBackupName, ok := backup.Spec.DriverMetadata[veleroBackupNameMetadataKey] - if !ok { - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("Backup missing Velero backup name in driverMetadata (key: %s)", veleroBackupNameMetadataKey)) - } - - // Step 3: Execute restore logic - // Check if we already created a Velero Restore - logger.Debug("checking for existing Velero Restore", "namespace", veleroNamespace) - veleroRestoreList := &velerov1.RestoreList{} - opts := []client.ListOption{ - client.InNamespace(veleroNamespace), - client.MatchingLabels{ - backupsv1alpha1.OwningJobNameLabel: restoreJob.Name, - backupsv1alpha1.OwningJobNamespaceLabel: restoreJob.Namespace, - }, - } - - if err := r.List(ctx, veleroRestoreList, opts...); err != nil { - logger.Error(err, "failed to get Velero Restore") - return ctrl.Result{}, err - } - - if len(veleroRestoreList.Items) == 0 { - // For copy restores, enforce failIfTargetExists before touching anything. - // In-place restores are excluded: the source application is expected to exist - // and will be halted/overwritten deliberately. - if target.IsCopy && restoreOpts.GetFailIfTargetExists() { - targetHRName := helmReleaseNameForApp(target.AppKind, target.AppName) - exists, err := r.targetHelmReleaseExists(ctx, target.AppKind, targetHRName, target.Namespace) - if err != nil { - logger.Error(err, "failed to check whether target HelmRelease exists") - return ctrl.Result{}, err - } - if exists { - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf( - "target application %q already exists in namespace %q; "+ - "set options.failIfTargetExists=false to overwrite", - target.AppName, target.Namespace)) - } - } - - // Resolve underlying resources once; prefer Backup status, fall back to Velero annotation. - ur := r.resolveUnderlyingResourcesForRestore(ctx, backup, veleroBackupName) - - // Pre-restore: graceful shutdown, suspend HRs, rename PVCs (skipped for copy) - ready, result, err := r.prepareForRestore(ctx, restoreJob, backup, ur, target, restoreOpts) - if err != nil { - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("pre-restore preparation failed: %v", err)) - } - if !ready { - logger.Debug("pre-restore preparation in progress, requeuing") - return result, nil - } - - // Create Velero Restore - logger.Debug("Velero Restore not found, creating new one") - if err := r.createVeleroRestore(ctx, restoreJob, backup, veleroStrategy, veleroBackupName, ur, target, restoreOpts); err != nil { - logger.Error(err, "failed to create Velero Restore") - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("failed to create Velero Restore: %v", err)) - } - logger.Debug("created Velero Restore, requeuing") - // Requeue to check status - return ctrl.Result{RequeueAfter: defaultRestoreRequeueAfter}, nil - } - - if len(veleroRestoreList.Items) > 1 { - logger.Error(fmt.Errorf("too many Velero restores for RestoreJob"), "found more than one Velero Restore referencing a single RestoreJob as owner") - return r.markRestoreJobFailed(ctx, restoreJob, "found multiple Velero Restores for this RestoreJob") - } - - veleroRestore := veleroRestoreList.Items[0].DeepCopy() - logger.Debug("found existing Velero Restore", "phase", veleroRestore.Status.Phase) - - // Check Velero Restore status - phase := string(veleroRestore.Status.Phase) - if phase == "" { - // Still in progress, requeue - return ctrl.Result{RequeueAfter: defaultActiveRestorePollingInterval}, nil - } - - // Step 4: On success - if phase == "Completed" { - // Post-restore: rename resources if target app name differs from source. - // Velero resource modifiers cannot change metadata.name, so we do it after restore. - if target.IsRenamed { - if err := r.postRestoreRename(ctx, restoreJob, backup, target); err != nil { - r.cleanupResourceModifierConfigMaps(ctx, restoreJob) - return r.markRestoreJobFailed(ctx, restoreJob, fmt.Sprintf("post-restore rename failed: %v", err)) - } - } - - // Clean up resource modifier ConfigMaps now that the restore is complete. - r.cleanupResourceModifierConfigMaps(ctx, restoreJob) - - now := metav1.Now() - restoreJob.Status.CompletedAt = &now - restoreJob.Status.Phase = backupsv1alpha1.RestoreJobPhaseSucceeded - if err := r.Status().Update(ctx, restoreJob); err != nil { - logger.Error(err, "failed to update RestoreJob status") - return ctrl.Result{}, err - } - logger.Debug("RestoreJob succeeded") - return ctrl.Result{}, nil - } - - // Step 5: On failure - if phase == "Failed" || phase == "PartiallyFailed" { - r.cleanupResourceModifierConfigMaps(ctx, restoreJob) - message := fmt.Sprintf("Velero Restore failed with phase: %s", phase) - if veleroRestore.Status.FailureReason != "" { - message = fmt.Sprintf("%s: %s", message, veleroRestore.Status.FailureReason) - } - return r.markRestoreJobFailed(ctx, restoreJob, message) - } - - // Still in progress (InProgress, New, etc.) - return ctrl.Result{RequeueAfter: defaultRestoreRequeueAfter}, nil -} - -// Velero resource modifier types (local mirrors of the internal Velero types). - -type resourceModifiers struct { - Version string `yaml:"version"` - ResourceModifierRules []resourceModifierRule `yaml:"resourceModifierRules"` -} - -type resourceModifierRule struct { - Conditions resourceModifierConditions `yaml:"conditions"` - MergePatches []mergePatch `yaml:"mergePatches,omitempty"` - Patches []jsonPatch `yaml:"patches,omitempty"` -} - -type resourceModifierConditions struct { - GroupResource string `yaml:"groupResource"` - ResourceNameRegex string `yaml:"resourceNameRegex,omitempty"` - Namespaces []string `yaml:"namespaces,omitempty"` -} - -type mergePatch struct { - PatchData string `yaml:"patchData"` -} - -type jsonPatch struct { - Operation string `yaml:"operation"` - Path string `yaml:"path"` - Value string `yaml:"value,omitempty"` -} - -// marshalPatchData marshals an arbitrary object to YAML for use as -// mergePatch.PatchData in Velero resource modifiers. -func marshalPatchData(v interface{}) (string, error) { - b, err := yaml.Marshal(v) - if err != nil { - return "", fmt.Errorf("failed to marshal patch data: %w", err) - } - return string(b), nil -} - -// createResourceModifiersConfigMap creates a Velero resource modifiers ConfigMap -// that patches VM resources during restore: -// - PVC adoption: always adds cdi.kubevirt.io/allowClaimAdoption=true to all -// restored PVCs so CDI can adopt them when a HelmRelease of VMDisk recreates a DV. -// - OVN IP/MAC: sets OVN annotations on the VirtualMachine for correct ssh access to restored VM. -func (r *RestoreJobReconciler) createResourceModifiersConfigMap(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, backup *backupsv1alpha1.Backup, ur *runtime.RawExtension, target restoreTarget, opts RestoreOptions) (*corev1.ConfigMap, error) { - logger := getLogger(ctx) - - targetNS := target.Namespace - - var rules []resourceModifierRule - - // PVC adoption: allow CDI to adopt restored PVCs when the HelmRelease recreates a DV. - pvcPatch, err := marshalPatchData(map[string]interface{}{ - "metadata": map[string]interface{}{ - "annotations": map[string]string{ - cdiAllowClaimAdoption: "true", - }, - }, - }) - if err != nil { - return nil, err - } - rules = append(rules, resourceModifierRule{ - Conditions: resourceModifierConditions{ - GroupResource: "persistentvolumeclaims", - ResourceNameRegex: ".*", - Namespaces: []string{targetNS}, - }, - MergePatches: []mergePatch{{PatchData: pvcPatch}}, - }) - - // For cross-namespace restore: strip Velero's dynamic PV restore selector and - // volumeName from PVCs so the storage provisioner can dynamically provision new PVs. - // Without this, Velero's CSI PVCAction adds spec.selector with a velero.io/dynamic-pv-restore - // label that prevents dynamic provisioning when PVs are not included in the restore. - // Uses merge patch (null values) instead of JSON Patch remove to avoid RFC 6902 - // failures when the fields don't exist on the PVC (e.g. statically provisioned PVCs). - if target.IsCopy { - pvcStripPatch, err := marshalPatchData(map[string]interface{}{ - "spec": map[string]interface{}{ - "selector": nil, - "volumeName": nil, - }, - }) - if err != nil { - return nil, err - } - rules = append(rules, resourceModifierRule{ - Conditions: resourceModifierConditions{ - GroupResource: "persistentvolumeclaims", - ResourceNameRegex: ".*", - Namespaces: []string{targetNS}, - }, - MergePatches: []mergePatch{{PatchData: pvcStripPatch}}, - }) - } - - // OVN IP/MAC annotations on VirtualMachine for correct network identity after restore. - // Only applied when keepOriginalIpAndMac is true; for restore-to-copy the copy - // should get new IP/MAC from the network to avoid conflicts. - if opts.GetKeepOriginalIpAndMac() { - if vmRes := getVMInstanceResources(ur); vmRes != nil && (vmRes.IP != "" || vmRes.MAC != "") { - ovnAnnotations := map[string]string{} - if vmRes.IP != "" { - ovnAnnotations[ovnIPAnnotation] = vmRes.IP - } - if vmRes.MAC != "" { - ovnAnnotations[ovnMACAnnotation] = vmRes.MAC - } - vmPatch, err := marshalPatchData(map[string]interface{}{ - "spec": map[string]interface{}{ - "template": map[string]interface{}{ - "metadata": map[string]interface{}{ - "annotations": ovnAnnotations, - }, - }, - }, - }) - if err != nil { - return nil, err - } - rules = append(rules, resourceModifierRule{ - Conditions: resourceModifierConditions{ - GroupResource: "virtualmachines.kubevirt.io", - ResourceNameRegex: ".*", - Namespaces: []string{targetNS}, - }, - MergePatches: []mergePatch{{PatchData: vmPatch}}, - }) - } - } - - rulesYAML, err := yaml.Marshal(resourceModifiers{ - Version: "v1", - ResourceModifierRules: rules, - }) - if err != nil { - return nil, fmt.Errorf("failed to marshal resource modifier rules: %w", err) - } - - cmName := fmt.Sprintf("restore-modifiers-%s-%s", restoreJob.Namespace, restoreJob.Name) - // Truncate name to fit Kubernetes 253-char limit - if len(cmName) > 253 { - cmName = cmName[:253] - } - - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: cmName, - Namespace: veleroNamespace, - Labels: map[string]string{ - backupsv1alpha1.OwningJobNameLabel: restoreJob.Name, - backupsv1alpha1.OwningJobNamespaceLabel: restoreJob.Namespace, - }, - }, - Data: map[string]string{ - "resource-modifier-rules.yaml": string(rulesYAML), - }, - } - - if err := r.Create(ctx, cm); err != nil { - if errors.IsAlreadyExists(err) { - // ConfigMap already exists (e.g. RestoreJob recreated with same name). - // Update its data to reflect the current backup's underlying resources. - existing := &corev1.ConfigMap{} - if err := r.Get(ctx, client.ObjectKey{Namespace: veleroNamespace, Name: cmName}, existing); err != nil { - return nil, fmt.Errorf("failed to get existing resourceModifiers ConfigMap: %w", err) - } - existing.Data = cm.Data - if err := r.Update(ctx, existing); err != nil { - return nil, fmt.Errorf("failed to update existing resourceModifiers ConfigMap: %w", err) - } - logger.Debug("updated existing resourceModifiers ConfigMap", "name", cmName) - return existing, nil - } - return nil, fmt.Errorf("failed to create resourceModifiers ConfigMap: %w", err) - } - - logger.Debug("created resourceModifiers ConfigMap", "name", cm.Name, "namespace", cm.Namespace) - return cm, nil -} - -// resolveUnderlyingResourcesForRestore returns underlying resources for symmetric -// restore label selectors. Velero Backup annotation is used when Backup.status was empty -// (e.g. CRD without underlyingResources in schema). -func (r *RestoreJobReconciler) resolveUnderlyingResourcesForRestore(ctx context.Context, backup *backupsv1alpha1.Backup, veleroBackupName string) *runtime.RawExtension { - if backup.Status.UnderlyingResources != nil && len(backup.Status.UnderlyingResources.Raw) > 0 { - return backup.Status.UnderlyingResources - } - vb := &velerov1.Backup{} - if err := r.Get(ctx, client.ObjectKey{Namespace: veleroNamespace, Name: veleroBackupName}, vb); err != nil { - return backup.Status.UnderlyingResources - } - if urJSON, ok := vb.Annotations[underlyingResourcesAnnotation]; ok && urJSON != "" { - return &runtime.RawExtension{Raw: []byte(urJSON)} - } - return backup.Status.UnderlyingResources -} - -// GVRs used during pre-restore preparation. -var ( - helmReleaseGVR = schema.GroupVersionResource{Group: "helm.toolkit.fluxcd.io", Version: "v2", Resource: "helmreleases"} - virtualMachineGVR = schema.GroupVersionResource{Group: "kubevirt.io", Version: "v1", Resource: "virtualmachines"} - vmiGVR = schema.GroupVersionResource{Group: "kubevirt.io", Version: "v1", Resource: "virtualmachineinstances"} - dataVolumeGVR = schema.GroupVersionResource{Group: "cdi.kubevirt.io", Version: "v1beta1", Resource: "datavolumes"} -) - -// helmReleaseNameForApp returns the HelmRelease name for the given application -// kind and name. Returns empty string for unsupported kinds. -func helmReleaseNameForApp(appKind, appName string) string { - switch appKind { - case vmInstanceKind: - return vmNamePrefix + appName - case vmDiskAppKind: - return vmDiskNamePrefix + appName - default: - return "" - } -} - -// targetHelmReleaseExists returns true when a HelmRelease with the given name -// already exists in namespace. Returns false for unsupported application kinds -// (those where helmReleaseNameForApp returns ""). -func (r *RestoreJobReconciler) targetHelmReleaseExists(ctx context.Context, appKind, hrName, namespace string) (bool, error) { - if hrName == "" { - return false, nil - } - _, err := r.Resource(helmReleaseGVR).Namespace(namespace).Get(ctx, hrName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return false, nil - } - return false, err - } - return true, nil -} - -// shortHash returns the first 4 hex characters of sha256(input). -func shortHash(input string) string { - h := sha256.Sum256([]byte(input)) - return hex.EncodeToString(h[:])[:4] -} - -// prepareForRestore performs graceful pre-restore cleanup: -// 1. Suspends HelmReleases that belong to the backup scope. -// 2. Halts the VirtualMachine (sets spec.runStrategy=Halted). -// 3. Waits for the VMI to disappear (graceful shutdown complete). -// 4. Deletes DataVolumes so CDI doesn't recreate PVCs after rename. -// 5. Renames existing PVCs to -orig- so Velero can create fresh -// ones via Data Movement. -// -// Failures in individual steps are non-fatal: missing resources are expected -// (e.g. restore requested when app was already deleted). Each action emits -// a Kubernetes Event on the RestoreJob for observability. -// -// postRestoreRename renames VMInstance HelmRelease after Velero Restore completes. -// Velero resource modifiers cannot change metadata.name, so this step creates -// a new HelmRelease with the target name and deletes the old one. -// Flux will reconcile the renamed HelmRelease and recreate downstream resources -// (VM, VMI) with the new name. -func (r *RestoreJobReconciler) postRestoreRename(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, backup *backupsv1alpha1.Backup, target restoreTarget) error { - logger := getLogger(ctx) - sourceAppName := backup.Spec.ApplicationRef.Name - sourceHRName := vmNamePrefix + sourceAppName - targetHRName := vmNamePrefix + target.AppName - - logger.Debug("post-restore rename", "from", sourceHRName, "to", targetHRName, "namespace", target.Namespace) - - // Get the restored HelmRelease with the original name - hrClient := r.Resource(helmReleaseGVR).Namespace(target.Namespace) - oldHR, err := hrClient.Get(ctx, sourceHRName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - logger.Debug("source HelmRelease not found, skipping rename", "name", sourceHRName) - return nil - } - return fmt.Errorf("failed to get HelmRelease %s: %w", sourceHRName, err) - } - - // Create new HelmRelease with the target name - newHR := oldHR.DeepCopy() - newHR.SetName(targetHRName) - newHR.SetResourceVersion("") - newHR.SetUID("") - newHR.SetCreationTimestamp(metav1.Time{}) - newHR.SetManagedFields(nil) - newHR.SetGeneration(0) - - // Update labels - labels := newHR.GetLabels() - if labels == nil { - labels = map[string]string{} - } - labels[appNameLabel] = target.AppName - labels["app.kubernetes.io/instance"] = targetHRName - labels["helm.toolkit.fluxcd.io/name"] = targetHRName - newHR.SetLabels(labels) - - // Remove Velero restore annotations/labels that tie it to the old restore - annotations := newHR.GetAnnotations() - delete(annotations, "velero.io/restore-name") - newHR.SetAnnotations(annotations) - - // Clear status so Flux reconciles fresh - unstructured.RemoveNestedField(newHR.Object, "status") - - if _, err := hrClient.Create(ctx, newHR, metav1.CreateOptions{}); err != nil { - if errors.IsAlreadyExists(err) { - logger.Debug("target HelmRelease already exists, skipping create", "name", targetHRName) - } else { - return fmt.Errorf("failed to create renamed HelmRelease %s: %w", targetHRName, err) - } - } else { - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PostRestoreRename", - fmt.Sprintf("Created renamed HelmRelease %s (from %s)", targetHRName, sourceHRName)) - } - - // Delete the old HelmRelease - if err := hrClient.Delete(ctx, sourceHRName, metav1.DeleteOptions{}); err != nil && !errors.IsNotFound(err) { - return fmt.Errorf("failed to delete old HelmRelease %s: %w", sourceHRName, err) - } - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PostRestoreRename", - fmt.Sprintf("Deleted old HelmRelease %s", sourceHRName)) - - logger.Debug("post-restore rename complete", "from", sourceHRName, "to", targetHRName) - return nil -} - -// Returns true when preparation is complete and the Velero Restore can be created. -// Returns false (with a requeue) when still waiting for VM shutdown. -func (r *RestoreJobReconciler) prepareForRestore(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, backup *backupsv1alpha1.Backup, ur *runtime.RawExtension, target restoreTarget, opts RestoreOptions) (ready bool, result ctrl.Result, err error) { - // For restore-to-copy, skip all source-app preparation. - // The source application remains untouched; we're restoring a copy into another namespace. - if target.IsCopy { - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PrepareForRestore", - "Restore to copy: skipping source application preparation") - return true, ctrl.Result{}, nil - } - - ns := restoreJob.Namespace - appName := backup.Spec.ApplicationRef.Name - appKind := backup.Spec.ApplicationRef.Kind - origSuffix := "-orig-" + shortHash(restoreJob.Name) - - // --- Step 1: Suspend HelmReleases --- - vmRes := getVMInstanceResources(ur) - hrNames := []string{} - if appKind == vmInstanceKind { - hrNames = append(hrNames, vmNamePrefix+appName) - } - if vmRes != nil { - for _, dv := range vmRes.DataVolumes { - hrNames = append(hrNames, dv.DataVolumeName) - } - } - for _, hrName := range hrNames { - if err := r.suspendHelmRelease(ctx, ns, hrName); err != nil { - r.Recorder.Event(restoreJob, corev1.EventTypeWarning, "PrepareForRestore", - fmt.Sprintf("Failed to suspend HelmRelease %s: %v", hrName, err)) - } else { - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PrepareForRestore", - fmt.Sprintf("Suspended HelmRelease %s", hrName)) - } - } - - // --- Step 2: Halt VM and wait for shutdown --- - if appKind == vmInstanceKind { - vmName := vmNamePrefix + appName - halted, err := r.haltVirtualMachine(ctx, ns, vmName) - if err != nil { - r.Recorder.Event(restoreJob, corev1.EventTypeWarning, "PrepareForRestore", - fmt.Sprintf("Failed to halt VM %s: %v", vmName, err)) - // Non-fatal: proceed even if halting fails (VM might not exist) - } else if !halted { - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PrepareForRestore", - fmt.Sprintf("Waiting for VM %s to shut down", vmName)) - return false, ctrl.Result{RequeueAfter: defaultRestoreRequeueAfter}, nil - } else { - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PrepareForRestore", - fmt.Sprintf("VM %s is halted", vmName)) - } - } - - // --- Step 3: Rename PVCs to -orig- --- - // Must happen BEFORE deleting DVs: the PVC has an ownerReference to the DV, - // so deleting the DV first would cascade-delete the PVC via garbage collection. - // Only when keepOriginalPVC is true (default for in-place restore). - if opts.GetKeepOriginalPVC() && vmRes != nil { - for _, dv := range vmRes.DataVolumes { - if err := r.renamePVC(ctx, restoreJob, ns, dv.DataVolumeName, dv.DataVolumeName+origSuffix); err != nil { - r.Recorder.Event(restoreJob, corev1.EventTypeWarning, "PrepareForRestore", - fmt.Sprintf("Failed to keep old PVC %s: %v", dv.DataVolumeName, err)) - } - } - } - - // --- Step 4: Delete DataVolumes so CDI doesn't recreate PVCs --- - if vmRes != nil { - for _, dv := range vmRes.DataVolumes { - if err := r.deleteDataVolume(ctx, ns, dv.DataVolumeName); err != nil { - r.Recorder.Event(restoreJob, corev1.EventTypeWarning, "PrepareForRestore", - fmt.Sprintf("Failed to delete DataVolume %s: %v", dv.DataVolumeName, err)) - } else { - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PrepareForRestore", - fmt.Sprintf("Deleted DataVolume %s", dv.DataVolumeName)) - } - } - } - - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PrepareForRestore", "Pre-restore preparation complete") - return true, ctrl.Result{}, nil -} - -// suspendHelmRelease sets spec.suspend=true on a HelmRelease. -func (r *RestoreJobReconciler) suspendHelmRelease(ctx context.Context, ns, name string) error { - hr, err := r.Resource(helmReleaseGVR).Namespace(ns).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return nil - } - return err - } - suspended, _, _ := unstructured.NestedBool(hr.Object, "spec", "suspend") - if suspended { - return nil - } - if err := unstructured.SetNestedField(hr.Object, true, "spec", "suspend"); err != nil { - return err - } - if _, err := r.Resource(helmReleaseGVR).Namespace(ns).Update(ctx, hr, metav1.UpdateOptions{}); err != nil { - return err - } - return nil -} - -// haltVirtualMachine sets runStrategy=Halted and returns true when the VMI is gone. -func (r *RestoreJobReconciler) haltVirtualMachine(ctx context.Context, ns, vmName string) (bool, error) { - vm, err := r.Resource(virtualMachineGVR).Namespace(ns).Get(ctx, vmName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return true, nil - } - return false, err - } - - currentStrategy, _, _ := unstructured.NestedString(vm.Object, "spec", "runStrategy") - if currentStrategy != "Halted" { - if err := unstructured.SetNestedField(vm.Object, "Halted", "spec", "runStrategy"); err != nil { - return false, err - } - if _, err := r.Resource(virtualMachineGVR).Namespace(ns).Update(ctx, vm, metav1.UpdateOptions{}); err != nil { - return false, err - } - } - - // VMI gone = shutdown complete - _, err = r.Resource(vmiGVR).Namespace(ns).Get(ctx, vmName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return true, nil - } - return false, err - } - return false, nil -} - -// deleteDataVolume deletes a DataVolume so CDI doesn't recreate the PVC after rename. -// Uses Orphan propagation to avoid cascade-deleting the PVC that the DV owns via -// ownerReference. Without this, keepOriginalPVC=false would silently destroy the -// original PVC through garbage collection instead of leaving it for Velero to overwrite. -func (r *RestoreJobReconciler) deleteDataVolume(ctx context.Context, ns, name string) error { - orphan := metav1.DeletePropagationOrphan - err := r.Resource(dataVolumeGVR).Namespace(ns).Delete(ctx, name, metav1.DeleteOptions{ - PropagationPolicy: &orphan, - }) - if err != nil && !errors.IsNotFound(err) { - return err - } - return nil -} - -// renamePVC preserves an existing PVC by rebinding it under a new name. -// The original PVC is deleted and a new one pointing to the same PV is created. -// Missing resources are silently skipped (non-fatal). -func (r *RestoreJobReconciler) renamePVC(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, ns, oldName, newName string) error { - logger := getLogger(ctx) - - // Check if already renamed - existingNew := &corev1.PersistentVolumeClaim{} - if err := r.Get(ctx, client.ObjectKey{Namespace: ns, Name: newName}, existingNew); err == nil { - return nil - } - - // Get the original PVC - oldPVC := &corev1.PersistentVolumeClaim{} - if err := r.Get(ctx, client.ObjectKey{Namespace: ns, Name: oldName}, oldPVC); err != nil { - if errors.IsNotFound(err) { - return nil // nothing to rename - } - return err - } - - pvName := oldPVC.Spec.VolumeName - if pvName == "" { - logger.Debug("PVC not bound, deleting", "name", oldName) - return r.Delete(ctx, oldPVC) - } - - // Patch PV reclaim policy to Retain so it survives PVC deletion - pv := &corev1.PersistentVolume{} - if err := r.Get(ctx, client.ObjectKey{Name: pvName}, pv); err != nil { - return fmt.Errorf("failed to get PV %s: %w", pvName, err) - } - if pv.Spec.PersistentVolumeReclaimPolicy != corev1.PersistentVolumeReclaimRetain { - pv.Spec.PersistentVolumeReclaimPolicy = corev1.PersistentVolumeReclaimRetain - if err := r.Update(ctx, pv); err != nil { - return fmt.Errorf("failed to set Retain policy on PV %s: %w", pvName, err) - } - } - - // Create the new -orig PVC first (unbound, just the object) - newPVC := &corev1.PersistentVolumeClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: newName, - Namespace: ns, - }, - Spec: corev1.PersistentVolumeClaimSpec{ - AccessModes: oldPVC.Spec.AccessModes, - Resources: oldPVC.Spec.Resources, - StorageClassName: oldPVC.Spec.StorageClassName, - VolumeMode: oldPVC.Spec.VolumeMode, - VolumeName: pvName, - }, - } - if err := r.Create(ctx, newPVC); err != nil && !errors.IsAlreadyExists(err) { - return fmt.Errorf("failed to create -orig PVC %s: %w", newName, err) - } - // Re-read to get UID for the claimRef - if err := r.Get(ctx, client.ObjectKey{Namespace: ns, Name: newName}, newPVC); err != nil { - return fmt.Errorf("failed to get -orig PVC %s: %w", newName, err) - } - - // Delete the original PVC - if err := r.Delete(ctx, oldPVC); err != nil && !errors.IsNotFound(err) { - return fmt.Errorf("failed to delete PVC %s: %w", oldName, err) - } - - // Point the PV's claimRef directly to the new -orig PVC. - // This is atomic — no window where the PV is Available for other PVCs to grab. - if err := r.Get(ctx, client.ObjectKey{Name: pvName}, pv); err != nil { - return fmt.Errorf("failed to re-fetch PV %s: %w", pvName, err) - } - pv.Spec.ClaimRef = &corev1.ObjectReference{ - APIVersion: "v1", - Kind: "PersistentVolumeClaim", - Namespace: ns, - Name: newName, - UID: newPVC.UID, - } - if err := r.Update(ctx, pv); err != nil { - return fmt.Errorf("failed to rebind PV %s to %s: %w", pvName, newName, err) - } - - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "PrepareForRestore", - fmt.Sprintf("Keep old PVC %s as %s (PV: %s)", oldName, newName, pvName)) - return nil -} - -// createVeleroRestore creates a Velero Restore resource. -func (r *RestoreJobReconciler) createVeleroRestore(ctx context.Context, restoreJob *backupsv1alpha1.RestoreJob, backup *backupsv1alpha1.Backup, strategy *strategyv1alpha1.Velero, veleroBackupName string, ur *runtime.RawExtension, target restoreTarget, opts RestoreOptions) error { - logger := getLogger(ctx) - logger.Debug("createVeleroRestore called", "strategy", strategy.Name, "veleroBackupName", veleroBackupName, "targetNS", target.Namespace, "isCopy", target.IsCopy) - - // For restore template context, always use the source (backup) namespace and app name. - // The strategy template uses includedNamespaces and orLabelSelectors to select - // resources from the backup tarball, which are stored under the source namespace - // and labeled with the source app name. - // Velero's namespaceMapping handles redirecting to the target namespace; - // resource modifiers handle renaming when the target app name differs. - templateContext := map[string]interface{}{ - "Application": map[string]interface{}{ - "metadata": map[string]interface{}{ - "name": backup.Spec.ApplicationRef.Name, - "namespace": backup.Namespace, - }, - "kind": backup.Spec.ApplicationRef.Kind, - }, - // TODO: Parameters are not currently stored on Backup, so they're unavailable during restore. - // This is a design limitation that should be addressed by persisting Parameters on the Backup object. - "Parameters": map[string]string{}, - } - - // Template the restore spec from the strategy, or use defaults if not specified - var veleroRestoreSpec velerov1.RestoreSpec - if strategy.Spec.Template.RestoreSpec != nil { - templatedSpec, err := template.Template(strategy.Spec.Template.RestoreSpec, templateContext) - if err != nil { - return fmt.Errorf("failed to template Velero Restore spec: %w", err) - } - veleroRestoreSpec = *templatedSpec - } - - // Set the backupName in the spec (required by Velero) - veleroRestoreSpec.BackupName = veleroBackupName - - // For restore-to-copy, set Velero namespaceMapping to redirect resources - // from the source namespace to the target namespace. - if target.IsCopy { - if veleroRestoreSpec.NamespaceMapping == nil { - veleroRestoreSpec.NamespaceMapping = make(map[string]string) - } - veleroRestoreSpec.NamespaceMapping[backup.Namespace] = target.Namespace - logger.Debug("set namespaceMapping on Velero Restore", "from", backup.Namespace, "to", target.Namespace) - } - - // Match backup: add OR selectors for each underlying VMDisk so restore applies the same - // scope as the intended backup (see createVeleroBackup). - if vmRes := getVMInstanceResources(ur); vmRes != nil { - for _, dv := range vmRes.DataVolumes { - veleroRestoreSpec.OrLabelSelectors = append(veleroRestoreSpec.OrLabelSelectors, &metav1.LabelSelector{ - MatchLabels: map[string]string{ - appKindLabel: vmDiskAppKind, - appNameLabel: dv.ApplicationName, - }, - }) - } - if len(vmRes.DataVolumes) > 0 { - logger.Debug("added VMDisk label selectors to Velero restore", "count", len(vmRes.DataVolumes)) - } - } - - // Create resourceModifiers ConfigMap - resourceModifierCM, err := r.createResourceModifiersConfigMap(ctx, restoreJob, backup, ur, target, opts) - if err != nil { - return fmt.Errorf("failed to create resourceModifiers ConfigMap: %w", err) - } - if resourceModifierCM != nil { - veleroRestoreSpec.ResourceModifier = &corev1.TypedLocalObjectReference{ - APIGroup: stringPtr(""), - Kind: "ConfigMap", - Name: resourceModifierCM.Name, - } - logger.Debug("set resourceModifier on Velero Restore", "configMap", resourceModifierCM.Name) - } - - generateName := fmt.Sprintf("%s.%s-", restoreJob.Namespace, restoreJob.Name) - veleroRestore := &velerov1.Restore{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: generateName, - Namespace: veleroNamespace, - Labels: map[string]string{ - backupsv1alpha1.OwningJobNameLabel: restoreJob.Name, - backupsv1alpha1.OwningJobNamespaceLabel: restoreJob.Namespace, - }, - }, - Spec: veleroRestoreSpec, - } - if err := r.Create(ctx, veleroRestore); err != nil { - logger.Error(err, "failed to create Velero Restore", "generateName", generateName) - r.Recorder.Event(restoreJob, corev1.EventTypeWarning, "VeleroRestoreCreationFailed", - fmt.Sprintf("Failed to create Velero Restore %s/%s: %v", veleroNamespace, generateName, err)) - return err - } - - logger.Debug("created Velero Restore", "name", veleroRestore.Name, "namespace", veleroRestore.Namespace) - r.Recorder.Event(restoreJob, corev1.EventTypeNormal, "VeleroRestoreCreated", - fmt.Sprintf("Created Velero Restore %s/%s", veleroNamespace, veleroRestore.Name)) - return nil -} - -// dataUploadListGVK is the API version shipped with Velero data mover CRDs (see velero datauploads CRD). -var dataUploadListGVK = schema.GroupVersionKind{Group: "velero.io", Version: "v2alpha1", Kind: "DataUploadList"} - -// formatVeleroBackupFailureMessageForBackupJob builds a BackupJob status message from Velero Backup -// status plus failed DataUpload resources (CSI data mover), similar to `velero backup describe`. -func formatVeleroBackupFailureMessageForBackupJob(ctx context.Context, c client.Client, veleroBackup *velerov1.Backup) string { - var b strings.Builder - fmt.Fprintf(&b, "Velero Backup failed with phase %s", veleroBackup.Status.Phase) - if fr := strings.TrimSpace(veleroBackup.Status.FailureReason); fr != "" { - fmt.Fprintf(&b, ": %s", fr) - } - if len(veleroBackup.Status.ValidationErrors) > 0 { - fmt.Fprintf(&b, "; validation: %v", veleroBackup.Status.ValidationErrors) - } - if h := veleroBackup.Status.HookStatus; h != nil && h.HooksFailed > 0 { - fmt.Fprintf(&b, "; hooks failed %d/%d", h.HooksFailed, h.HooksAttempted) - } - if veleroBackup.Status.BackupItemOperationsFailed > 0 { - fmt.Fprintf(&b, "; async item operations failed %d (completed %d, attempted %d)", - veleroBackup.Status.BackupItemOperationsFailed, - veleroBackup.Status.BackupItemOperationsCompleted, - veleroBackup.Status.BackupItemOperationsAttempted) - } - b.WriteString(appendFailedDataUploadMessages(ctx, c, veleroBackup.Name)) - return b.String() -} - -func appendFailedDataUploadMessages(ctx context.Context, c client.Client, veleroBackupName string) string { - ul := unstructured.UnstructuredList{} - ul.SetGroupVersionKind(dataUploadListGVK) - if err := c.List(ctx, &ul, client.InNamespace(veleroNamespace)); err != nil { - return "" - } - prefix := veleroBackupName + "-" - var b strings.Builder - for _, item := range ul.Items { - if !strings.HasPrefix(item.GetName(), prefix) { - continue - } - phase, _, _ := unstructured.NestedString(item.Object, "status", "phase") - if phase != "Failed" { - continue - } - msg, _, _ := unstructured.NestedString(item.Object, "status", "message") - if strings.TrimSpace(msg) == "" { - msg = "(empty status.message)" - } - srcPVC, _, _ := unstructured.NestedString(item.Object, "spec", "sourcePVC") - if srcPVC != "" { - fmt.Fprintf(&b, "; DataUpload %s failed for PVC %s: %s", item.GetName(), srcPVC, msg) - } else { - fmt.Fprintf(&b, "; DataUpload %s failed: %s", item.GetName(), msg) - } - } - return b.String() -} diff --git a/internal/backupcontroller/velerostrategy_controller_test.go b/internal/backupcontroller/velerostrategy_controller_test.go index 7b085dbf..a7de2076 100644 --- a/internal/backupcontroller/velerostrategy_controller_test.go +++ b/internal/backupcontroller/velerostrategy_controller_test.go @@ -2,13 +2,11 @@ package backupcontroller import ( "context" - "encoding/json" "testing" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" dynamicfake "k8s.io/client-go/dynamic/fake" @@ -208,1006 +206,3 @@ func TestCreateVeleroBackup_TemplateContext(t *testing.T) { t.Errorf("Template context Parameters.backupStorageLocationName not applied correctly. Expected 'default-storage', got '%s'", veleroBackup.Spec.StorageLocation) } } - -func TestResolveRestoreTarget_NoTargetNamespace_InPlace(t *testing.T) { - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{ - Name: "restore-test", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "my-backup"}, - TargetApplicationRef: &corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-vm", - }, - }, - } - - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-backup", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-vm", - }, - }, - } - - // No targetNamespace in options → in-place restore - opts := RestoreOptions{} - target := resolveRestoreTarget(restoreJob, backup, opts) - - if target.IsCopy { - t.Error("expected IsCopy=false when targetNamespace is omitted, got true") - } - if target.Namespace != "tenant-root" { - t.Errorf("expected namespace 'tenant-root', got '%s'", target.Namespace) - } - if target.AppName != "test-vm" { - t.Errorf("expected appName 'test-vm', got '%s'", target.AppName) - } - if target.AppKind != "VMInstance" { - t.Errorf("expected appKind 'VMInstance', got '%s'", target.AppKind) - } -} - -func TestResolveRestoreTarget_SameTargetNamespace_InPlace(t *testing.T) { - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{ - Name: "restore-test", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "my-backup"}, - }, - } - - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-backup", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-vm", - }, - }, - } - - // targetNamespace equals backup namespace → still in-place - opts := RestoreOptions{ - CommonRestoreOptions: CommonRestoreOptions{ - TargetNamespace: "tenant-root", - }, - } - target := resolveRestoreTarget(restoreJob, backup, opts) - - if target.IsCopy { - t.Error("expected IsCopy=false when targetNamespace equals backup namespace, got true") - } - if target.Namespace != "tenant-root" { - t.Errorf("expected namespace 'tenant-root', got '%s'", target.Namespace) - } -} - -func TestResolveRestoreTarget_DifferentTargetNamespace_Copy(t *testing.T) { - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{ - Name: "restore-test", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "my-backup"}, - }, - } - - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-backup", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-vm", - }, - }, - } - - opts := RestoreOptions{ - CommonRestoreOptions: CommonRestoreOptions{ - TargetNamespace: "tenant-copy", - }, - } - target := resolveRestoreTarget(restoreJob, backup, opts) - - if !target.IsCopy { - t.Error("expected IsCopy=true when targetNamespace differs from backup namespace, got false") - } - if target.Namespace != "tenant-copy" { - t.Errorf("expected namespace 'tenant-copy', got '%s'", target.Namespace) - } -} - -// newTestRestoreJobReconcilerWithDynamic builds a RestoreJobReconciler with -// both static and dynamic fake clients. Use dynamicObjects to pre-populate -// unstructured resources (e.g. HelmReleases). -func newTestRestoreJobReconcilerWithDynamic(t *testing.T, dynamicObjects []runtime.Object, objects ...client.Object) *RestoreJobReconciler { - t.Helper() - testScheme := runtime.NewScheme() - _ = scheme.AddToScheme(testScheme) - _ = backupsv1alpha1.AddToScheme(testScheme) - _ = velerov1.AddToScheme(testScheme) - - fakeClient := clientfake.NewClientBuilder(). - WithScheme(testScheme). - WithObjects(objects...). - Build() - - dynamicClient := dynamicfake.NewSimpleDynamicClient(testScheme, dynamicObjects...) - - mapping := &meta.RESTMapping{ - Resource: schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}, - GroupVersionKind: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"}, - Scope: meta.RESTScopeNamespace, - } - - return &RestoreJobReconciler{ - Client: fakeClient, - Interface: dynamicClient, - RESTMapper: &mockRESTMapper{mapping: mapping}, - Scheme: testScheme, - Recorder: record.NewFakeRecorder(100), - } -} - -// newTestRestoreJobReconciler builds a RestoreJobReconciler with fake clients for testing. -func newTestRestoreJobReconciler(t *testing.T, objects ...client.Object) *RestoreJobReconciler { - t.Helper() - testScheme := runtime.NewScheme() - _ = scheme.AddToScheme(testScheme) - _ = backupsv1alpha1.AddToScheme(testScheme) - _ = velerov1.AddToScheme(testScheme) - - fakeClient := clientfake.NewClientBuilder(). - WithScheme(testScheme). - WithObjects(objects...). - Build() - - dynamicClient := dynamicfake.NewSimpleDynamicClient(testScheme) - - mapping := &meta.RESTMapping{ - Resource: schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}, - GroupVersionKind: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"}, - Scope: meta.RESTScopeNamespace, - } - - return &RestoreJobReconciler{ - Client: fakeClient, - Interface: dynamicClient, - RESTMapper: &mockRESTMapper{mapping: mapping}, - Scheme: testScheme, - Recorder: record.NewFakeRecorder(100), - } -} - -func TestPrepareForRestore_KeepOriginalPVCFalse_SkipsRename(t *testing.T) { - ns := "tenant-root" - - // Create a PVC that would be renamed if keepOriginalPVC were true - pvc := &corev1.PersistentVolumeClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: "vm-disk-ubuntu-source", - Namespace: ns, - }, - Spec: corev1.PersistentVolumeClaimSpec{}, - } - - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{ - Name: "restore-test", - Namespace: ns, - }, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "my-backup"}, - }, - } - - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-backup", - Namespace: ns, - }, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-vm", - }, - }, - } - - // underlyingResources with a DataVolume referencing the PVC - urData := vmInstanceResources{ - DataVolumes: []backupsv1alpha1.DataVolumeResource{ - {DataVolumeName: "vm-disk-ubuntu-source", ApplicationName: "ubuntu-source"}, - }, - } - urRaw, _ := json.Marshal(urData) - ur := &runtime.RawExtension{Raw: urRaw} - - target := restoreTarget{ - Namespace: ns, - AppName: "test-vm", - AppKind: "VMInstance", - IsCopy: false, - } - - // keepOriginalPVC = false → PVCs should NOT be renamed - opts := RestoreOptions{ - KeepOriginalPVC: boolPtr(false), - } - - reconciler := newTestRestoreJobReconciler(t, pvc, restoreJob, backup) - - ctx := context.Background() - ready, _, err := reconciler.prepareForRestore(ctx, restoreJob, backup, ur, target, opts) - if err != nil { - t.Fatalf("prepareForRestore() error = %v", err) - } - if !ready { - t.Fatal("expected ready=true, got false") - } - - // Verify the original PVC still exists with its original name (not renamed) - origPVC := &corev1.PersistentVolumeClaim{} - err = reconciler.Get(ctx, client.ObjectKey{Namespace: ns, Name: "vm-disk-ubuntu-source"}, origPVC) - if err != nil { - t.Errorf("original PVC should still exist with original name when keepOriginalPVC=false, got error: %v", err) - } - - // Verify no -orig PVC was created - origSuffix := "-orig-" + shortHash(restoreJob.Name) - renamedPVC := &corev1.PersistentVolumeClaim{} - err = reconciler.Get(ctx, client.ObjectKey{Namespace: ns, Name: "vm-disk-ubuntu-source" + origSuffix}, renamedPVC) - if err == nil { - t.Error("PVC should NOT have been renamed when keepOriginalPVC=false, but found renamed PVC") - } -} - -func TestResolveRestoreTarget_VMDisk_CommonRestoreOptions(t *testing.T) { - tests := []struct { - name string - targetNS string - wantIsCopy bool - wantNamespace string - }{ - { - name: "VMDisk in-place restore when targetNamespace is omitted", - targetNS: "", - wantIsCopy: false, - wantNamespace: "tenant-root", - }, - { - name: "VMDisk cross-namespace restore when targetNamespace differs", - targetNS: "tenant-copy", - wantIsCopy: true, - wantNamespace: "tenant-copy", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{ - Name: "restore-vmdisk", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "disk-backup"}, - TargetApplicationRef: &corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMDisk", - Name: "ubuntu-source", - }, - }, - } - - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{ - Name: "disk-backup", - Namespace: "tenant-root", - }, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMDisk", - Name: "ubuntu-source", - }, - }, - } - - // VMDisk uses only CommonRestoreOptions (no VMI-specific fields) - opts := RestoreOptions{ - CommonRestoreOptions: CommonRestoreOptions{ - TargetNamespace: tt.targetNS, - }, - } - - target := resolveRestoreTarget(restoreJob, backup, opts) - - if target.IsCopy != tt.wantIsCopy { - t.Errorf("IsCopy = %v, want %v", target.IsCopy, tt.wantIsCopy) - } - if target.Namespace != tt.wantNamespace { - t.Errorf("Namespace = %q, want %q", target.Namespace, tt.wantNamespace) - } - if target.AppKind != "VMDisk" { - t.Errorf("AppKind = %q, want 'VMDisk'", target.AppKind) - } - if target.AppName != "ubuntu-source" { - t.Errorf("AppName = %q, want 'ubuntu-source'", target.AppName) - } - }) - } -} - -func TestParseRestoreOptions_VMDiskOnlyCommonFields(t *testing.T) { - // Simulate a VMDisk restore where only CommonRestoreOptions fields are set - raw, _ := json.Marshal(map[string]interface{}{ - "targetNamespace": "tenant-copy", - "failIfTargetExists": true, - }) - ext := &runtime.RawExtension{Raw: raw} - - opts, err := parseRestoreOptions(ext) - if err != nil { - t.Fatalf("parseRestoreOptions() error = %v", err) - } - - if opts.TargetNamespace != "tenant-copy" { - t.Errorf("TargetNamespace = %q, want 'tenant-copy'", opts.TargetNamespace) - } - if !opts.GetFailIfTargetExists() { - t.Error("GetFailIfTargetExists() = false, want true") - } - // VMI-specific fields should be nil (not set by VMDisk options) - if opts.KeepOriginalPVC != nil { - t.Errorf("KeepOriginalPVC should be nil for VMDisk options, got %v", *opts.KeepOriginalPVC) - } - if opts.KeepOriginalIpAndMac != nil { - t.Errorf("KeepOriginalIpAndMac should be nil for VMDisk options, got %v", *opts.KeepOriginalIpAndMac) - } -} - -func TestRestoreOptions_Defaults(t *testing.T) { - t.Run("nil options default all bools to true", func(t *testing.T) { - opts, err := parseRestoreOptions(nil) - if err != nil { - t.Fatalf("parseRestoreOptions(nil) error = %v", err) - } - - if opts.TargetNamespace != "" { - t.Errorf("TargetNamespace default should be empty, got %q", opts.TargetNamespace) - } - if !opts.GetFailIfTargetExists() { - t.Error("GetFailIfTargetExists() should default to true") - } - if !opts.GetKeepOriginalPVC() { - t.Error("GetKeepOriginalPVC() should default to true") - } - if !opts.GetKeepOriginalIpAndMac() { - t.Error("GetKeepOriginalIpAndMac() should default to true") - } - }) - - t.Run("empty JSON defaults all bools to true", func(t *testing.T) { - raw, _ := json.Marshal(map[string]interface{}{}) - opts, err := parseRestoreOptions(&runtime.RawExtension{Raw: raw}) - if err != nil { - t.Fatalf("parseRestoreOptions({}) error = %v", err) - } - - if !opts.GetFailIfTargetExists() { - t.Error("GetFailIfTargetExists() should default to true") - } - if !opts.GetKeepOriginalPVC() { - t.Error("GetKeepOriginalPVC() should default to true") - } - if !opts.GetKeepOriginalIpAndMac() { - t.Error("GetKeepOriginalIpAndMac() should default to true") - } - }) - - t.Run("explicit false overrides defaults", func(t *testing.T) { - raw, _ := json.Marshal(map[string]interface{}{ - "failIfTargetExists": false, - "keepOriginalPVC": false, - "keepOriginalIpAndMac": false, - }) - opts, err := parseRestoreOptions(&runtime.RawExtension{Raw: raw}) - if err != nil { - t.Fatalf("parseRestoreOptions() error = %v", err) - } - - if opts.GetFailIfTargetExists() { - t.Error("GetFailIfTargetExists() should be false when explicitly set") - } - if opts.GetKeepOriginalPVC() { - t.Error("GetKeepOriginalPVC() should be false when explicitly set") - } - if opts.GetKeepOriginalIpAndMac() { - t.Error("GetKeepOriginalIpAndMac() should be false when explicitly set") - } - }) -} - -func TestResolveRestoreTarget_IsRenamed(t *testing.T) { - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-alpine", - }, - }, - } - - t.Run("same name is not renamed", func(t *testing.T) { - rj := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "bk"}, - TargetApplicationRef: &corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-alpine", - }, - }, - } - target := resolveRestoreTarget(rj, backup, RestoreOptions{ - CommonRestoreOptions: CommonRestoreOptions{TargetNamespace: "tenant-foo"}, - }) - if target.IsRenamed { - t.Error("IsRenamed should be false when names match") - } - }) - - t.Run("different name is renamed", func(t *testing.T) { - rj := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "bk"}, - TargetApplicationRef: &corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-new", - }, - }, - } - target := resolveRestoreTarget(rj, backup, RestoreOptions{ - CommonRestoreOptions: CommonRestoreOptions{TargetNamespace: "tenant-foo"}, - }) - if !target.IsRenamed { - t.Error("IsRenamed should be true when names differ") - } - if target.AppName != "test-new" { - t.Errorf("AppName = %q, want 'test-new'", target.AppName) - } - if !target.IsCopy { - t.Error("IsCopy should be true") - } - }) - - t.Run("no targetApplicationRef is not renamed", func(t *testing.T) { - rj := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "bk"}, - }, - } - target := resolveRestoreTarget(rj, backup, RestoreOptions{ - CommonRestoreOptions: CommonRestoreOptions{TargetNamespace: "tenant-foo"}, - }) - if target.IsRenamed { - t.Error("IsRenamed should be false when targetApplicationRef is nil") - } - if target.AppName != "test-alpine" { - t.Errorf("AppName = %q, want 'test-alpine'", target.AppName) - } - }) -} - -// makeUnstructuredHelmRelease creates an unstructured HelmRelease for dynamic client tests. -func makeUnstructuredHelmRelease(name, namespace string, labels map[string]string) *unstructured.Unstructured { - hr := &unstructured.Unstructured{} - hr.SetAPIVersion("helm.toolkit.fluxcd.io/v2") - hr.SetKind("HelmRelease") - hr.SetName(name) - hr.SetNamespace(namespace) - hr.SetLabels(labels) - return hr -} - -func TestPostRestoreRename_RenamesHelmRelease(t *testing.T) { - ns := "tenant-foo" - sourceHR := makeUnstructuredHelmRelease("vm-instance-test-alpine", ns, map[string]string{ - appNameLabel: "test-alpine", - "app.kubernetes.io/instance": "vm-instance-test-alpine", - "helm.toolkit.fluxcd.io/name": "vm-instance-test-alpine", - }) - - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj-rename", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "bk"}, - }, - } - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-alpine", - }, - }, - } - target := restoreTarget{ - Namespace: ns, - AppName: "test-new", - AppKind: "VMInstance", - IsCopy: true, - IsRenamed: true, - } - - reconciler := newTestRestoreJobReconcilerWithDynamic(t, []runtime.Object{sourceHR}, restoreJob, backup) - ctx := context.Background() - - err := reconciler.postRestoreRename(ctx, restoreJob, backup, target) - if err != nil { - t.Fatalf("postRestoreRename() error = %v", err) - } - - hrClient := reconciler.Resource(helmReleaseGVR).Namespace(ns) - - // New HelmRelease should exist with target name - newHR, err := hrClient.Get(ctx, "vm-instance-test-new", metav1.GetOptions{}) - if err != nil { - t.Fatalf("new HelmRelease vm-instance-test-new not found: %v", err) - } - - // Check labels were updated - labels := newHR.GetLabels() - if labels[appNameLabel] != "test-new" { - t.Errorf("label %s = %q, want 'test-new'", appNameLabel, labels[appNameLabel]) - } - if labels["app.kubernetes.io/instance"] != "vm-instance-test-new" { - t.Errorf("label app.kubernetes.io/instance = %q, want 'vm-instance-test-new'", labels["app.kubernetes.io/instance"]) - } - if labels["helm.toolkit.fluxcd.io/name"] != "vm-instance-test-new" { - t.Errorf("label helm.toolkit.fluxcd.io/name = %q, want 'vm-instance-test-new'", labels["helm.toolkit.fluxcd.io/name"]) - } - - // Old HelmRelease should be deleted - _, err = hrClient.Get(ctx, "vm-instance-test-alpine", metav1.GetOptions{}) - if err == nil { - t.Error("old HelmRelease vm-instance-test-alpine should have been deleted") - } -} - -func TestPostRestoreRename_SkipsWhenSourceNotFound(t *testing.T) { - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj-rename", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "bk"}, - }, - } - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-alpine", - }, - }, - } - target := restoreTarget{ - Namespace: "tenant-foo", - AppName: "test-new", - AppKind: "VMInstance", - IsCopy: true, - IsRenamed: true, - } - - // No HelmRelease in dynamic client — should skip gracefully - reconciler := newTestRestoreJobReconcilerWithDynamic(t, nil, restoreJob, backup) - ctx := context.Background() - - err := reconciler.postRestoreRename(ctx, restoreJob, backup, target) - if err != nil { - t.Fatalf("postRestoreRename() should skip gracefully when source HR not found, got error: %v", err) - } -} - -func TestPostRestoreRename_IdempotentWhenTargetExists(t *testing.T) { - ns := "tenant-foo" - sourceHR := makeUnstructuredHelmRelease("vm-instance-test-alpine", ns, map[string]string{ - appNameLabel: "test-alpine", - }) - // Target already exists (e.g. from a previous reconcile) - targetHR := makeUnstructuredHelmRelease("vm-instance-test-new", ns, map[string]string{ - appNameLabel: "test-new", - }) - - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj-rename", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "bk"}, - }, - } - backup := &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: "VMInstance", - Name: "test-alpine", - }, - }, - } - target := restoreTarget{ - Namespace: ns, - AppName: "test-new", - AppKind: "VMInstance", - IsCopy: true, - IsRenamed: true, - } - - reconciler := newTestRestoreJobReconcilerWithDynamic(t, []runtime.Object{sourceHR, targetHR}, restoreJob, backup) - ctx := context.Background() - - err := reconciler.postRestoreRename(ctx, restoreJob, backup, target) - if err != nil { - t.Fatalf("postRestoreRename() should be idempotent, got error: %v", err) - } - - hrClient := reconciler.Resource(helmReleaseGVR).Namespace(ns) - - // Target should still exist - _, err = hrClient.Get(ctx, "vm-instance-test-new", metav1.GetOptions{}) - if err != nil { - t.Fatalf("target HelmRelease should exist: %v", err) - } - - // Source should be deleted - _, err = hrClient.Get(ctx, "vm-instance-test-alpine", metav1.GetOptions{}) - if err == nil { - t.Error("source HelmRelease should have been deleted") - } -} - -// --- failIfTargetExists enforcement tests --- - -func TestTargetHelmReleaseExists_ReturnsTrueWhenPresent(t *testing.T) { - ns := "tenant-copy" - hr := makeUnstructuredHelmRelease("vm-instance-test", ns, nil) - - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - } - backup := &backupsv1alpha1.Backup{ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}} - - reconciler := newTestRestoreJobReconcilerWithDynamic(t, []runtime.Object{hr}, restoreJob, backup) - ctx := context.Background() - - exists, err := reconciler.targetHelmReleaseExists(ctx, vmInstanceKind, "vm-instance-test", ns) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !exists { - t.Error("expected exists=true when HelmRelease is present") - } -} - -func TestTargetHelmReleaseExists_ReturnsFalseWhenAbsent(t *testing.T) { - ns := "tenant-copy" - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - } - backup := &backupsv1alpha1.Backup{ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}} - - reconciler := newTestRestoreJobReconcilerWithDynamic(t, nil, restoreJob, backup) - ctx := context.Background() - - exists, err := reconciler.targetHelmReleaseExists(ctx, vmInstanceKind, "vm-instance-test", ns) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if exists { - t.Error("expected exists=false when HelmRelease is absent") - } -} - -func TestTargetHelmReleaseExists_UnsupportedKindViaHelper(t *testing.T) { - ns := "tenant-copy" - // Even though a HR exists, unsupported kinds produce an empty hrName - // from helmReleaseNameForApp, which makes targetHelmReleaseExists return false. - hr := makeUnstructuredHelmRelease("vm-instance-test", ns, nil) - - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - } - backup := &backupsv1alpha1.Backup{ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}} - - reconciler := newTestRestoreJobReconcilerWithDynamic(t, []runtime.Object{hr}, restoreJob, backup) - ctx := context.Background() - - // Unsupported kinds get empty hrName from the helper - hrName := helmReleaseNameForApp("MariaDB", "mydb") - exists, err := reconciler.targetHelmReleaseExists(ctx, "MariaDB", hrName, ns) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if exists { - t.Error("expected exists=false for unsupported kind (empty hrName)") - } -} - -// --- createResourceModifiersConfigMap tests --- - -func makeTestBackup(ns, appName, appKind string) *backupsv1alpha1.Backup { - return &backupsv1alpha1.Backup{ - ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: ns}, - Spec: backupsv1alpha1.BackupSpec{ - ApplicationRef: corev1.TypedLocalObjectReference{ - APIGroup: stringPtr("apps.cozystack.io"), - Kind: appKind, - Name: appName, - }, - }, - } -} - -func makeTestRestoreJob(ns, name string) *backupsv1alpha1.RestoreJob { - return &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns}, - Spec: backupsv1alpha1.RestoreJobSpec{ - BackupRef: corev1.LocalObjectReference{Name: "bk"}, - }, - } -} - -func makeVMInstanceUR(ip, mac string, dvs []backupsv1alpha1.DataVolumeResource) *runtime.RawExtension { - data := vmInstanceResources{IP: ip, MAC: mac, DataVolumes: dvs} - raw, _ := json.Marshal(data) - return &runtime.RawExtension{Raw: raw} -} - -func TestCreateResourceModifiersConfigMap_InPlace_WithOVN(t *testing.T) { - ns := "tenant-root" - restoreJob := makeTestRestoreJob(ns, "rj-inplace") - backup := makeTestBackup(ns, "test-vm", "VMInstance") - - ur := makeVMInstanceUR("10.0.0.5", "aa:bb:cc:dd:ee:ff", nil) - target := restoreTarget{Namespace: ns, AppName: "test-vm", AppKind: "VMInstance", IsCopy: false} - opts := RestoreOptions{} // defaults: keepOriginalIpAndMac=true - - reconciler := newTestRestoreJobReconciler(t, restoreJob, backup) - ctx := context.Background() - - cm, err := reconciler.createResourceModifiersConfigMap(ctx, restoreJob, backup, ur, target, opts) - if err != nil { - t.Fatalf("createResourceModifiersConfigMap() error = %v", err) - } - if cm == nil { - t.Fatal("expected non-nil ConfigMap") - } - - rulesYAML, ok := cm.Data["resource-modifier-rules.yaml"] - if !ok { - t.Fatal("ConfigMap missing resource-modifier-rules.yaml key") - } - - // Should contain PVC adoption annotation - if !containsString(rulesYAML, cdiAllowClaimAdoption) { - t.Error("expected PVC adoption annotation in rules") - } - // Should contain OVN IP annotation (keepOriginalIpAndMac defaults to true) - if !containsString(rulesYAML, ovnIPAnnotation) { - t.Error("expected OVN IP annotation in rules for in-place restore with IP") - } - // Should NOT contain selector removal (in-place, not copy) - if containsString(rulesYAML, "/spec/selector") { - t.Error("selector removal rule should not be present for in-place restore") - } -} - -func TestCreateResourceModifiersConfigMap_Copy_NoOVN(t *testing.T) { - sourceNS := "tenant-root" - targetNS := "tenant-copy" - restoreJob := makeTestRestoreJob(sourceNS, "rj-copy") - backup := makeTestBackup(sourceNS, "test-vm", "VMInstance") - - // Copy restore: keepOriginalIpAndMac=false, no OVN annotations on copy - opts := RestoreOptions{ - KeepOriginalIpAndMac: boolPtr(false), - } - ur := makeVMInstanceUR("10.0.0.5", "aa:bb:cc:dd:ee:ff", nil) - target := restoreTarget{Namespace: targetNS, AppName: "test-vm", AppKind: "VMInstance", IsCopy: true} - - reconciler := newTestRestoreJobReconciler(t, restoreJob, backup) - ctx := context.Background() - - cm, err := reconciler.createResourceModifiersConfigMap(ctx, restoreJob, backup, ur, target, opts) - if err != nil { - t.Fatalf("createResourceModifiersConfigMap() error = %v", err) - } - - rulesYAML := cm.Data["resource-modifier-rules.yaml"] - - // Should contain PVC adoption annotation - if !containsString(rulesYAML, cdiAllowClaimAdoption) { - t.Error("expected PVC adoption annotation in rules") - } - // Should contain merge patch nulling out selector and volumeName (copy restore) - if !containsString(rulesYAML, "selector: null") { - t.Error("expected selector: null merge patch for copy restore") - } - if !containsString(rulesYAML, "volumeName: null") { - t.Error("expected volumeName: null merge patch for copy restore") - } - // Should NOT contain OVN annotations (keepOriginalIpAndMac=false) - if containsString(rulesYAML, ovnIPAnnotation) { - t.Error("OVN IP annotation should not be present when keepOriginalIpAndMac=false") - } -} - -func TestCreateResourceModifiersConfigMap_AlreadyExists_IsIdempotent(t *testing.T) { - ns := "tenant-root" - restoreJob := makeTestRestoreJob(ns, "rj-idem") - backup := makeTestBackup(ns, "test-vm", "VMInstance") - - target := restoreTarget{Namespace: ns, AppName: "test-vm", AppKind: "VMInstance", IsCopy: false} - opts := RestoreOptions{} - ur := makeVMInstanceUR("", "", nil) - - reconciler := newTestRestoreJobReconciler(t, restoreJob, backup) - ctx := context.Background() - - // First call creates the ConfigMap. - cm1, err := reconciler.createResourceModifiersConfigMap(ctx, restoreJob, backup, ur, target, opts) - if err != nil { - t.Fatalf("first call error = %v", err) - } - - // Second call must not error (AlreadyExists → update path). - cm2, err := reconciler.createResourceModifiersConfigMap(ctx, restoreJob, backup, ur, target, opts) - if err != nil { - t.Fatalf("second call error = %v", err) - } - if cm1.Name != cm2.Name { - t.Errorf("ConfigMap name changed: %q → %q", cm1.Name, cm2.Name) - } -} - -// --- helmReleaseNameForApp tests --- - -func TestHelmReleaseNameForApp(t *testing.T) { - tests := []struct { - kind, name, want string - }{ - {vmInstanceKind, "test-alpine", "vm-instance-test-alpine"}, - {vmDiskAppKind, "ubuntu-source", "vm-disk-ubuntu-source"}, - {"MariaDB", "mydb", ""}, - } - for _, tt := range tests { - t.Run(tt.kind+"/"+tt.name, func(t *testing.T) { - got := helmReleaseNameForApp(tt.kind, tt.name) - if got != tt.want { - t.Errorf("helmReleaseNameForApp(%q, %q) = %q, want %q", tt.kind, tt.name, got, tt.want) - } - }) - } -} - -func TestTargetHelmReleaseExists_VMDisk(t *testing.T) { - ns := "tenant-copy" - hr := makeUnstructuredHelmRelease("vm-disk-ubuntu-source", ns, nil) - - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - } - backup := &backupsv1alpha1.Backup{ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}} - - reconciler := newTestRestoreJobReconcilerWithDynamic(t, []runtime.Object{hr}, restoreJob, backup) - ctx := context.Background() - - hrName := helmReleaseNameForApp(vmDiskAppKind, "ubuntu-source") - exists, err := reconciler.targetHelmReleaseExists(ctx, vmDiskAppKind, hrName, ns) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !exists { - t.Error("expected exists=true for VMDisk HelmRelease") - } -} - -func TestTargetHelmReleaseExists_UnsupportedKind_ReturnsFalse(t *testing.T) { - restoreJob := &backupsv1alpha1.RestoreJob{ - ObjectMeta: metav1.ObjectMeta{Name: "rj", Namespace: "tenant-root"}, - } - backup := &backupsv1alpha1.Backup{ObjectMeta: metav1.ObjectMeta{Name: "bk", Namespace: "tenant-root"}} - - reconciler := newTestRestoreJobReconcilerWithDynamic(t, nil, restoreJob, backup) - ctx := context.Background() - - // Unsupported kinds produce empty hrName which returns false - hrName := helmReleaseNameForApp("MariaDB", "mydb") - exists, err := reconciler.targetHelmReleaseExists(ctx, "MariaDB", hrName, "tenant-copy") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if exists { - t.Error("expected exists=false for unsupported kind") - } -} - -// --- ResourceModifier merge patch test for copy restore --- - -func TestCreateResourceModifiersConfigMap_Copy_UsesMergePatchForPVC(t *testing.T) { - sourceNS := "tenant-root" - targetNS := "tenant-copy" - restoreJob := makeTestRestoreJob(sourceNS, "rj-copy-merge") - backup := makeTestBackup(sourceNS, "test-vm", "VMInstance") - - opts := RestoreOptions{KeepOriginalIpAndMac: boolPtr(false)} - ur := makeVMInstanceUR("", "", nil) - target := restoreTarget{Namespace: targetNS, AppName: "test-vm", AppKind: "VMInstance", IsCopy: true} - - reconciler := newTestRestoreJobReconciler(t, restoreJob, backup) - ctx := context.Background() - - cm, err := reconciler.createResourceModifiersConfigMap(ctx, restoreJob, backup, ur, target, opts) - if err != nil { - t.Fatalf("createResourceModifiersConfigMap() error = %v", err) - } - - rulesYAML := cm.Data["resource-modifier-rules.yaml"] - - // Should use merge patch (patchData with null), NOT JSON patch (operation: remove) - if containsString(rulesYAML, "operation: remove") { - t.Error("should use merge patch instead of JSON Patch remove for PVC fields") - } - // The merge patch should null out selector and volumeName - if !containsString(rulesYAML, "selector: null") { - t.Error("expected selector: null in merge patch") - } - if !containsString(rulesYAML, "volumeName: null") { - t.Error("expected volumeName: null in merge patch") - } -} - -// containsString reports whether substr appears in s. -func containsString(s, substr string) bool { - if len(substr) == 0 || len(s) < len(substr) { - return false - } - for i := 0; i <= len(s)-len(substr); i++ { - if s[i:i+len(substr)] == substr { - return true - } - } - return false -} diff --git a/internal/controller/applicationdefinition_controller.go b/internal/controller/applicationdefinition_controller.go index 6ce25249..e5920b4c 100644 --- a/internal/controller/applicationdefinition_controller.go +++ b/internal/controller/applicationdefinition_controller.go @@ -32,6 +32,8 @@ type ApplicationDefinitionReconciler struct { mu sync.Mutex lastEvent time.Time lastHandled time.Time + + CozystackAPIKind string } func (r *ApplicationDefinitionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { @@ -65,7 +67,7 @@ func (r *ApplicationDefinitionReconciler) SetupWithManager(mgr ctrl.Manager) err } type appDefHashView struct { - Name string `json:"name"` + Name string `json:"name"` Spec cozyv1alpha1.ApplicationDefinitionSpec `json:"spec"` } @@ -153,13 +155,23 @@ func (r *ApplicationDefinitionReconciler) getWorkload( ctx context.Context, key types.NamespacedName, ) (tpl *corev1.PodTemplateSpec, obj client.Object, patch client.Patch, err error) { - dep := &appsv1.Deployment{} - if err := r.Get(ctx, key, dep); err != nil { - return nil, nil, nil, err + if r.CozystackAPIKind == "Deployment" { + dep := &appsv1.Deployment{} + if err := r.Get(ctx, key, dep); err != nil { + return nil, nil, nil, err + } + obj = dep + tpl = &dep.Spec.Template + patch = client.MergeFrom(dep.DeepCopy()) + } else { + ds := &appsv1.DaemonSet{} + if err := r.Get(ctx, key, ds); err != nil { + return nil, nil, nil, err + } + obj = ds + tpl = &ds.Spec.Template + patch = client.MergeFrom(ds.DeepCopy()) } - obj = dep - tpl = &dep.Spec.Template - patch = client.MergeFrom(dep.DeepCopy()) if tpl.Annotations == nil { tpl.Annotations = make(map[string]string) } diff --git a/internal/controller/dashboard/README.md b/internal/controller/dashboard/README.md index 2efe9f45..c3b2152e 100644 --- a/internal/controller/dashboard/README.md +++ b/internal/controller/dashboard/README.md @@ -156,7 +156,7 @@ menuItems = append(menuItems, map[string]any{ map[string]any{ "key": "{plural}", "label": "{ResourceLabel}", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/{group}/{version}/{plural}", + "link": "/openapi-ui/{clusterName}/{namespace}/api-table/{group}/{version}/{plural}", }, }, }), @@ -174,7 +174,7 @@ menuItems = append(menuItems, map[string]any{ **Important Notes**: - The sidebar tag (`{lowercase-kind}-sidebar`) must match what the Factory uses -- The link format: `/openapi-ui/{cluster}/{namespace}/api-table/{group}/{version}/{plural}` +- The link format: `/openapi-ui/{clusterName}/{namespace}/api-table/{group}/{version}/{plural}` - All sidebars share the same `keysAndTags` and `menuItems`, so changes affect all sidebar instances ### Step 4: Verify Integration diff --git a/internal/controller/dashboard/breadcrumb.go b/internal/controller/dashboard/breadcrumb.go index 6d65f2db..aadcacac 100644 --- a/internal/controller/dashboard/breadcrumb.go +++ b/internal/controller/dashboard/breadcrumb.go @@ -33,12 +33,12 @@ func (m *Manager) ensureBreadcrumb(ctx context.Context, crd *cozyv1alpha1.Applic key := plural // e.g., "virtualmachines" label := labelPlural - link := fmt.Sprintf("/openapi-ui/{cluster}/{namespace}/api-table/%s/%s/%s", strings.ToLower(group), strings.ToLower(version), plural) + link := fmt.Sprintf("/openapi-ui/{clusterName}/{namespace}/api-table/%s/%s/%s", strings.ToLower(group), strings.ToLower(version), plural) // If this is a module, change the first breadcrumb item to "Tenant Modules" if crd.Spec.Dashboard != nil && crd.Spec.Dashboard.Module { key = "tenantmodules" label = "Tenant Modules" - link = "/openapi-ui/{cluster}/{namespace}/api-table/core.cozystack.io/v1alpha1/tenantmodules" + link = "/openapi-ui/{clusterName}/{namespace}/api-table/core.cozystack.io/v1alpha1/tenantmodules" } items := []any{ diff --git a/internal/controller/dashboard/customformsoverride.go b/internal/controller/dashboard/customformsoverride.go index 0a20ae71..60bc82fc 100644 --- a/internal/controller/dashboard/customformsoverride.go +++ b/internal/controller/dashboard/customformsoverride.go @@ -46,11 +46,8 @@ func (m *Manager) ensureCustomFormsOverride(ctx context.Context, crd *cozyv1alph } } - // Parse OpenAPI schema once for reuse - l := log.FromContext(ctx) - openAPIProps := parseOpenAPIProperties(crd.Spec.Application.OpenAPISchema) - // Build schema with multilineString for string fields without enum + l := log.FromContext(ctx) schema, err := buildMultilineStringSchema(crd.Spec.Application.OpenAPISchema) if err != nil { // If schema parsing fails, log the error and use an empty schema @@ -58,12 +55,6 @@ func (m *Manager) ensureCustomFormsOverride(ctx context.Context, crd *cozyv1alph schema = map[string]any{} } - // Override specific fields with API-backed dropdowns (listInput type) - applyListInputOverrides(schema, kind, openAPIProps) - - // Hide deprecated fields from the UI - hidden = append(hidden, hiddenDeprecatedFields(kind)...) - spec := map[string]any{ "customizationId": customizationID, "hidden": hidden, @@ -93,58 +84,8 @@ func (m *Manager) ensureCustomFormsOverride(ctx context.Context, crd *cozyv1alph return err } -// ensureCFOMapping updates the CFOMapping resource to include a mapping for the given CRD -func (m *Manager) ensureCFOMapping(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) error { - g, v, kind := pickGVK(crd) - plural := pickPlural(kind, crd) - - resourcePath := fmt.Sprintf("/%s/%s/%s", g, v, plural) - customizationID := fmt.Sprintf("default-%s", resourcePath) - - obj := &dashv1alpha1.CFOMapping{} - obj.SetName("cfomapping") - - _, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error { - // Parse existing mappings - mappings := make(map[string]string) - if obj.Spec.JSON.Raw != nil { - var spec map[string]any - if err := json.Unmarshal(obj.Spec.JSON.Raw, &spec); err == nil { - if m, ok := spec["mappings"].(map[string]any); ok { - for k, val := range m { - if s, ok := val.(string); ok { - mappings[k] = s - } - } - } - } - } - - // Add/update the mapping for this CRD - mappings[resourcePath] = customizationID - - specData := map[string]any{ - "mappings": mappings, - } - b, err := json.Marshal(specData) - if err != nil { - return err - } - - newSpec := dashv1alpha1.ArbitrarySpec{JSON: apiextv1.JSON{Raw: b}} - if !compareArbitrarySpecs(obj.Spec, newSpec) { - obj.Spec = newSpec - } - return nil - }) - return err -} - // buildMultilineStringSchema parses OpenAPI schema and creates schema with multilineString -// for all string fields inside spec that don't have enum. -// It handles two structures: -// - properties.spec.properties (most resources) -// - properties.properties (VMDisk and similar resources without spec wrapper) +// for all string fields inside spec that don't have enum func buildMultilineStringSchema(openAPISchema string) (map[string]any, error) { if openAPISchema == "" { return map[string]any{}, nil @@ -164,25 +105,15 @@ func buildMultilineStringSchema(openAPISchema string) (map[string]any, error) { "properties": map[string]any{}, } - var specProps map[string]any - var hasSpec bool - - // First try to find properties under spec - if specProp, ok := props["spec"].(map[string]any); ok { - specProps, hasSpec = specProp["properties"].(map[string]any) + // Check if there's a spec property + specProp, ok := props["spec"].(map[string]any) + if !ok { + return map[string]any{}, nil } - // If no spec wrapper, use top-level properties directly (VMDisk pattern) - if !hasSpec { - specProps = props - // Still wrap in spec for consistency with applyListInputOverrides - schemaProps := schema["properties"].(map[string]any) - specSchema := map[string]any{ - "properties": map[string]any{}, - } - schemaProps["spec"] = specSchema - processSpecProperties(specProps, specSchema["properties"].(map[string]any)) - return schema, nil + specProps, ok := specProp["properties"].(map[string]any) + if !ok { + return map[string]any{}, nil } // Create spec.properties structure in schema @@ -198,206 +129,6 @@ func buildMultilineStringSchema(openAPISchema string) (map[string]any, error) { return schema, nil } -// applyListInputOverrides injects listInput type overrides into the schema -// for fields that should be rendered as API-backed dropdowns in the dashboard. -// openAPIProps are the parsed top-level properties from the OpenAPI schema. -func applyListInputOverrides(schema map[string]any, kind string, openAPIProps map[string]any) { - switch kind { - case "VMInstance": - specProps := ensureSchemaPath(schema, "spec") - field := map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/instancetype.kubevirt.io/v1beta1/virtualmachineclusterinstancetypes", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - "allowEmpty": true, - }, - } - if prop, _ := openAPIProps["instanceType"].(map[string]any); prop != nil { - if def := prop["default"]; def != nil { - field["default"] = def - } - } - specProps["instanceType"] = field - - // Override disks[].name to be an API-backed dropdown listing VMDisk resources - disksItemProps := ensureArrayItemProps(specProps, "disks") - disksItemProps["name"] = map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/apps.cozystack.io/v1alpha1/namespaces/{namespace}/vmdisks", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - }, - } - - // Override networks[].name to be an API-backed dropdown listing NetworkAttachmentDefinitions - networksItemProps := ensureArrayItemProps(specProps, "networks") - networksItemProps["name"] = map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/k8s.cni.cncf.io/v1/namespaces/{namespace}/network-attachment-definitions", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - }, - } - - case "ClickHouse", "Harbor", "HTTPCache", "Kubernetes", "MariaDB", "MongoDB", - "NATS", "OpenBAO", "Postgres", "Qdrant", "RabbitMQ", "Redis": - specProps := ensureSchemaPath(schema, "spec") - specProps["storageClass"] = storageClassListInput() - - case "VMDisk": - specProps := ensureSchemaPath(schema, "spec") - specProps["storageClass"] = storageClassListInput() - - // Override source.image.name to be an API-backed dropdown listing default images - if sourceObj, ok := specProps["source"].(map[string]any); ok { - if imgProps, ok := sourceObj["properties"].(map[string]any); ok { - if imgName, ok := imgProps["image"].(map[string]any); ok { - if imgNameProps, ok := imgName["properties"].(map[string]any); ok { - imgNameProps["name"] = map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/cdi.kubevirt.io/v1beta1/namespaces/cozy-public/datavolumes", - "keysToValue": []any{"metadata", "annotations", "vm-default-images.cozystack.io/name"}, - "keysToLabel": []any{"metadata", "annotations", "vm-default-images.cozystack.io/description"}, - }, - } - } - } - // Override source.disk.name to be an API-backed dropdown listing VMDisk resources - if diskName, ok := imgProps["disk"].(map[string]any); ok { - if diskNameProps, ok := diskName["properties"].(map[string]any); ok { - diskNameProps["name"] = map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/apps.cozystack.io/v1alpha1/namespaces/{namespace}/vmdisks", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - }, - } - } - } - } - } - - case "FoundationDB": - storageProps := ensureSchemaPath(schema, "spec", "storage") - storageProps["storageClass"] = storageClassListInput() - - case "Kafka": - kafkaProps := ensureSchemaPath(schema, "spec", "kafka") - kafkaProps["storageClass"] = storageClassListInput() - zkProps := ensureSchemaPath(schema, "spec", "zookeeper") - zkProps["storageClass"] = storageClassListInput() - - case "Tenant": - specProps := ensureSchemaPath(schema, "spec") - specProps["schedulingClass"] = schedulingClassListInput() - } -} - -// hiddenDeprecatedFields returns hidden paths for deprecated fields that should not -// appear in the dashboard UI for the given kind. -func hiddenDeprecatedFields(kind string) []any { - switch kind { - case "VMInstance": - return []any{ - []any{"spec", "subnets"}, - } - } - return nil -} - -// storageClassListInput returns a listInput field config for a storageClass dropdown -// backed by the cluster's available StorageClasses. -func storageClassListInput() map[string]any { - return map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/storage.k8s.io/v1/storageclasses", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - }, - } -} - -// schedulingClassListInput returns a listInput field config for a schedulingClass dropdown -// backed by the cluster's available SchedulingClass CRs. -func schedulingClassListInput() map[string]any { - return map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/cozystack.io/v1alpha1/schedulingclasses", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - "allowEmpty": true, - }, - } -} - -// ensureArrayItemProps ensures that parentProps[fieldName].items.properties exists -// and returns the items properties map. Used for overriding fields inside array items. -func ensureArrayItemProps(parentProps map[string]any, fieldName string) map[string]any { - field, ok := parentProps[fieldName].(map[string]any) - if !ok { - field = map[string]any{} - parentProps[fieldName] = field - } - items, ok := field["items"].(map[string]any) - if !ok { - items = map[string]any{} - field["items"] = items - } - props, ok := items["properties"].(map[string]any) - if !ok { - props = map[string]any{} - items["properties"] = props - } - return props -} - -// parseOpenAPIProperties parses the top-level properties from an OpenAPI schema JSON string. -func parseOpenAPIProperties(openAPISchema string) map[string]any { - if openAPISchema == "" { - return nil - } - var root map[string]any - if err := json.Unmarshal([]byte(openAPISchema), &root); err != nil { - return nil - } - props, _ := root["properties"].(map[string]any) - return props -} - -// ensureSchemaPath ensures the nested properties structure exists in a schema -// and returns the innermost properties map. -// e.g. ensureSchemaPath(schema, "spec") returns schema["properties"]["spec"]["properties"] -func ensureSchemaPath(schema map[string]any, segments ...string) map[string]any { - current := schema - for _, seg := range segments { - props, ok := current["properties"].(map[string]any) - if !ok { - props = map[string]any{} - current["properties"] = props - } - child, ok := props[seg].(map[string]any) - if !ok { - child = map[string]any{} - props[seg] = child - } - current = child - } - props, ok := current["properties"].(map[string]any) - if !ok { - props = map[string]any{} - current["properties"] = props - } - return props -} - // processSpecProperties recursively processes spec properties and adds multilineString type // for string fields without enum func processSpecProperties(props map[string]any, schemaProps map[string]any) { diff --git a/internal/controller/dashboard/customformsoverride_test.go b/internal/controller/dashboard/customformsoverride_test.go index 6a83d62e..9f7babe9 100644 --- a/internal/controller/dashboard/customformsoverride_test.go +++ b/internal/controller/dashboard/customformsoverride_test.go @@ -169,453 +169,3 @@ func TestBuildMultilineStringSchemaInvalidJSON(t *testing.T) { t.Errorf("Expected nil schema for invalid JSON, got %v", schema) } } - -func TestApplyListInputOverrides_VMInstance(t *testing.T) { - openAPIProps := map[string]any{ - "instanceType": map[string]any{"type": "string", "default": "u1.medium"}, - } - - schema := map[string]any{} - applyListInputOverrides(schema, "VMInstance", openAPIProps) - - specProps := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any) - instanceType, ok := specProps["instanceType"].(map[string]any) - if !ok { - t.Fatal("instanceType not found in schema.properties.spec.properties") - } - - if instanceType["type"] != "listInput" { - t.Errorf("expected type listInput, got %v", instanceType["type"]) - } - - if instanceType["default"] != "u1.medium" { - t.Errorf("expected default u1.medium, got %v", instanceType["default"]) - } - - customProps, ok := instanceType["customProps"].(map[string]any) - if !ok { - t.Fatal("customProps not found") - } - - expectedURI := "/api/clusters/{cluster}/k8s/apis/instancetype.kubevirt.io/v1beta1/virtualmachineclusterinstancetypes" - if customProps["valueUri"] != expectedURI { - t.Errorf("expected valueUri %s, got %v", expectedURI, customProps["valueUri"]) - } - - if customProps["allowEmpty"] != true { - t.Errorf("expected allowEmpty true, got %v", customProps["allowEmpty"]) - } - - // Check disks[].name is a listInput - disks, ok := specProps["disks"].(map[string]any) - if !ok { - t.Fatal("disks not found in schema.properties.spec.properties") - } - items, ok := disks["items"].(map[string]any) - if !ok { - t.Fatal("disks.items not found") - } - itemProps, ok := items["properties"].(map[string]any) - if !ok { - t.Fatal("disks.items.properties not found") - } - diskName, ok := itemProps["name"].(map[string]any) - if !ok { - t.Fatal("disks.items.properties.name not found") - } - if diskName["type"] != "listInput" { - t.Errorf("expected disks name type listInput, got %v", diskName["type"]) - } - diskCustomProps, ok := diskName["customProps"].(map[string]any) - if !ok { - t.Fatal("disks name customProps not found") - } - expectedDiskURI := "/api/clusters/{cluster}/k8s/apis/apps.cozystack.io/v1alpha1/namespaces/{namespace}/vmdisks" - if diskCustomProps["valueUri"] != expectedDiskURI { - t.Errorf("expected disks valueUri %s, got %v", expectedDiskURI, diskCustomProps["valueUri"]) - } - - // Check networks[].name is a listInput - networks, ok := specProps["networks"].(map[string]any) - if !ok { - t.Fatal("networks not found in schema.properties.spec.properties") - } - netItems, ok := networks["items"].(map[string]any) - if !ok { - t.Fatal("networks.items not found") - } - netItemProps, ok := netItems["properties"].(map[string]any) - if !ok { - t.Fatal("networks.items.properties not found") - } - netName, ok := netItemProps["name"].(map[string]any) - if !ok { - t.Fatal("networks.items.properties.name not found") - } - if netName["type"] != "listInput" { - t.Errorf("expected networks name type listInput, got %v", netName["type"]) - } - netCustomProps, ok := netName["customProps"].(map[string]any) - if !ok { - t.Fatal("networks name customProps not found") - } - expectedNetURI := "/api/clusters/{cluster}/k8s/apis/k8s.cni.cncf.io/v1/namespaces/{namespace}/network-attachment-definitions" - if netCustomProps["valueUri"] != expectedNetURI { - t.Errorf("expected networks valueUri %s, got %v", expectedNetURI, netCustomProps["valueUri"]) - } -} - -func TestHiddenDeprecatedFields_VMInstance(t *testing.T) { - hidden := hiddenDeprecatedFields("VMInstance") - if len(hidden) != 1 { - t.Fatalf("expected 1 hidden path, got %d", len(hidden)) - } - path, ok := hidden[0].([]any) - if !ok { - t.Fatal("hidden path is not []any") - } - if len(path) != 2 || path[0] != "spec" || path[1] != "subnets" { - t.Errorf("expected [spec subnets], got %v", path) - } -} - -func TestHiddenDeprecatedFields_UnknownKind(t *testing.T) { - hidden := hiddenDeprecatedFields("SomeOtherKind") - if hidden != nil { - t.Errorf("expected nil for unknown kind, got %v", hidden) - } -} - -func TestApplyListInputOverrides_StorageClassSimple(t *testing.T) { - for _, kind := range []string{ - "ClickHouse", "Harbor", "HTTPCache", "Kubernetes", "MariaDB", "MongoDB", - "NATS", "OpenBAO", "Postgres", "Qdrant", "RabbitMQ", "Redis", "VMDisk", - } { - t.Run(kind, func(t *testing.T) { - schema := map[string]any{} - applyListInputOverrides(schema, kind, map[string]any{}) - - specProps := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any) - sc, ok := specProps["storageClass"].(map[string]any) - if !ok { - t.Fatalf("storageClass not found in spec.properties for kind %s", kind) - } - assertStorageClassListInput(t, sc) - }) - } -} - -func TestApplyListInputOverrides_StorageClassFoundationDB(t *testing.T) { - schema := map[string]any{} - applyListInputOverrides(schema, "FoundationDB", map[string]any{}) - - storageProps := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any)["storage"].(map[string]any)["properties"].(map[string]any) - sc, ok := storageProps["storageClass"].(map[string]any) - if !ok { - t.Fatal("storageClass not found in spec.storage.properties") - } - assertStorageClassListInput(t, sc) -} - -func TestApplyListInputOverrides_VMDisk_SourceFields(t *testing.T) { - openAPISchema := `{ - "properties":{ - "optical":{"type":"boolean"}, - "source":{ - "type":"object", - "properties":{ - "image":{ - "type":"object", - "properties":{ - "name":{"type":"string"} - } - }, - "disk":{ - "type":"object", - "properties":{ - "name":{"type":"string"} - } - } - } - }, - "storage":{"type":"string"}, - "storageClass":{"type":"string"} - } - }` - - schema, err := buildMultilineStringSchema(openAPISchema) - if err != nil { - t.Fatalf("buildMultilineStringSchema failed: %v", err) - } - - applyListInputOverrides(schema, "VMDisk", map[string]any{}) - - specProps := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any) - - // Check storageClass - sc, ok := specProps["storageClass"].(map[string]any) - if !ok { - t.Fatal("storageClass not found in spec.properties") - } - assertStorageClassListInput(t, sc) - - // Check source.image.name listInput - // Structure: specProps["source"]["properties"]["image"]["properties"]["name"] - sourceObj, ok := specProps["source"].(map[string]any) - if !ok { - t.Fatal("source not found in spec.properties") - } - sourceObjProps, ok := sourceObj["properties"].(map[string]any) - if !ok { - t.Fatal("source.properties not found") - } - imageObj, ok := sourceObjProps["image"].(map[string]any) - if !ok { - t.Fatal("image not found in source.properties") - } - imageObjProps, ok := imageObj["properties"].(map[string]any) - if !ok { - t.Fatal("image.properties not found") - } - imgName, ok := imageObjProps["name"].(map[string]any) - if !ok { - t.Fatal("name not found in image.properties") - } - if imgName["type"] != "listInput" { - t.Errorf("expected type listInput, got %v", imgName["type"]) - } - imgNameCustomProps, ok := imgName["customProps"].(map[string]any) - if !ok { - t.Fatal("name.customProps not found") - } - expectedImageURI := "/api/clusters/{cluster}/k8s/apis/cdi.kubevirt.io/v1beta1/namespaces/cozy-public/datavolumes" - if imgNameCustomProps["valueUri"] != expectedImageURI { - t.Errorf("expected valueUri %s, got %v", expectedImageURI, imgNameCustomProps["valueUri"]) - } - - // Check source.disk.name listInput - diskObj, ok := sourceObjProps["disk"].(map[string]any) - if !ok { - t.Fatal("disk not found in source.properties") - } - diskObjProps, ok := diskObj["properties"].(map[string]any) - if !ok { - t.Fatal("disk.properties not found") - } - diskName, ok := diskObjProps["name"].(map[string]any) - if !ok { - t.Fatal("name not found in disk.properties") - } - if diskName["type"] != "listInput" { - t.Errorf("expected type listInput, got %v", diskName["type"]) - } - diskNameCustomProps, ok := diskName["customProps"].(map[string]any) - if !ok { - t.Fatal("disk name.customProps not found") - } - expectedDiskURI := "/api/clusters/{cluster}/k8s/apis/apps.cozystack.io/v1alpha1/namespaces/{namespace}/vmdisks" - if diskNameCustomProps["valueUri"] != expectedDiskURI { - t.Errorf("expected valueUri %s, got %v", expectedDiskURI, diskNameCustomProps["valueUri"]) - } -} - -func TestApplyListInputOverrides_StorageClassKafka(t *testing.T) { - schema := map[string]any{} - applyListInputOverrides(schema, "Kafka", map[string]any{}) - - specProps := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any) - - kafkaSC, ok := specProps["kafka"].(map[string]any)["properties"].(map[string]any)["storageClass"].(map[string]any) - if !ok { - t.Fatal("storageClass not found in spec.kafka.properties") - } - assertStorageClassListInput(t, kafkaSC) - - zkSC, ok := specProps["zookeeper"].(map[string]any)["properties"].(map[string]any)["storageClass"].(map[string]any) - if !ok { - t.Fatal("storageClass not found in spec.zookeeper.properties") - } - assertStorageClassListInput(t, zkSC) -} - -// assertStorageClassListInput verifies that a field is a correctly configured storageClass listInput. -func assertStorageClassListInput(t *testing.T, field map[string]any) { - t.Helper() - if field["type"] != "listInput" { - t.Errorf("expected type listInput, got %v", field["type"]) - } - customProps, ok := field["customProps"].(map[string]any) - if !ok { - t.Fatal("customProps not found") - } - expectedURI := "/api/clusters/{cluster}/k8s/apis/storage.k8s.io/v1/storageclasses" - if customProps["valueUri"] != expectedURI { - t.Errorf("expected valueUri %s, got %v", expectedURI, customProps["valueUri"]) - } -} - -func TestApplyListInputOverrides_UnknownKind(t *testing.T) { - schema := map[string]any{} - applyListInputOverrides(schema, "SomeOtherKind", map[string]any{}) - - if len(schema) != 0 { - t.Errorf("expected empty schema for unknown kind, got %v", schema) - } -} - -func TestApplyListInputOverrides_NoDefault(t *testing.T) { - openAPIProps := map[string]any{ - "instanceType": map[string]any{"type": "string"}, - } - - schema := map[string]any{} - applyListInputOverrides(schema, "VMInstance", openAPIProps) - - specProps := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any) - instanceType := specProps["instanceType"].(map[string]any) - - if _, exists := instanceType["default"]; exists { - t.Errorf("expected no default key, got %v", instanceType["default"]) - } -} - -func TestApplyListInputOverrides_MergesWithExistingSchema(t *testing.T) { - openAPIProps := map[string]any{ - "instanceType": map[string]any{"type": "string", "default": "u1.medium"}, - } - - // Simulate schema that already has spec.properties from buildMultilineStringSchema - schema := map[string]any{ - "properties": map[string]any{ - "spec": map[string]any{ - "properties": map[string]any{ - "otherField": map[string]any{"type": "multilineString"}, - }, - }, - }, - } - applyListInputOverrides(schema, "VMInstance", openAPIProps) - - specProps := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any) - - // instanceType should be added - if _, ok := specProps["instanceType"].(map[string]any); !ok { - t.Fatal("instanceType not found after override") - } - - // otherField should be preserved - otherField, ok := specProps["otherField"].(map[string]any) - if !ok { - t.Fatal("otherField was lost after override") - } - if otherField["type"] != "multilineString" { - t.Errorf("otherField type changed, got %v", otherField["type"]) - } -} - -func TestParseOpenAPIProperties(t *testing.T) { - t.Run("extracts properties", func(t *testing.T) { - props := parseOpenAPIProperties(`{"type":"object","properties":{"instanceType":{"type":"string","default":"u1.medium"}}}`) - field, _ := props["instanceType"].(map[string]any) - if field["default"] != "u1.medium" { - t.Errorf("expected default u1.medium, got %v", field["default"]) - } - }) - - t.Run("empty string", func(t *testing.T) { - if props := parseOpenAPIProperties(""); props != nil { - t.Errorf("expected nil, got %v", props) - } - }) - - t.Run("invalid JSON", func(t *testing.T) { - if props := parseOpenAPIProperties("{bad"); props != nil { - t.Errorf("expected nil, got %v", props) - } - }) - - t.Run("no properties key", func(t *testing.T) { - if props := parseOpenAPIProperties(`{"type":"object"}`); props != nil { - t.Errorf("expected nil, got %v", props) - } - }) -} - -func TestEnsureSchemaPath(t *testing.T) { - t.Run("creates path from empty schema", func(t *testing.T) { - schema := map[string]any{} - props := ensureSchemaPath(schema, "spec") - - props["field"] = "value" - - // Verify structure: schema.properties.spec.properties.field - got := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any)["field"] - if got != "value" { - t.Errorf("expected value, got %v", got) - } - }) - - t.Run("preserves existing nested properties", func(t *testing.T) { - schema := map[string]any{ - "properties": map[string]any{ - "spec": map[string]any{ - "properties": map[string]any{ - "existing": "keep", - }, - }, - }, - } - props := ensureSchemaPath(schema, "spec") - - if props["existing"] != "keep" { - t.Errorf("existing property lost, got %v", props["existing"]) - } - }) - - t.Run("multi-level path", func(t *testing.T) { - schema := map[string]any{} - props := ensureSchemaPath(schema, "spec", "nested") - - props["deep"] = true - - got := schema["properties"].(map[string]any)["spec"].(map[string]any)["properties"].(map[string]any)["nested"].(map[string]any)["properties"].(map[string]any)["deep"] - if got != true { - t.Errorf("expected true, got %v", got) - } - }) -} - -func TestEnsureArrayItemProps(t *testing.T) { - t.Run("creates from empty parent", func(t *testing.T) { - parent := map[string]any{} - props := ensureArrayItemProps(parent, "disks") - - props["name"] = map[string]any{"type": "listInput"} - - got := parent["disks"].(map[string]any)["items"].(map[string]any)["properties"].(map[string]any)["name"].(map[string]any)["type"] - if got != "listInput" { - t.Errorf("expected listInput, got %v", got) - } - }) - - t.Run("preserves existing item properties", func(t *testing.T) { - parent := map[string]any{ - "disks": map[string]any{ - "items": map[string]any{ - "properties": map[string]any{ - "bus": map[string]any{"type": "string"}, - }, - }, - }, - } - props := ensureArrayItemProps(parent, "disks") - props["name"] = map[string]any{"type": "listInput"} - - if props["bus"].(map[string]any)["type"] != "string" { - t.Error("existing bus property was lost") - } - if props["name"].(map[string]any)["type"] != "listInput" { - t.Error("name property was not added") - } - }) -} diff --git a/internal/controller/dashboard/factory.go b/internal/controller/dashboard/factory.go index fe0cadfd..e55aedc7 100644 --- a/internal/controller/dashboard/factory.go +++ b/internal/controller/dashboard/factory.go @@ -47,8 +47,7 @@ func (m *Manager) ensureFactory(ctx context.Context, crd *cozyv1alpha1.Applicati if prefix, ok := vncTabPrefix(kind); ok { tabs = append(tabs, vncTab(prefix)) } - tabs = append(tabs, eventsTab(kind)) - tabs = append(tabs, yamlTab(g, v, plural)) + tabs = append(tabs, yamlTab(plural)) // Use unified factory creation config := UnifiedResourceConfig{ @@ -161,11 +160,11 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "vpc-subnets-table", - "baseprefix": "/openapi-ui", - "cluster": "{2}", - "customizationId": "virtualprivatecloud-subnets", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/configmaps", + "id": "vpc-subnets-table", + "baseprefix": "/openapi-ui", + "clusterNamePartOfUrl": "{2}", + "customizationId": "virtualprivatecloud-subnets", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/configmaps", "fieldSelector": map[string]any{ "metadata.name": "virtualprivatecloud-{6}-subnets", }, @@ -189,12 +188,12 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "resource-quotas-table", - "baseprefix": "/openapi-ui", - "cluster": "{2}", - "customizationId": "factory-resource-quotas", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{reqsJsonPath[0]['.status.namespace']}/resourcequotas", - "pathToItems": []any{`items`}, + "id": "resource-quotas-table", + "baseprefix": "/openapi-ui", + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-resource-quotas", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{reqsJsonPath[0]['.status.namespace']}/resourcequotas", + "pathToItems": []any{`items`}, }, }, }), @@ -243,13 +242,13 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "conditions-table", - "fetchUrl": endpoint, - "cluster": "{2}", - "customizationId": "factory-status-conditions", - "baseprefix": "/openapi-ui", - "withoutControls": true, - "pathToItems": []any{"status", "conditions"}, + "id": "conditions-table", + "fetchUrl": endpoint, + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-status-conditions", + "baseprefix": "/openapi-ui", + "withoutControls": true, + "pathToItems": []any{"status", "conditions"}, }, }, }), @@ -265,12 +264,12 @@ func workloadsTab(kind string) map[string]any { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "workloads-table", - "fetchUrl": "/api/clusters/{2}/k8s/apis/cozystack.io/v1alpha1/namespaces/{3}/workloadmonitors", - "cluster": "{2}", - "baseprefix": "/openapi-ui", - "customizationId": "factory-details-v1alpha1.cozystack.io.workloadmonitors", - "pathToItems": []any{"items"}, + "id": "workloads-table", + "fetchUrl": "/api/clusters/{2}/k8s/apis/cozystack.io/v1alpha1/namespaces/{3}/workloadmonitors", + "clusterNamePartOfUrl": "{2}", + "baseprefix": "/openapi-ui", + "customizationId": "factory-details-v1alpha1.cozystack.io.workloadmonitors", + "pathToItems": []any{"items"}, "labelSelector": map[string]any{ "apps.cozystack.io/application.group": "apps.cozystack.io", "apps.cozystack.io/application.kind": kind, @@ -290,12 +289,12 @@ func servicesTab(kind string) map[string]any { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "services-table", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services", - "cluster": "{2}", - "baseprefix": "/openapi-ui", - "customizationId": "factory-details-v1.services", - "pathToItems": []any{"items"}, + "id": "services-table", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services", + "clusterNamePartOfUrl": "{2}", + "baseprefix": "/openapi-ui", + "customizationId": "factory-details-v1.services", + "pathToItems": []any{"items"}, "labelSelector": map[string]any{ "apps.cozystack.io/application.group": "apps.cozystack.io", "apps.cozystack.io/application.kind": kind, @@ -316,12 +315,12 @@ func ingressesTab(kind string) map[string]any { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "ingresses-table", - "fetchUrl": "/api/clusters/{2}/k8s/apis/networking.k8s.io/v1/namespaces/{3}/ingresses", - "cluster": "{2}", - "baseprefix": "/openapi-ui", - "customizationId": "factory-details-networking.k8s.io.v1.ingresses", - "pathToItems": []any{"items"}, + "id": "ingresses-table", + "fetchUrl": "/api/clusters/{2}/k8s/apis/networking.k8s.io/v1/namespaces/{3}/ingresses", + "clusterNamePartOfUrl": "{2}", + "baseprefix": "/openapi-ui", + "customizationId": "factory-details-networking.k8s.io.v1.ingresses", + "pathToItems": []any{"items"}, "labelSelector": map[string]any{ "apps.cozystack.io/application.group": "apps.cozystack.io", "apps.cozystack.io/application.kind": kind, @@ -342,12 +341,12 @@ func secretsTab(kind string) map[string]any { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "secrets-table", - "fetchUrl": "/api/clusters/{2}/k8s/apis/core.cozystack.io/v1alpha1/namespaces/{3}/tenantsecrets", - "cluster": "{2}", - "baseprefix": "/openapi-ui", - "customizationId": "factory-details-v1alpha1.core.cozystack.io.tenantsecrets", - "pathToItems": []any{"items"}, + "id": "secrets-table", + "fetchUrl": "/api/clusters/{2}/k8s/apis/core.cozystack.io/v1alpha1/namespaces/{3}/tenantsecrets", + "clusterNamePartOfUrl": "{2}", + "baseprefix": "/openapi-ui", + "customizationId": "factory-details-v1alpha1.core.cozystack.io.tenantsecrets", + "pathToItems": []any{"items"}, "labelSelector": map[string]any{ "apps.cozystack.io/application.group": "apps.cozystack.io", "apps.cozystack.io/application.kind": kind, @@ -359,38 +358,7 @@ func secretsTab(kind string) map[string]any { } } -// eventsTab shows Kubernetes Events scoped to the application's namespace. -// Events are namespace-scoped because Kubernetes Events don't carry application -// labels and cannot be filtered by label selector. In Cozystack's multi-tenancy -// model, each tenant namespace maps to a single application scope, so namespace -// filtering provides the correct event scope. -// For Tenant applications, events are fetched from status.namespace (the tenant's -// own namespace) instead of the parent namespace where the Tenant object lives. -func eventsTab(kind string) map[string]any { - nsPlaceholder := "{3}" - if kind == "Tenant" { - nsPlaceholder = "{reqsJsonPath[0]['.status.namespace']}" - } - return map[string]any{ - "key": "events", - "label": "Events", - "children": []any{ - map[string]any{ - "type": "EnrichedTable", - "data": map[string]any{ - "id": "events-table", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/" + nsPlaceholder + "/events", - "cluster": "{2}", - "baseprefix": "/openapi-ui", - "customizationId": "factory-details-events", - "pathToItems": []any{"items"}, - }, - }, - }, - } -} - -func yamlTab(group, version, plural string) map[string]any { +func yamlTab(plural string) map[string]any { return map[string]any{ "key": "yaml", "label": "YAML", @@ -401,10 +369,8 @@ func yamlTab(group, version, plural string) map[string]any { "id": "yaml-editor", "cluster": "{2}", "isNameSpaced": true, - "type": "apis", - "apiGroup": group, - "apiVersion": version, - "plural": plural, + "type": "builtin", + "typeName": plural, "prefillValuesRequestIndex": float64(0), "readOnly": true, "substractHeight": float64(400), @@ -614,14 +580,15 @@ type factoryFlags struct { Secrets bool } -// factoryFeatureFlags determines which tabs to show based on whether the -// ApplicationDefinition has non-empty Include resource selectors. -// Workloads tab is always shown. +// factoryFeatureFlags tries several conventional locations so you can evolve the API +// without breaking the controller. Defaults are false (hidden). func factoryFeatureFlags(crd *cozyv1alpha1.ApplicationDefinition) factoryFlags { - return factoryFlags{ - Workloads: true, - Ingresses: len(crd.Spec.Ingresses.Include) > 0, - Services: len(crd.Spec.Services.Include) > 0, - Secrets: len(crd.Spec.Secrets.Include) > 0, - } + var f factoryFlags + + f.Workloads = true + f.Ingresses = true + f.Services = true + f.Secrets = true + + return f } diff --git a/internal/controller/dashboard/factory_test.go b/internal/controller/dashboard/factory_test.go deleted file mode 100644 index b3742564..00000000 --- a/internal/controller/dashboard/factory_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package dashboard - -import ( - "testing" -) - -func TestEventsTab_Structure(t *testing.T) { - tab := eventsTab("PostgreSQL") - - if tab["key"] != "events" { - t.Errorf("expected key=events, got %v", tab["key"]) - } - if tab["label"] != "Events" { - t.Errorf("expected label=Events, got %v", tab["label"]) - } - - children, ok := tab["children"].([]any) - if !ok || len(children) != 1 { - t.Fatal("expected exactly 1 child in events tab") - } - - table, ok := children[0].(map[string]any) - if !ok { - t.Fatal("child is not a map") - } - if table["type"] != "EnrichedTable" { - t.Errorf("expected type=EnrichedTable, got %v", table["type"]) - } - - data, ok := table["data"].(map[string]any) - if !ok { - t.Fatal("table data is not a map") - } - if data["id"] != "events-table" { - t.Errorf("expected id=events-table, got %v", data["id"]) - } - if data["fetchUrl"] != "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/events" { - t.Errorf("unexpected fetchUrl for non-Tenant: %v", data["fetchUrl"]) - } - if data["customizationId"] != "factory-details-events" { - t.Errorf("expected customizationId=factory-details-events, got %v", data["customizationId"]) - } - - pathToItems, ok := data["pathToItems"].([]any) - if !ok || len(pathToItems) != 1 || pathToItems[0] != "items" { - t.Errorf("expected pathToItems=[items], got %v", data["pathToItems"]) - } -} - -func TestEventsTab_TenantUsesStatusNamespace(t *testing.T) { - tab := eventsTab("Tenant") - children := tab["children"].([]any) - table := children[0].(map[string]any) - data := table["data"].(map[string]any) - - expectedURL := "/api/clusters/{2}/k8s/api/v1/namespaces/{reqsJsonPath[0]['.status.namespace']}/events" - if data["fetchUrl"] != expectedURL { - t.Errorf("expected Tenant fetchUrl to use status.namespace, got %v", data["fetchUrl"]) - } -} diff --git a/internal/controller/dashboard/manager.go b/internal/controller/dashboard/manager.go index 42c641ad..23897586 100644 --- a/internal/controller/dashboard/manager.go +++ b/internal/controller/dashboard/manager.go @@ -132,10 +132,6 @@ func (m *Manager) EnsureForAppDef(ctx context.Context, crd *cozyv1alpha1.Applica return reconcile.Result{}, err } - if err := m.ensureCFOMapping(ctx, crd); err != nil { - return reconcile.Result{}, err - } - if err := m.ensureSidebar(ctx, crd); err != nil { return reconcile.Result{}, err } @@ -143,10 +139,6 @@ func (m *Manager) EnsureForAppDef(ctx context.Context, crd *cozyv1alpha1.Applica if err := m.ensureFactory(ctx, crd); err != nil { return reconcile.Result{}, err } - - if err := m.ensureNavigation(ctx, crd); err != nil { - return reconcile.Result{}, err - } return reconcile.Result{}, nil } @@ -299,6 +291,10 @@ func (m *Manager) buildExpectedResourceSet(crds []cozyv1alpha1.ApplicationDefini // Add other stock sidebars that are created for each CRD stockSidebars := []string{ + "stock-instance-api-form", + "stock-instance-api-table", + "stock-instance-builtin-form", + "stock-instance-builtin-table", "stock-project-factory-marketplace", "stock-project-factory-workloadmonitor-details", "stock-project-api-form", @@ -307,10 +303,6 @@ func (m *Manager) buildExpectedResourceSet(crds []cozyv1alpha1.ApplicationDefini "stock-project-builtin-table", "stock-project-crd-form", "stock-project-crd-table", - "stock-instance-api-form", - "stock-instance-api-table", - "stock-instance-builtin-form", - "stock-instance-builtin-table", } for _, sidebarID := range stockSidebars { expected["Sidebar"][sidebarID] = true diff --git a/internal/controller/dashboard/marketplacepanel.go b/internal/controller/dashboard/marketplacepanel.go index 14684afc..6bfce752 100644 --- a/internal/controller/dashboard/marketplacepanel.go +++ b/internal/controller/dashboard/marketplacepanel.go @@ -68,46 +68,31 @@ func (m *Manager) ensureMarketplacePanel(ctx context.Context, crd *cozyv1alpha1. tags[i] = t } - _, err := controllerutil.CreateOrUpdate(ctx, m.Client, mp, func() error { + specMap := map[string]any{ + "description": d.Description, + "name": displayName, + "type": "nonCrd", + "apiGroup": "apps.cozystack.io", + "apiVersion": "v1alpha1", + "typeName": app.Plural, // e.g., "buckets" + "disabled": false, + "hidden": false, + "tags": tags, + "icon": d.Icon, + } + + specBytes, err := json.Marshal(specMap) + if err != nil { + return reconcile.Result{}, err + } + + _, err = controllerutil.CreateOrUpdate(ctx, m.Client, mp, func() error { if err := controllerutil.SetOwnerReference(crd, mp, m.Scheme); err != nil { return err } // Add dashboard labels to dynamic resources m.addDashboardLabels(mp, crd, ResourceTypeDynamic) - // Preserve user-set disabled/hidden values from existing resource - disabled := false - hidden := false - if mp.Spec.Raw != nil { - var existing map[string]any - if err := json.Unmarshal(mp.Spec.Raw, &existing); err == nil { - if v, ok := existing["disabled"].(bool); ok { - disabled = v - } - if v, ok := existing["hidden"].(bool); ok { - hidden = v - } - } - } - - specMap := map[string]any{ - "description": d.Description, - "name": displayName, - "type": "nonCrd", - "apiGroup": "apps.cozystack.io", - "apiVersion": "v1alpha1", - "plural": app.Plural, // e.g., "buckets" - "disabled": disabled, - "hidden": hidden, - "tags": tags, - "icon": d.Icon, - } - - specBytes, err := json.Marshal(specMap) - if err != nil { - return err - } - // Only update spec if it's different to avoid unnecessary updates newSpec := dashv1alpha1.ArbitrarySpec{ JSON: apiextv1.JSON{Raw: specBytes}, diff --git a/internal/controller/dashboard/navigation.go b/internal/controller/dashboard/navigation.go deleted file mode 100644 index 5e4bad2e..00000000 --- a/internal/controller/dashboard/navigation.go +++ /dev/null @@ -1,69 +0,0 @@ -package dashboard - -import ( - "context" - "encoding/json" - "fmt" - "strings" - - dashv1alpha1 "github.com/cozystack/cozystack/api/dashboard/v1alpha1" - cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - - apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) - -// ensureNavigation updates the Navigation resource to include a baseFactoriesMapping entry for the given CRD -func (m *Manager) ensureNavigation(ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition) error { - g, v, kind := pickGVK(crd) - plural := pickPlural(kind, crd) - - lowerKind := strings.ToLower(kind) - factoryKey := fmt.Sprintf("%s-details", lowerKind) - - // All CRD resources are namespaced API resources - mappingKey := fmt.Sprintf("base-factory-namespaced-api-%s-%s-%s", g, v, plural) - - obj := &dashv1alpha1.Navigation{} - obj.SetName("navigation") - - _, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error { - // Parse existing spec - spec := make(map[string]any) - if obj.Spec.JSON.Raw != nil { - if err := json.Unmarshal(obj.Spec.JSON.Raw, &spec); err != nil { - spec = make(map[string]any) - } - } - - // Get or create baseFactoriesMapping - var mappings map[string]string - if existing, ok := spec["baseFactoriesMapping"].(map[string]any); ok { - mappings = make(map[string]string, len(existing)) - for k, val := range existing { - if s, ok := val.(string); ok { - mappings[k] = s - } - } - } else { - mappings = make(map[string]string) - } - - // Add/update the mapping for this CRD - mappings[mappingKey] = factoryKey - - spec["baseFactoriesMapping"] = mappings - - b, err := json.Marshal(spec) - if err != nil { - return err - } - - newSpec := dashv1alpha1.ArbitrarySpec{JSON: apiextv1.JSON{Raw: b}} - if !compareArbitrarySpecs(obj.Spec, newSpec) { - obj.Spec = newSpec - } - return nil - }) - return err -} diff --git a/internal/controller/dashboard/sidebar.go b/internal/controller/dashboard/sidebar.go index 69c933fb..a6ade387 100644 --- a/internal/controller/dashboard/sidebar.go +++ b/internal/controller/dashboard/sidebar.go @@ -17,12 +17,13 @@ import ( // ensureSidebar creates/updates multiple Sidebar resources that share the same menu: // - The "details" sidebar tied to the current kind (stock-project-factory--details) -// - The stock-project sidebars: api-form, api-table, builtin-form, builtin-table, crd-form, crd-table +// - The stock-instance sidebars: api-form, api-table, builtin-form, builtin-table +// - The stock-project sidebars: api-form, api-table, builtin-form, builtin-table, crd-form, crd-table // // Menu rules: // - The first section is "Marketplace" with two hardcoded entries: -// - Marketplace (/openapi-ui/{cluster}/{namespace}/factory/marketplace) -// - Tenant Info (/openapi-ui/{cluster}/{namespace}/factory/info-details/info) +// - Marketplace (/openapi-ui/{clusterName}/{namespace}/factory/marketplace) +// - Tenant Info (/openapi-ui/{clusterName}/{namespace}/factory/info-details/info) // - All other sections are built from CRDs where spec.dashboard != nil. // - Categories are ordered strictly as: // Marketplace, IaaS, PaaS, NaaS, , Resources, Backups, Administration @@ -38,23 +39,6 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati } all = crdList.Items - // 1b) Fetch all MarketplacePanels to determine which resources are hidden - hiddenResources := map[string]bool{} - var mpList dashv1alpha1.MarketplacePanelList - if err := m.List(ctx, &mpList, &client.ListOptions{}); err == nil { - for i := range mpList.Items { - mp := &mpList.Items[i] - if mp.Spec.Raw != nil { - var spec map[string]any - if err := json.Unmarshal(mp.Spec.Raw, &spec); err == nil { - if hidden, ok := spec["hidden"].(bool); ok && hidden { - hiddenResources[mp.Name] = true - } - } - } - } - } - // 2) Build category -> []item map (only for CRDs with spec.dashboard != nil) type item struct { Key string @@ -80,11 +64,6 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati plural := pickPlural(kind, def) lowerKind := strings.ToLower(kind) - // Skip resources hidden via MarketplacePanel - if hiddenResources[def.Name] { - continue - } - // Check if this resource is a module if def.Spec.Dashboard.Module { // Special case: info should have its own keysAndTags, not be in modules @@ -112,7 +91,7 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati // Weight (default 0) weight := def.Spec.Dashboard.Weight - link := fmt.Sprintf("/openapi-ui/{cluster}/{namespace}/api-table/%s/%s/%s", g, v, plural) + link := fmt.Sprintf("/openapi-ui/{clusterName}/{namespace}/api-table/%s/%s/%s", g, v, plural) categories[cat] = append(categories[cat], item{ Key: plural, @@ -144,9 +123,6 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati // Add sidebar for backups.cozystack.io Backup resource keysAndTags["backups"] = []any{"backup-sidebar"} - // Add sidebar for backups.cozystack.io RestoreJob resource - keysAndTags["restorejobs"] = []any{"restorejob-sidebar"} - // 3) Sort items within each category by Weight (desc), then Label (A→Z) for cat := range categories { sort.Slice(categories[cat], func(i, j int) bool { @@ -170,7 +146,7 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati map[string]any{ "key": "marketplace", "label": "Marketplace", - "link": "/openapi-ui/{cluster}/{namespace}/factory/marketplace", + "link": "/openapi-ui/{clusterName}/{namespace}/factory/marketplace", }, }, }, @@ -200,28 +176,23 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati // Add hardcoded Backups section menuItems = append(menuItems, map[string]any{ - "key": "backups-category", + "key": "backups", "label": "Backups", "children": []any{ map[string]any{ "key": "plans", "label": "Plans", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/plans", + "link": "/openapi-ui/{clusterName}/{namespace}/api-table/backups.cozystack.io/v1alpha1/plans", }, map[string]any{ "key": "backupjobs", "label": "BackupJobs", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backupjobs", + "link": "/openapi-ui/{clusterName}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backupjobs", }, map[string]any{ "key": "backups", "label": "Backups", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backups", - }, - map[string]any{ - "key": "restorejobs", - "label": "RestoreJobs", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/backups.cozystack.io/v1alpha1/restorejobs", + "link": "/openapi-ui/{clusterName}/{namespace}/api-table/backups.cozystack.io/v1alpha1/backups", }, }, }) @@ -234,22 +205,22 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati map[string]any{ "key": "info", "label": "Info", - "link": "/openapi-ui/{cluster}/{namespace}/factory/info-details/info", + "link": "/openapi-ui/{clusterName}/{namespace}/factory/info-details/info", }, map[string]any{ "key": "modules", "label": "Modules", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/core.cozystack.io/v1alpha1/tenantmodules", + "link": "/openapi-ui/{clusterName}/{namespace}/api-table/core.cozystack.io/v1alpha1/tenantmodules", }, map[string]any{ "key": "loadbalancer-services", "label": "External IPs", - "link": "/openapi-ui/{cluster}/{namespace}/factory/external-ips", + "link": "/openapi-ui/{clusterName}/{namespace}/factory/external-ips", }, map[string]any{ "key": "tenants", "label": "Tenants", - "link": "/openapi-ui/{cluster}/{namespace}/api-table/apps.cozystack.io/v1alpha1/tenants", + "link": "/openapi-ui/{clusterName}/{namespace}/api-table/apps.cozystack.io/v1alpha1/tenants", }, }, }) @@ -257,7 +228,13 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati // 6) Prepare the list of Sidebar IDs to upsert with the SAME content // Create sidebars for ALL CRDs with dashboard config targetIDs := []string{ - // stock-project sidebars (namespace-level, full menu) + // stock-instance sidebars + "stock-instance-api-form", + "stock-instance-api-table", + "stock-instance-builtin-form", + "stock-instance-builtin-table", + + // stock-project sidebars "stock-project-factory-marketplace", "stock-project-factory-workloadmonitor-details", "stock-project-factory-kube-service-details", @@ -266,7 +243,6 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati "stock-project-factory-plan-details", "stock-project-factory-backupjob-details", "stock-project-factory-backup-details", - "stock-project-factory-restorejob-details", "stock-project-factory-external-ips", "stock-project-api-form", "stock-project-api-table", @@ -274,19 +250,9 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati "stock-project-builtin-table", "stock-project-crd-form", "stock-project-crd-table", - // stock-instance sidebars (namespace-level pages after namespace is selected) - "stock-instance-api-form", - "stock-instance-api-table", - "stock-instance-builtin-form", - "stock-instance-builtin-table", } - // Add details sidebars for all CRDs with dashboard config, and collect - // the set of IDs that are genuinely CRD-backed (dynamic). The hardcoded - // `-details` IDs above (e.g. kube-* and backup/backupjob/plan/restorejob) - // are not tied to an ApplicationDefinition and must be treated as static - // so they receive consistent labels via upsertMultipleSidebars(). - dynamicDetailsIDs := map[string]bool{} + // Add details sidebars for all CRDs with dashboard config for i := range all { def := &all[i] if def.Spec.Dashboard == nil { @@ -296,22 +262,17 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Applicati lowerKind := strings.ToLower(kind) detailsID := fmt.Sprintf("stock-project-factory-%s-details", lowerKind) targetIDs = append(targetIDs, detailsID) - dynamicDetailsIDs[detailsID] = true } // 7) Upsert all target sidebars with identical menuItems and keysAndTags - return m.upsertMultipleSidebars(ctx, crd, targetIDs, dynamicDetailsIDs, keysAndTags, menuItems) + return m.upsertMultipleSidebars(ctx, crd, targetIDs, keysAndTags, menuItems) } // upsertMultipleSidebars creates/updates several Sidebar resources with the same menu spec. -// dynamicDetailsIDs identifies `stock-project-factory--details` sidebars that are -// backed by an ApplicationDefinition and should therefore be owned by that CRD. -// Any other ID is treated as a static sidebar (managed-by labels, no owner ref). func (m *Manager) upsertMultipleSidebars( ctx context.Context, crd *cozyv1alpha1.ApplicationDefinition, ids []string, - dynamicDetailsIDs map[string]bool, keysAndTags map[string]any, menuItems []any, ) error { @@ -327,10 +288,8 @@ func (m *Manager) upsertMultipleSidebars( if _, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error { // Only set owner reference for dynamic sidebars (stock-project-factory-{kind}-details) - // that are actually backed by an ApplicationDefinition. Static sidebars — including - // hardcoded details sidebars for built-in/backup resources — must fall through to the - // static-label branch so they're managed consistently. - if strings.HasPrefix(id, "stock-project-factory-") && strings.HasSuffix(id, "-details") && dynamicDetailsIDs[id] { + // Static sidebars (stock-instance-*, stock-project-*) should not have owner references + if strings.HasPrefix(id, "stock-project-factory-") && strings.HasSuffix(id, "-details") { // This is a dynamic sidebar, set owner reference only if it matches the current CRD _, _, kind := pickGVK(crd) lowerKind := strings.ToLower(kind) diff --git a/internal/controller/dashboard/static_helpers.go b/internal/controller/dashboard/static_helpers.go index db37e05b..af46674b 100644 --- a/internal/controller/dashboard/static_helpers.go +++ b/internal/controller/dashboard/static_helpers.go @@ -650,31 +650,12 @@ func createStringColumn(name, jsonPath string) map[string]any { } } -// createTimestampColumn creates a timestamp column with custom formatting. -// Extra jsonPaths act as ordered fallbacks: the first non-null path wins, -// and `-` is used only when every path is null. Depth is capped at two -// because the template parser's non-greedy matcher cannot track more than -// one level of alternating quotes in a nested reqsJsonPath fallback. -func createTimestampColumn(name string, jsonPaths ...string) map[string]any { - if len(jsonPaths) == 0 { - panic("createTimestampColumn requires at least one jsonPath") - } - if len(jsonPaths) > 2 { - panic("createTimestampColumn supports at most two jsonPaths (primary + one fallback)") - } - - var text string - switch len(jsonPaths) { - case 1: - text = "{reqsJsonPath[0]['" + jsonPaths[0] + "']['-']}" - case 2: - text = "{reqsJsonPath[0]['" + jsonPaths[0] + "'][\"{reqsJsonPath[0]['" + jsonPaths[1] + "']['-']}\"]}" - } - +// createTimestampColumn creates a timestamp column with custom formatting +func createTimestampColumn(name, jsonPath string) map[string]any { return map[string]any{ "name": name, "type": "factory", - "jsonPath": jsonPaths[0], + "jsonPath": jsonPath, "customProps": map[string]any{ "disableEventBubbling": true, "items": []any{ @@ -692,7 +673,7 @@ func createTimestampColumn(name string, jsonPaths ...string) map[string]any { "data": map[string]any{ "formatter": "timestamp", "id": "time-value", - "text": text, + "text": "{reqsJsonPath[0]['" + jsonPath + "']['-']}", }, }, }, @@ -1153,7 +1134,7 @@ func yamlEditor(id, cluster string, isNameSpaced bool, typeName string, prefillV "cluster": cluster, "isNameSpaced": isNameSpaced, "type": "builtin", - "plural": typeName, + "typeName": typeName, "prefillValuesRequestIndex": prefillValuesRequestIndex, "substractHeight": float64(400), }, diff --git a/internal/controller/dashboard/static_processor.go b/internal/controller/dashboard/static_processor.go index d4b270f4..902e3818 100644 --- a/internal/controller/dashboard/static_processor.go +++ b/internal/controller/dashboard/static_processor.go @@ -49,8 +49,6 @@ func (m *Manager) ensureStaticResource(ctx context.Context, obj client.Object) e resource.(*dashv1alpha1.Navigation).Spec = o.Spec case *dashv1alpha1.TableUriMapping: resource.(*dashv1alpha1.TableUriMapping).Spec = o.Spec - case *dashv1alpha1.CFOMapping: - resource.(*dashv1alpha1.CFOMapping).Spec = o.Spec } // Ensure labels are always set m.addDashboardLabels(resource, nil, ResourceTypeStatic) diff --git a/internal/controller/dashboard/static_refactored.go b/internal/controller/dashboard/static_refactored.go index 9f28c0fb..b2ace34b 100644 --- a/internal/controller/dashboard/static_refactored.go +++ b/internal/controller/dashboard/static_refactored.go @@ -17,111 +17,111 @@ func CreateAllBreadcrumbs() []*dashboardv1alpha1.Breadcrumb { return []*dashboardv1alpha1.Breadcrumb{ // Stock project factory configmap details createBreadcrumb("stock-project-factory-configmap-details", []map[string]any{ - createBreadcrumbItem("configmaps", "v1/configmaps", "/openapi-ui/{cluster}/{namespace}/builtin-table/configmaps"), + createBreadcrumbItem("configmaps", "v1/configmaps", "/openapi-ui/{clusterName}/{namespace}/builtin-table/configmaps"), createBreadcrumbItem("configmap", "{6}"), }), // Stock cluster factory namespace details createBreadcrumb("stock-cluster-factory-namespace-details", []map[string]any{ - createBreadcrumbItem("namespaces", "v1/namespaces", "/openapi-ui/{cluster}/builtin-table/namespaces"), + createBreadcrumbItem("namespaces", "v1/namespaces", "/openapi-ui/{clusterName}/builtin-table/namespaces"), createBreadcrumbItem("namespace", "{5}"), }), // Stock cluster factory node details createBreadcrumb("stock-cluster-factory-node-details", []map[string]any{ - createBreadcrumbItem("node", "v1/nodes", "/openapi-ui/{cluster}/builtin-table/nodes"), + createBreadcrumbItem("node", "v1/nodes", "/openapi-ui/{clusterName}/builtin-table/nodes"), createBreadcrumbItem("node", "{5}"), }), // Stock project factory pod details createBreadcrumb("stock-project-factory-pod-details", []map[string]any{ - createBreadcrumbItem("pods", "v1/pods", "/openapi-ui/{cluster}/{namespace}/builtin-table/pods"), + createBreadcrumbItem("pods", "v1/pods", "/openapi-ui/{clusterName}/{namespace}/builtin-table/pods"), createBreadcrumbItem("pod", "{6}"), }), // Stock project factory secret details createBreadcrumb("stock-project-factory-kube-secret-details", []map[string]any{ - createBreadcrumbItem("secrets", "v1/secrets", "/openapi-ui/{cluster}/{namespace}/builtin-table/secrets"), + createBreadcrumbItem("secrets", "v1/secrets", "/openapi-ui/{clusterName}/{namespace}/builtin-table/secrets"), createBreadcrumbItem("secret", "{6}"), }), // Stock project factory service details createBreadcrumb("stock-project-factory-kube-service-details", []map[string]any{ - createBreadcrumbItem("services", "v1/services", "/openapi-ui/{cluster}/{namespace}/builtin-table/services"), + createBreadcrumbItem("services", "v1/services", "/openapi-ui/{clusterName}/{namespace}/builtin-table/services"), createBreadcrumbItem("service", "{6}"), }), // Stock project factory ingress details createBreadcrumb("stock-project-factory-kube-ingress-details", []map[string]any{ - createBreadcrumbItem("ingresses", "networking.k8s.io/v1/ingresses", "/openapi-ui/{cluster}/{namespace}/builtin-table/ingresses"), + createBreadcrumbItem("ingresses", "networking.k8s.io/v1/ingresses", "/openapi-ui/{clusterName}/{namespace}/builtin-table/ingresses"), createBreadcrumbItem("ingress", "{6}"), }), // Stock cluster api table createBreadcrumb("stock-cluster-api-table", []map[string]any{ - createBreadcrumbItem("api", "{apiGroup}/{apiVersion}/{plural}"), + createBreadcrumbItem("api", "{apiGroup}/{apiVersion}/{typeName}"), }), // Stock cluster api form createBreadcrumb("stock-cluster-api-form", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{plural}", "/openapi-ui/{cluster}/api-table/{apiGroup}/{apiVersion}/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{typeName}", "/openapi-ui/{clusterName}/api-table/{apiGroup}/{apiVersion}/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Create"), }), // Stock cluster api form edit createBreadcrumb("stock-cluster-api-form-edit", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{plural}", "/openapi-ui/{cluster}/api-table/{apiGroup}/{apiVersion}/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{typeName}", "/openapi-ui/{clusterName}/api-table/{apiGroup}/{apiVersion}/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Update"), }), // Stock cluster builtin table createBreadcrumb("stock-cluster-builtin-table", []map[string]any{ - createBreadcrumbItem("api", "v1/{plural}"), + createBreadcrumbItem("api", "v1/{typeName}"), }), // Stock cluster builtin form createBreadcrumb("stock-cluster-builtin-form", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "v1/{plural}", "/openapi-ui/{cluster}/builtin-table/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "v1/{typeName}", "/openapi-ui/{clusterName}/builtin-table/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Create"), }), // Stock cluster builtin form edit createBreadcrumb("stock-cluster-builtin-form-edit", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "v1/{plural}", "/openapi-ui/{cluster}/builtin-table/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "v1/{typeName}", "/openapi-ui/{clusterName}/builtin-table/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Update"), }), // Stock project api table createBreadcrumb("stock-project-api-table", []map[string]any{ - createBreadcrumbItem("api", "{apiGroup}/{apiVersion}/{plural}"), + createBreadcrumbItem("api", "{apiGroup}/{apiVersion}/{typeName}"), }), // Stock project api form createBreadcrumb("stock-project-api-form", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{plural}", "/openapi-ui/{cluster}/{namespace}/api-table/{apiGroup}/{apiVersion}/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{typeName}", "/openapi-ui/{clusterName}/{namespace}/api-table/{apiGroup}/{apiVersion}/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Create"), }), // Stock project api form edit createBreadcrumb("stock-project-api-form-edit", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{plural}", "/openapi-ui/{cluster}/{namespace}/api-table/{apiGroup}/{apiVersion}/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "{apiGroup}/{apiVersion}/{typeName}", "/openapi-ui/{clusterName}/{namespace}/api-table/{apiGroup}/{apiVersion}/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Update"), }), // Stock project builtin table createBreadcrumb("stock-project-builtin-table", []map[string]any{ - createBreadcrumbItem("api", "v1/{plural}"), + createBreadcrumbItem("api", "v1/{typeName}"), }), // Stock project builtin form createBreadcrumb("stock-project-builtin-form", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "v1/{plural}", "/openapi-ui/{cluster}/{namespace}/builtin-table/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "v1/{typeName}", "/openapi-ui/{clusterName}/{namespace}/builtin-table/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Create"), }), // Stock project builtin form edit createBreadcrumb("stock-project-builtin-form-edit", []map[string]any{ - createBreadcrumbItem("create-api-res-namespaced-table", "v1/{plural}", "/openapi-ui/{cluster}/{namespace}/builtin-table/{plural}"), + createBreadcrumbItem("create-api-res-namespaced-table", "v1/{typeName}", "/openapi-ui/{clusterName}/{namespace}/builtin-table/{typeName}"), createBreadcrumbItem("create-api-res-namespaced-typename", "Update"), }), } @@ -154,14 +154,6 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid createStringColumn("Version", ".status.version"), }), - // Factory service details endpointslice (Pod serving table) - createCustomColumnsOverride("factory-kube-service-details-endpointslice", []any{ - createStringColumn("Pod", ".targetRef.name"), - createArrayColumn("Addresses", ".addresses"), - createBoolColumn("Ready", ".conditions.ready"), - createStringColumn("Node", ".nodeName"), - }), - // Factory service details port mapping createCustomColumnsOverride("factory-kube-service-details-port-mapping", []any{ createStringColumn("Name", ".name"), @@ -224,20 +216,6 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid createStringColumn("Name", ".name"), }), - // Factory details events. Event Time falls back to `.firstTimestamp` - // because core/v1 Events (Helm, controller-runtime) populate only the - // legacy timestamps while events.k8s.io/v1 Events populate only - // `.eventTime`; taking the first non-null of the two covers both. - createCustomColumnsOverride("factory-details-events", []any{ - createTimestampColumn("Last Seen", ".lastTimestamp", ".eventTime"), - createTimestampColumn("Event Time", ".eventTime", ".firstTimestamp"), - createStringColumn("Type", ".type"), - createStringColumn("Reason", ".reason"), - createStringColumn("Object", ".involvedObject.kind"), - createStringColumn("Name", ".involvedObject.name"), - createStringColumn("Message", ".message"), - }), - // Factory status conditions createCustomColumnsOverride("factory-status-conditions", []any{ createStringColumn("Type", ".type"), @@ -425,14 +403,6 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid createTimestampColumn("Taken At", ".spec.takenAt"), createTimestampColumn("Created", ".metadata.creationTimestamp"), }), - - // Stock namespace backups cozystack io v1alpha1 restorejobs - createCustomColumnsOverride("stock-namespace-/backups.cozystack.io/v1alpha1/restorejobs", []any{ - createCustomColumnWithJsonPath("Name", ".metadata.name", "RestoreJob", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/restorejob-details/{reqsJsonPath[0]['.metadata.name']['-']}"), - createStringColumn("Phase", ".status.phase"), - createStringColumn("Backup", ".spec.backupRef.name"), - createTimestampColumn("Created", ".metadata.creationTimestamp"), - }), } } @@ -525,61 +495,6 @@ func CreateAllCustomFormsOverrides() []*dashboardv1alpha1.CustomFormsOverride { createFormItem("spec.ports", "Ports", "array"), }, }), - - // Plans form override - backups.cozystack.io/v1alpha1 - createCustomFormsOverride("default-/backups.cozystack.io/v1alpha1/plans", map[string]any{ - "formItems": []any{ - createFormItem("metadata.name", "Name", "text"), - createFormItem("metadata.namespace", "Namespace", "text"), - createFormItem("spec.applicationRef.kind", "Application Kind", "text"), - createFormItem("spec.applicationRef.name", "Application Name", "text"), - createFormItem("spec.schedule.type", "Schedule Type", "text"), - createFormItem("spec.schedule.cron", "Schedule Cron", "text"), - }, - "schema": createSchema(map[string]any{ - "backupClassName": listInputScemaItemBackupClass(), - }), - }), - - // BackupJobs form override - backups.cozystack.io/v1alpha1 - createCustomFormsOverride("default-/backups.cozystack.io/v1alpha1/backupjobs", map[string]any{ - "formItems": []any{ - createFormItem("metadata.name", "Name", "text"), - createFormItem("metadata.namespace", "Namespace", "text"), - createFormItem("spec.planRef.name", "Plan Name (optional)", "text"), - createFormItem("spec.applicationRef.apiGroup", "Application API Group", "text"), - createFormItem("spec.applicationRef.kind", "Application Kind", "text"), - createFormItem("spec.applicationRef.name", "Application Name", "text"), - }, - "schema": createSchema(map[string]any{ - "backupClassName": listInputScemaItemBackupClass(), - }), - }), - - // RestoreJobs form override - backups.cozystack.io/v1alpha1 - createCustomFormsOverride("default-/backups.cozystack.io/v1alpha1/restorejobs", map[string]any{ - "formItems": []any{ - createFormItem("metadata.name", "Name", "text"), - createFormItem("metadata.namespace", "Namespace", "text"), - createFormItem("spec.backupRef.name", "Backup", "text"), - // Target application: leave empty to restore into the same application - // as referenced by the selected Backup. Fill all three to restore into - // a different application (e.g. rename, or restore into a new target). - createFormItem("spec.targetApplicationRef.apiGroup", "Target Application API Group (optional, used to restore into a different application)", "text"), - createFormItem("spec.targetApplicationRef.kind", "Target Application Kind (optional, used to restore into a different application)", "text"), - createFormItem("spec.targetApplicationRef.name", "Target Application Name (optional, used to restore into a different application)", "text"), - // Driver-specific options (key-value editor). Refer to the backup driver - // documentation for supported keys. - createFormItem("spec.options", "Options (driver-specific key/value pairs)", "object"), - }, - "schema": createSchema(map[string]any{ - "backupRef": map[string]any{ - "properties": map[string]any{ - "name": listInputSchemaItemBackup(), - }, - }, - }), - }), } } @@ -599,14 +514,14 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { }, []any{ map[string]any{ "data": map[string]any{ - "baseApiVersion": "v1alpha1", - "baseprefix": "openapi-ui", - "cluster": "{2}", - "id": 311, - "marketplaceKind": "MarketplacePanel", - "marketplacePlural": "marketplacepanels", - "namespace": "{3}", - "baseApiGroup": "dashboard.cozystack.io", + "baseApiVersion": "v1alpha1", + "baseprefix": "openapi-ui", + "clusterNamePartOfUrl": "{2}", + "id": 311, + "mpResourceKind": "MarketplacePanel", + "mpResourceName": "marketplacepanels", + "namespacePartOfUrl": "{3}", + "baseApiGroup": "dashboard.cozystack.io", }, "type": "MarketplaceCard", }, @@ -919,7 +834,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { "prefillValuesRequestIndex": 0, "substractHeight": float64(400), "type": "builtin", - "plural": "secrets", + "typeName": "secrets", "readOnly": true, }, }, @@ -1149,13 +1064,13 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "service-port-mapping-table", - "baseprefix": "/openapi-ui", - "cluster": "{2}", - "customizationId": "factory-kube-service-details-port-mapping", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services/{6}", - "pathToItems": ".spec.ports", - "withoutControls": true, + "id": "service-port-mapping-table", + "baseprefix": "/openapi-ui", + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-kube-service-details-port-mapping", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services/{6}", + "pathToItems": ".spec.ports", + "withoutControls": true, }, }, }), @@ -1175,11 +1090,11 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "service-pod-serving-table", - "baseprefix": "/openapi-ui", - "cluster": "{2}", - "customizationId": "factory-kube-service-details-endpointslice", - "fetchUrl": "/api/clusters/{2}/k8s/apis/discovery.k8s.io/v1/namespaces/{3}/endpointslices", + "id": "service-pod-serving-table", + "baseprefix": "/openapi-ui", + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-kube-service-details-endpointslice", + "fetchUrl": "/api/clusters/{2}/k8s/apis/discovery.k8s.io/v1/namespaces/{3}/endpointslices", "labelSelector": map[string]any{ "kubernetes.io/service-name": "{reqsJsonPath[0]['.metadata.name']['-']}", }, @@ -1209,7 +1124,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { "prefillValuesRequestIndex": 0, "substractHeight": float64(400), "type": "builtin", - "plural": "services", + "typeName": "services", }, }, }, @@ -1232,11 +1147,11 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "pods-table", - "baseprefix": "/openapi-ui", - "cluster": "{2}", - "customizationId": "factory-node-details-/v1/pods", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/pods", + "id": "pods-table", + "baseprefix": "/openapi-ui", + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-node-details-/v1/pods", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/pods", "labelSelectorFull": map[string]any{ "pathToLabels": ".spec.selector", "reqIndex": 0, @@ -1364,13 +1279,13 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "rules-table", - "fetchUrl": "/api/clusters/{2}/k8s/apis/networking.k8s.io/v1/namespaces/{3}/ingresses/{6}", - "cluster": "{2}", - "customizationId": "factory-kube-ingress-details-rules", - "baseprefix": "/openapi-ui", - "withoutControls": true, - "pathToItems": []any{"spec", "rules"}, + "id": "rules-table", + "fetchUrl": "/api/clusters/{2}/k8s/apis/networking.k8s.io/v1/namespaces/{3}/ingresses/{6}", + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-kube-ingress-details-rules", + "baseprefix": "/openapi-ui", + "withoutControls": true, + "pathToItems": []any{"spec", "rules"}, }, }, }), @@ -1386,10 +1301,8 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { "id": "yaml-editor", "cluster": "{2}", "isNameSpaced": true, - "type": "apis", - "apiGroup": "networking.k8s.io", - "apiVersion": "v1", - "plural": "ingresses", + "type": "builtin", + "typeName": "ingresses", "prefillValuesRequestIndex": float64(0), "substractHeight": float64(400), }, @@ -1518,11 +1431,11 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "workloads-table", - "baseprefix": "/openapi-ui", - "cluster": "{2}", - "customizationId": "factory-details-v1alpha1.cozystack.io.workloads", - "fetchUrl": "/api/clusters/{2}/k8s/apis/cozystack.io/v1alpha1/namespaces/{3}/workloads", + "id": "workloads-table", + "baseprefix": "/openapi-ui", + "clusterNamePartOfUrl": "{2}", + "customizationId": "factory-details-v1alpha1.cozystack.io.workloads", + "fetchUrl": "/api/clusters/{2}/k8s/apis/cozystack.io/v1alpha1/namespaces/{3}/workloads", "labelSelector": map[string]any{ "workloads.cozystack.io/monitor": "{reqs[0]['metadata','name']}", }, @@ -1543,10 +1456,8 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { "isNameSpaced": true, "prefillValuesRequestIndex": 0, "substractHeight": float64(400), - "type": "apis", - "apiGroup": "cozystack.io", - "apiVersion": "v1alpha1", - "plural": "workloadmonitors", + "type": "builtin", + "typeName": "workloadmonitors", }, }, }, @@ -1645,9 +1556,13 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { antdText("application-ref-label", true, "Application", nil), parsedText("application-ref-value", "{reqsJsonPath[0]['.spec.applicationRef.kind']['-']}.{reqsJsonPath[0]['.spec.applicationRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.applicationRef.name']['-']}", nil), }), - antdFlexVertical("spec-backup-class-name-block", 4, []any{ - antdText("backup-class-name-label", true, "Backup Class", nil), - parsedText("backup-class-name-value", "{reqsJsonPath[0]['.spec.backupClassName']['-']}", nil), + antdFlexVertical("spec-storage-ref-block", 4, []any{ + antdText("storage-ref-label", true, "Storage", nil), + parsedText("storage-ref-value", "{reqsJsonPath[0]['.spec.storageRef.kind']['-']}.{reqsJsonPath[0]['.spec.storageRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.storageRef.name']['-']}", nil), + }), + antdFlexVertical("spec-strategy-ref-block", 4, []any{ + antdText("strategy-ref-label", true, "Strategy", nil), + parsedText("strategy-ref-value", "{reqsJsonPath[0]['.spec.strategyRef.kind']['-']}.{reqsJsonPath[0]['.spec.strategyRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.strategyRef.name']['-']}", nil), }), antdFlexVertical("spec-schedule-type-block", 4, []any{ antdText("schedule-type-label", true, "Schedule Type", nil), @@ -1765,9 +1680,13 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { antdText("application-ref-label", true, "Application", nil), parsedText("application-ref-value", "{reqsJsonPath[0]['.spec.applicationRef.kind']['-']}.{reqsJsonPath[0]['.spec.applicationRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.applicationRef.name']['-']}", nil), }), - antdFlexVertical("spec-backup-class-name-block", 4, []any{ - antdText("backup-class-name-label", true, "Backup Class", nil), - parsedText("backup-class-name-value", "{reqsJsonPath[0]['.spec.backupClassName']['-']}", nil), + antdFlexVertical("spec-storage-ref-block", 4, []any{ + antdText("storage-ref-label", true, "Storage", nil), + parsedText("storage-ref-value", "{reqsJsonPath[0]['.spec.storageRef.kind']['-']}.{reqsJsonPath[0]['.spec.storageRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.storageRef.name']['-']}", nil), + }), + antdFlexVertical("spec-strategy-ref-block", 4, []any{ + antdText("strategy-ref-label", true, "Strategy", nil), + parsedText("strategy-ref-value", "{reqsJsonPath[0]['.spec.strategyRef.name']['-']}", nil), }), antdFlexVertical("status-backup-ref-block", 4, []any{ antdText("backup-ref-label", true, "Backup Ref", nil), @@ -1945,9 +1864,13 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { antdText("application-ref-label", true, "Application", nil), parsedText("application-ref-value", "{reqsJsonPath[0]['.spec.applicationRef.kind']['-']}.{reqsJsonPath[0]['.spec.applicationRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.applicationRef.name']['-']}", nil), }), - antdFlexVertical("spec-backup-class-name-block", 4, []any{ - antdText("backup-class-name-label", true, "Backup Class", nil), - parsedText("backup-class-name-value", "{reqsJsonPath[0]['.spec.backupClassName']['-']}", nil), + antdFlexVertical("spec-storage-ref-block", 4, []any{ + antdText("storage-ref-label", true, "Storage", nil), + parsedText("storage-ref-value", "{reqsJsonPath[0]['.spec.storageRef.kind']['-']}.{reqsJsonPath[0]['.spec.storageRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.storageRef.name']['-']}", nil), + }), + antdFlexVertical("spec-strategy-ref-block", 4, []any{ + antdText("strategy-ref-label", true, "Strategy", nil), + parsedText("strategy-ref-value", "{reqsJsonPath[0]['.spec.strategyRef.kind']['-']}.{reqsJsonPath[0]['.spec.strategyRef.apiGroup']['-']}/{reqsJsonPath[0]['.spec.strategyRef.name']['-']}", nil), }), antdFlexVertical("status-artifact-uri-block", 4, []any{ antdText("artifact-uri-label", true, "Artifact URI", nil), @@ -1970,177 +1893,6 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { } backupSpec := createUnifiedFactory(backupConfig, backupTabs, []any{"/api/clusters/{2}/k8s/apis/backups.cozystack.io/v1alpha1/namespaces/{3}/backups/{6}"}) - // RestoreJob details factory using unified approach - restoreJobConfig := UnifiedResourceConfig{ - Name: "restorejob-details", - ResourceType: "factory", - Kind: "RestoreJob", - Plural: "restorejobs", - Title: "restorejob", - } - restoreJobTabs := []any{ - map[string]any{ - "key": "details", - "label": "Details", - "children": []any{ - contentCard("details-card", map[string]any{ - "marginBottom": "24px", - }, []any{ - antdText("details-title", true, "RestoreJob details", map[string]any{ - "fontSize": 20, - "marginBottom": "12px", - }), - spacer("details-spacer", 16), - antdRow("details-grid", []any{48, 12}, []any{ - antdCol("col-left", 12, []any{ - antdFlexVertical("col-left-stack", 24, []any{ - antdFlexVertical("meta-name-block", 4, []any{ - antdText("meta-name-label", true, "Name", nil), - parsedText("meta-name-value", "{reqsJsonPath[0]['.metadata.name']['-']}", nil), - }), - antdFlexVertical("meta-namespace-block", 8, []any{ - antdText("meta-namespace-label", true, "Namespace", nil), - antdFlex("header-row", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "header-badge", - "text": "NS", - "title": "namespace", - "style": map[string]any{ - "backgroundColor": "#a25792ff", - "borderRadius": "20px", - "color": "#fff", - "display": "inline-block", - "fontFamily": "RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif", - "fontSize": "15px", - "fontWeight": 400, - "lineHeight": "24px", - "minWidth": 24, - "padding": "0 9px", - "textAlign": "center", - "whiteSpace": "nowrap", - }, - }, - }, - map[string]any{ - "type": "antdLink", - "data": map[string]any{ - "id": "namespace-link", - "text": "{reqsJsonPath[0]['.metadata.namespace']['-']}", - "href": "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace", - }, - }, - }), - }), - antdFlexVertical("meta-created-block", 4, []any{ - antdText("created-time-label", true, "Created", nil), - antdFlex("created-time-block", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "created-time-icon", - "text": "🌐", - }, - }, - map[string]any{ - "type": "parsedText", - "data": map[string]any{ - "formatter": "timestamp", - "id": "created-time-value", - "text": "{reqsJsonPath[0]['.metadata.creationTimestamp']['-']}", - }, - }, - }), - }), - }), - }), - antdCol("col-right", 12, []any{ - antdFlexVertical("col-right-stack", 24, []any{ - antdFlexVertical("status-phase-block", 4, []any{ - antdText("phase-label", true, "Phase", nil), - parsedText("phase-value", "{reqsJsonPath[0]['.status.phase']['-']}", nil), - }), - antdFlexVertical("spec-backup-ref-block", 4, []any{ - antdText("backup-ref-label", true, "Backup Ref", nil), - parsedText("backup-ref-value", "{reqsJsonPath[0]['.spec.backupRef.name']['-']}", nil), - }), - antdFlexVertical("spec-target-application-ref-block", 4, []any{ - antdText("target-application-ref-label", true, "Target Application", nil), - // targetApplicationRef is optional — when absent, the restore targets - // the same application as the selected Backup. Show a single friendly - // fallback in that case instead of rendering "-.-/-". - parsedText("target-application-ref-value", "{reqsJsonPath[0]['.spec.targetApplicationRef.name']['Same as backup']}", nil), - }), - antdFlexVertical("spec-options-target-namespace-block", 4, []any{ - antdText("options-target-namespace-label", true, "Target Namespace", nil), - parsedText("options-target-namespace-value", "{reqsJsonPath[0]['.spec.options.targetNamespace']['-']}", nil), - }), - antdFlexVertical("spec-options-fail-if-target-exists-block", 4, []any{ - antdText("options-fail-if-target-exists-label", true, "Fail If Target Exists", nil), - parsedText("options-fail-if-target-exists-value", "{reqsJsonPath[0]['.spec.options.failIfTargetExists']['-']}", nil), - }), - antdFlexVertical("spec-options-keep-original-pvc-block", 4, []any{ - antdText("options-keep-original-pvc-label", true, "Keep Original PVC", nil), - parsedText("options-keep-original-pvc-value", "{reqsJsonPath[0]['.spec.options.keepOriginalPVC']['-']}", nil), - }), - antdFlexVertical("spec-options-keep-original-ip-mac-block", 4, []any{ - antdText("options-keep-original-ip-mac-label", true, "Keep Original IP/MAC", nil), - parsedText("options-keep-original-ip-mac-value", "{reqsJsonPath[0]['.spec.options.keepOriginalIpAndMac']['-']}", nil), - }), - antdFlexVertical("status-started-at-block", 4, []any{ - antdText("started-at-label", true, "Started At", nil), - antdFlex("started-at-time-block", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "started-at-time-icon", - "text": "🌐", - }, - }, - map[string]any{ - "type": "parsedText", - "data": map[string]any{ - "formatter": "timestamp", - "id": "started-at-time-value", - "text": "{reqsJsonPath[0]['.status.startedAt']['-']}", - }, - }, - }), - }), - antdFlexVertical("status-completed-at-block", 4, []any{ - antdText("completed-at-label", true, "Completed At", nil), - antdFlex("completed-at-time-block", 6, []any{ - map[string]any{ - "type": "antdText", - "data": map[string]any{ - "id": "completed-at-time-icon", - "text": "🌐", - }, - }, - map[string]any{ - "type": "parsedText", - "data": map[string]any{ - "formatter": "timestamp", - "id": "completed-at-time-value", - "text": "{reqsJsonPath[0]['.status.completedAt']['-']}", - }, - }, - }), - }), - antdFlexVertical("status-message-block", 4, []any{ - antdText("message-label", true, "Message", nil), - parsedText("message-value", "{reqsJsonPath[0]['.status.message']['-']}", nil), - }), - }), - }), - }), - }), - }, - }, - } - restoreJobSpec := createUnifiedFactory(restoreJobConfig, restoreJobTabs, []any{"/api/clusters/{2}/k8s/apis/backups.cozystack.io/v1alpha1/namespaces/{3}/restorejobs/{6}"}) - // External IPs factory (filtered services) externalIPsTabs := []any{ map[string]any{ @@ -2150,12 +1902,12 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { map[string]any{ "type": "EnrichedTable", "data": map[string]any{ - "id": "external-ips-table", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services", - "cluster": "{2}", - "baseprefix": "/openapi-ui", - "customizationId": "factory-details-v1.services", - "pathToItems": ".items", + "id": "external-ips-table", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/services", + "clusterNamePartOfUrl": "{2}", + "baseprefix": "/openapi-ui", + "customizationId": "factory-details-v1.services", + "pathToItems": []any{"items"}, "fieldSelector": map[string]any{ "spec.type": "LoadBalancer", }, @@ -2193,39 +1945,18 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory { createFactory("plan-details", planSpec), createFactory("backupjob-details", backupJobSpec), createFactory("backup-details", backupSpec), - createFactory("restorejob-details", restoreJobSpec), createFactory("external-ips", externalIPsSpec), } } // CreateAllNavigations creates all navigation resources using helper functions func CreateAllNavigations() []*dashboardv1alpha1.Navigation { - // Build baseFactoriesMapping for static (built-in) factories - baseFactoriesMapping := map[string]string{ - // Cluster-scoped builtin resources - "base-factory-clusterscoped-builtin-v1-namespaces": "namespace-details", - "base-factory-clusterscoped-builtin-v1-nodes": "node-details", - // Namespaced builtin resources - "base-factory-namespaced-builtin-v1-pods": "pod-details", - "base-factory-namespaced-builtin-v1-secrets": "kube-secret-details", - "base-factory-namespaced-builtin-v1-services": "kube-service-details", - // Namespaced API resources - "base-factory-namespaced-api-networking.k8s.io-v1-ingresses": "kube-ingress-details", - "base-factory-namespaced-api-cozystack.io-v1alpha1-workloadmonitors": "workloadmonitor-details", - // Backup resources (not ApplicationDefinitions, so ensureNavigation doesn't cover them) - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-plans": "plan-details", - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-backupjobs": "backupjob-details", - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-backups": "backup-details", - "base-factory-namespaced-api-backups.cozystack.io-v1alpha1-restorejobs": "restorejob-details", - } - return []*dashboardv1alpha1.Navigation{ createNavigation("navigation", map[string]any{ "namespaces": map[string]any{ "change": "/openapi-ui/{selectedCluster}/{value}/factory/marketplace", "clear": "/openapi-ui/{selectedCluster}/api-table/core.cozystack.io/v1alpha1/tenantnamespaces", }, - "baseFactoriesMapping": baseFactoriesMapping, }), } } @@ -2283,9 +2014,9 @@ func createCustomFormsOverride(customizationId string, spec map[string]any) *das "strategy": "merge", } - // Merge into newSpec caller-provided fields without: customizationId, hidden, strategy + // Merge caller-provided fields (like formItems) into newSpec for key, value := range spec { - if key != "customizationId" && key != "hidden" && key != "strategy" { + if key != "customizationId" && key != "hidden" && key != "schema" && key != "strategy" { newSpec[key] = value } } @@ -2330,41 +2061,6 @@ func createNavigation(name string, spec map[string]any) *dashboardv1alpha1.Navig } } -func listInputScemaItemBackupClass() map[string]any { - return map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/backups.cozystack.io/v1alpha1/backupclasses", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - }, - } -} - -// listInputSchemaItemBackup returns a listInput schema overlay for selecting a Backup -// from the current namespace (used by RestoreJob form for spec.backupRef.name). -func listInputSchemaItemBackup() map[string]any { - return map[string]any{ - "type": "listInput", - "customProps": map[string]any{ - "valueUri": "/api/clusters/{cluster}/k8s/apis/backups.cozystack.io/v1alpha1/namespaces/{namespace}/backups", - "keysToValue": []any{"metadata", "name"}, - "keysToLabel": []any{"metadata", "name"}, - }, - } -} - -// backupClassSchema returns the schema for spec.backupClassName as listInput (BackupJob/Plan). -func createSchema(customProps map[string]any) map[string]any { - return map[string]any{ - "properties": map[string]any{ - "spec": map[string]any{ - "properties": customProps, - }, - }, - } -} - // createFormItem creates a form item for CustomFormsOverride func createFormItem(path, label, fieldType string) map[string]any { return map[string]any{ @@ -2374,20 +2070,6 @@ func createFormItem(path, label, fieldType string) map[string]any { } } -// createFormItemWithAPI creates a form item with API endpoint for resource-based selects -func createFormItemWithAPI(path, label, fieldType string, apiConfig map[string]any) map[string]any { - item := map[string]any{ - "path": path, - "label": label, - "type": fieldType, - } - // Merge API configuration into the form item - for key, value := range apiConfig { - item[key] = value - } - return item -} - // ---------------- Workloadmonitor specific functions ---------------- // createNamespaceHeader creates a header specifically for namespace with correct colors and text @@ -2637,51 +2319,6 @@ func createWorkloadmonitorHeader() map[string]any { } } -// CreateStaticCFOMapping creates the CFOMapping resource with mappings from static CustomFormsOverrides -func CreateStaticCFOMapping() *dashboardv1alpha1.CFOMapping { - // Build mappings from static CustomFormsOverrides - customFormsOverrides := CreateAllCustomFormsOverrides() - mappings := make(map[string]string, len(customFormsOverrides)) - for _, cfo := range customFormsOverrides { - var spec map[string]any - if err := json.Unmarshal(cfo.Spec.JSON.Raw, &spec); err != nil { - continue - } - customizationID, ok := spec["customizationId"].(string) - if !ok { - continue - } - // Extract the resource path from customizationId (remove "default-" prefix) - resourcePath := strings.TrimPrefix(customizationID, "default-") - mappings[resourcePath] = customizationID - } - - return createCFOMapping("cfomapping", mappings) -} - -// createCFOMapping creates a CFOMapping resource -func createCFOMapping(name string, mappings map[string]string) *dashboardv1alpha1.CFOMapping { - spec := map[string]any{ - "mappings": mappings, - } - jsonData, _ := json.Marshal(spec) - - return &dashboardv1alpha1.CFOMapping{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "dashboard.cozystack.io/v1alpha1", - Kind: "CFOMapping", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: dashboardv1alpha1.ArbitrarySpec{ - JSON: v1.JSON{ - Raw: jsonData, - }, - }, - } -} - // ---------------- Complete resource creation function ---------------- // CreateAllStaticResources creates all static dashboard resources using helper functions @@ -2718,8 +2355,5 @@ func CreateAllStaticResources() []client.Object { resources = append(resources, tableUriMapping) } - // Add CFOMapping - resources = append(resources, CreateStaticCFOMapping()) - return resources } diff --git a/internal/controller/workload_controller_test.go b/internal/controller/workload_controller_test.go index 194a20d3..b454adc3 100644 --- a/internal/controller/workload_controller_test.go +++ b/internal/controller/workload_controller_test.go @@ -43,7 +43,7 @@ func TestWorkloadReconciler_DeletesOnMissingMonitor(t *testing.T) { Name: "pod-foo", Namespace: "default", Labels: map[string]string{ - "workloads.cozystack.io/monitor": "missing-monitor", + "workloadmonitor.cozystack.io/name": "missing-monitor", }, }, } @@ -89,7 +89,7 @@ func TestWorkloadReconciler_KeepsWhenAllExist(t *testing.T) { Name: "pod-foo", Namespace: "default", Labels: map[string]string{ - "workloads.cozystack.io/monitor": "mon", + "workloadmonitor.cozystack.io/name": "mon", }, }, } diff --git a/internal/controller/workloadmonitor_controller.go b/internal/controller/workloadmonitor_controller.go index 35906a87..a684df9b 100644 --- a/internal/controller/workloadmonitor_controller.go +++ b/internal/controller/workloadmonitor_controller.go @@ -4,13 +4,7 @@ import ( "context" "encoding/json" "fmt" - "io" - "net/http" - "net/url" "sort" - "strconv" - "strings" - "time" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -28,29 +22,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - cosiv1alpha1 "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage/v1alpha1" ) -const ( - // namespaceMonitoringLabel is the namespace label that indicates which tenant - // namespace hosts the monitoring stack (VictoriaMetrics/Prometheus). - namespaceMonitoringLabel = "namespace.cozystack.io/monitoring" - workloadLabelPrefix = "workloads.cozystack.io/" - // workloadMonitorLabel is reserved: it names the WorkloadMonitor that owns - // the Workload and is always set by the reconciler, so it is never copied - // from monitor labels. - workloadMonitorLabel = workloadLabelPrefix + "monitor" - // vmSelectService is the well-known service name for VictoriaMetrics vmselect - // within a monitoring namespace. Port 8481, path /select/0/prometheus. - vmSelectService = "vmselect-shortterm" - vmSelectPort = "8481" - vmSelectPath = "/select/0/prometheus" -) - -// prometheusHTTPClient is a dedicated HTTP client for Prometheus queries, -// avoiding the shared http.DefaultClient global. -var prometheusHTTPClient = &http.Client{Timeout: 10 * time.Second} - // WorkloadMonitorReconciler reconciles a WorkloadMonitor object type WorkloadMonitorReconciler struct { client.Client @@ -63,13 +36,6 @@ type WorkloadMonitorReconciler struct { // +kubebuilder:rbac:groups=cozystack.io,resources=workloads/status,verbs=get;update;patch // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch // +kubebuilder:rbac:groups=core,resources=persistentvolumeclaims,verbs=get;list;watch -// +kubebuilder:rbac:groups=core,resources=namespaces,verbs=get -// +kubebuilder:rbac:groups=objectstorage.k8s.io,resources=bucketclaims,verbs=get;list;watch - -// isBucketClaimReady checks if the BucketClaim has been provisioned. -func (r *WorkloadMonitorReconciler) isBucketClaimReady(bc *cosiv1alpha1.BucketClaim) bool { - return bc.Status.BucketReady -} // isServiceReady checks if the service has an external IP bound func (r *WorkloadMonitorReconciler) isServiceReady(svc *corev1.Service) bool { @@ -135,190 +101,6 @@ func updateOwnerReferences(obj metav1.Object, monitor client.Object) { obj.SetOwnerReferences(owners) } -// resolvePrometheusURL returns the Prometheus-compatible API base URL for the given namespace. -// It reads the namespace.cozystack.io/monitoring label to find the monitoring namespace, -// then constructs the vmselect URL. Returns empty string if monitoring is not configured. -func (r *WorkloadMonitorReconciler) resolvePrometheusURL(ctx context.Context, namespace string) string { - logger := log.FromContext(ctx) - ns := &corev1.Namespace{} - if err := r.Get(ctx, types.NamespacedName{Name: namespace}, ns); err != nil { - logger.V(1).Info("Failed to read namespace for monitoring resolution", "namespace", namespace, "error", err) - return "" - } - monitoringNS := ns.Labels[namespaceMonitoringLabel] - if monitoringNS == "" { - return "" - } - return fmt.Sprintf("http://%s.%s.svc:%s%s", vmSelectService, monitoringNS, vmSelectPort, vmSelectPath) -} - -// bucketMetrics holds size metrics for a single bucket, keyed by metric name. -type bucketMetrics struct { - LogicalSize int64 - PhysicalSize int64 - HasLogical bool - HasPhysical bool -} - -// queryAllBucketMetrics fetches SeaweedFS bucket size metrics for the given -// bucket names in a single Prometheus query and returns them keyed by bucket -// name. The query is scoped to only the requested buckets to avoid fetching -// metrics for buckets belonging to other WorkloadMonitors. -func (r *WorkloadMonitorReconciler) queryAllBucketMetrics(ctx context.Context, prometheusBaseURL string, bucketNames []string) map[string]*bucketMetrics { - result := make(map[string]*bucketMetrics) - if prometheusBaseURL == "" || len(bucketNames) == 0 { - return result - } - logger := log.FromContext(ctx) - - query := fmt.Sprintf(`{__name__=~"SeaweedFS_s3_bucket_(size|physical_size)_bytes",bucket=~"%s"}`, strings.Join(bucketNames, "|")) - u, err := url.Parse(strings.TrimRight(prometheusBaseURL, "/") + "/api/v1/query") - if err != nil { - logger.Error(err, "Failed to parse Prometheus URL") - return result - } - u.RawQuery = url.Values{"query": {query}}.Encode() - - httpCtx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - - req, err := http.NewRequestWithContext(httpCtx, http.MethodGet, u.String(), nil) - if err != nil { - logger.Error(err, "Failed to create Prometheus request") - return result - } - - resp, err := prometheusHTTPClient.Do(req) - if err != nil { - logger.V(1).Info("Failed to query Prometheus for bucket metrics", "error", err) - return result - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - logger.V(1).Info("Prometheus returned non-OK status for bucket metrics", "status", resp.StatusCode) - return result - } - - body, err := io.ReadAll(io.LimitReader(resp.Body, 4<<20)) - if err != nil { - logger.Error(err, "Failed to read Prometheus response") - return result - } - - var promResp struct { - Status string `json:"status"` - Data struct { - Result []struct { - Metric map[string]string `json:"metric"` - Value [2]json.RawMessage `json:"value"` - } `json:"result"` - } `json:"data"` - } - if err := json.Unmarshal(body, &promResp); err != nil { - logger.Error(err, "Failed to parse Prometheus response") - return result - } - if promResp.Status != "success" { - return result - } - - for _, r := range promResp.Data.Result { - bucket := r.Metric["bucket"] - metricName := r.Metric["__name__"] - if bucket == "" || metricName == "" { - continue - } - - var valueStr string - if err := json.Unmarshal(r.Value[1], &valueStr); err != nil { - continue - } - val, err := strconv.ParseFloat(valueStr, 64) - if err != nil { - continue - } - - bm, ok := result[bucket] - if !ok { - bm = &bucketMetrics{} - result[bucket] = bm - } - - switch metricName { - case "SeaweedFS_s3_bucket_size_bytes": - bm.LogicalSize = int64(val) - bm.HasLogical = true - case "SeaweedFS_s3_bucket_physical_size_bytes": - bm.PhysicalSize = int64(val) - bm.HasPhysical = true - } - } - - return result -} - -// reconcileBucketClaimForMonitor creates or updates a Workload object for the given BucketClaim and WorkloadMonitor. -func (r *WorkloadMonitorReconciler) reconcileBucketClaimForMonitor( - ctx context.Context, - monitor *cozyv1alpha1.WorkloadMonitor, - bc cosiv1alpha1.BucketClaim, - allMetrics map[string]*bucketMetrics, -) error { - logger := log.FromContext(ctx) - workload := &cozyv1alpha1.Workload{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("bucket-%s", bc.Name), - Namespace: bc.Namespace, - Labels: make(map[string]string, len(bc.Labels)), - }, - } - - resources := make(map[string]resource.Quantity) - - // Look up pre-fetched bucket metrics by the SeaweedFS bucket name. - // bc.Status.BucketName is the COSI Bucket name, which the COSI driver - // uses directly as the SeaweedFS bucket name. - if bm, ok := allMetrics[bc.Status.BucketName]; ok { - if bm.HasLogical { - resources["s3-storage-bytes"] = *resource.NewQuantity(bm.LogicalSize, resource.BinarySI) - } - if bm.HasPhysical { - resources["s3-physical-storage-bytes"] = *resource.NewQuantity(bm.PhysicalSize, resource.BinarySI) - } - } - - monitorLabels := r.getMonitorLabels(monitor) - _, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error { - updateOwnerReferences(workload.GetObjectMeta(), &bc) - - if workload.Labels == nil { - workload.Labels = make(map[string]string) - } - // Apply monitor-level labels first so source-object labels can override on conflict - for k, v := range monitorLabels { - workload.Labels[k] = v - } - for k, v := range bc.Labels { - workload.Labels[k] = v - } - workload.Labels[workloadMonitorLabel] = monitor.Name - - workload.Status.Kind = monitor.Spec.Kind - workload.Status.Type = monitor.Spec.Type - workload.Status.Resources = resources - workload.Status.Operational = r.isBucketClaimReady(&bc) - - return nil - }) - if err != nil { - logger.Error(err, "Failed to CreateOrUpdate Workload", "workload", workload.Name) - return err - } - - return nil -} - // reconcileServiceForMonitor creates or updates a Workload object for the given Service and WorkloadMonitor. func (r *WorkloadMonitorReconciler) reconcileServiceForMonitor( ctx context.Context, @@ -355,22 +137,14 @@ func (r *WorkloadMonitorReconciler) reconcileServiceForMonitor( resourceLabel = fmt.Sprintf("%s.ipaddresspool.metallb.io/requests.ipaddresses", resourceLabel) resources[resourceLabel] = quantity - monitorLabels := r.getMonitorLabels(monitor) _, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error { // Update owner references with the new monitor updateOwnerReferences(workload.GetObjectMeta(), &svc) - // Apply monitor-level labels first so source-object labels can override on conflict - if workload.Labels == nil { - workload.Labels = make(map[string]string) - } - for k, v := range monitorLabels { - workload.Labels[k] = v - } for k, v := range svc.Labels { workload.Labels[k] = v } - workload.Labels[workloadMonitorLabel] = monitor.Name + workload.Labels["workloads.cozystack.io/monitor"] = monitor.Name // Fill Workload status fields: workload.Status.Kind = monitor.Spec.Kind @@ -414,22 +188,14 @@ func (r *WorkloadMonitorReconciler) reconcilePVCForMonitor( resources[resourceLabel] = resourceQuantity } - monitorLabels := r.getMonitorLabels(monitor) _, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error { // Update owner references with the new monitor updateOwnerReferences(workload.GetObjectMeta(), &pvc) - // Apply monitor-level labels first so source-object labels can override on conflict - if workload.Labels == nil { - workload.Labels = make(map[string]string) - } - for k, v := range monitorLabels { - workload.Labels[k] = v - } for k, v := range pvc.Labels { workload.Labels[k] = v } - workload.Labels[workloadMonitorLabel] = monitor.Name + workload.Labels["workloads.cozystack.io/monitor"] = monitor.Name // Fill Workload status fields: workload.Status.Kind = monitor.Spec.Kind @@ -496,22 +262,14 @@ func (r *WorkloadMonitorReconciler) reconcilePodForMonitor( } metaLabels := r.getWorkloadMetadata(&pod) - monitorLabels := r.getMonitorLabels(monitor) _, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error { // Update owner references with the new monitor updateOwnerReferences(workload.GetObjectMeta(), &pod) - // Apply monitor-level labels first so source-object labels can override on conflict - if workload.Labels == nil { - workload.Labels = make(map[string]string) - } - for k, v := range monitorLabels { - workload.Labels[k] = v - } for k, v := range pod.Labels { workload.Labels[k] = v } - workload.Labels[workloadMonitorLabel] = monitor.Name + workload.Labels["workloads.cozystack.io/monitor"] = monitor.Name // Add workload meta to labels for k, v := range metaLabels { @@ -617,34 +375,6 @@ func (r *WorkloadMonitorReconciler) Reconcile(ctx context.Context, req ctrl.Requ } } - bucketClaimList := &cosiv1alpha1.BucketClaimList{} - if err := r.List( - ctx, - bucketClaimList, - client.InNamespace(monitor.Namespace), - client.MatchingLabels(monitor.Spec.Selector), - ); err != nil { - logger.Error(err, "Unable to list BucketClaims for WorkloadMonitor", "monitor", monitor.Name) - return ctrl.Result{}, err - } - - if len(bucketClaimList.Items) > 0 { - bucketPromURL := r.resolvePrometheusURL(ctx, monitor.Namespace) - var bucketNames []string - for _, bc := range bucketClaimList.Items { - if bc.Status.BucketName != "" { - bucketNames = append(bucketNames, bc.Status.BucketName) - } - } - allBucketMetrics := r.queryAllBucketMetrics(ctx, bucketPromURL, bucketNames) - for _, bc := range bucketClaimList.Items { - if err := r.reconcileBucketClaimForMonitor(ctx, monitor, bc, allBucketMetrics); err != nil { - logger.Error(err, "Failed to reconcile Workload for BucketClaim", "BucketClaim", bc.Name) - continue - } - } - } - // Update WorkloadMonitor status based on observed pods monitor.Status.ObservedReplicas = observedReplicas monitor.Status.AvailableReplicas = availableReplicas @@ -658,12 +388,10 @@ func (r *WorkloadMonitorReconciler) Reconcile(ctx context.Context, req ctrl.Requ fresh.Status.ObservedReplicas = observedReplicas fresh.Status.AvailableReplicas = availableReplicas - // Default to operational = true, but check MinReplicas if set. - // Use fresh.Spec to avoid making decisions based on a stale cached copy - // when the spec was updated between the initial read and this retry. - fresh.Status.Operational = pointer.Bool(true) - if fresh.Spec.MinReplicas != nil && availableReplicas < *fresh.Spec.MinReplicas { - fresh.Status.Operational = pointer.Bool(false) + // Default to operational = true, but check MinReplicas if set + monitor.Status.Operational = pointer.Bool(true) + if monitor.Spec.MinReplicas != nil && availableReplicas < *monitor.Spec.MinReplicas { + monitor.Status.Operational = pointer.Bool(false) } return r.Status().Update(ctx, fresh) }) @@ -672,12 +400,7 @@ func (r *WorkloadMonitorReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, err } - // Requeue periodically if there are BucketClaims to keep sizes up to date. - // Bucket sizes come from Prometheus metrics that update every 60s. - if len(bucketClaimList.Items) > 0 { - return ctrl.Result{RequeueAfter: 60 * time.Second}, nil - } - + // Return without requeue if we want purely event-driven reconciliations return ctrl.Result{}, nil } @@ -696,11 +419,6 @@ func (r *WorkloadMonitorReconciler) SetupWithManager(mgr ctrl.Manager) error { &corev1.PersistentVolumeClaim{}, handler.EnqueueRequestsFromMapFunc(mapObjectToMonitor(&corev1.PersistentVolumeClaim{}, r.Client)), ). - // Watch BucketClaims for S3 bucket billing - Watches( - &cosiv1alpha1.BucketClaim{}, - handler.EnqueueRequestsFromMapFunc(mapObjectToMonitor(&cosiv1alpha1.BucketClaim{}, r.Client)), - ). // Watch for changes to Workload objects we create (owned by WorkloadMonitor) Owns(&cozyv1alpha1.Workload{}). Complete(r) @@ -754,21 +472,3 @@ func (r *WorkloadMonitorReconciler) getWorkloadMetadata(obj client.Object) map[s } return labels } - -// getMonitorLabels extracts workloads.cozystack.io/* labels from a WorkloadMonitor -// so they can be propagated onto Workload objects created for pods, PVCs, services, -// or bucket claims. The monitor label "workloads.cozystack.io/monitor" is reserved -// and set separately per Workload, so it is excluded here. -func (r *WorkloadMonitorReconciler) getMonitorLabels(monitor *cozyv1alpha1.WorkloadMonitor) map[string]string { - labels := make(map[string]string) - for k, v := range monitor.GetLabels() { - if !strings.HasPrefix(k, workloadLabelPrefix) { - continue - } - if k == workloadMonitorLabel { - continue - } - labels[k] = v - } - return labels -} diff --git a/internal/controller/workloadmonitor_controller_test.go b/internal/controller/workloadmonitor_controller_test.go deleted file mode 100644 index 355b0379..00000000 --- a/internal/controller/workloadmonitor_controller_test.go +++ /dev/null @@ -1,846 +0,0 @@ -package controller - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "strings" - "testing" - - cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - cosiv1alpha1 "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage/v1alpha1" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - "sigs.k8s.io/controller-runtime/pkg/reconcile" -) - -func TestReconcile_OperationalStatusPersisted(t *testing.T) { - scheme := runtime.NewScheme() - _ = cozyv1alpha1.AddToScheme(scheme) - _ = corev1.AddToScheme(scheme) - _ = cosiv1alpha1.AddToScheme(scheme) - - minReplicas := int32(2) - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-monitor", - Namespace: "default", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Selector: map[string]string{"app": "test"}, - MinReplicas: &minReplicas, - }, - } - - // Create one pod that is ready — availableReplicas=1 < minReplicas=2, so Operational should be false - pod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-pod-1", - Namespace: "default", - Labels: map[string]string{"app": "test"}, - }, - Status: corev1.PodStatus{ - Conditions: []corev1.PodCondition{ - {Type: corev1.PodReady, Status: corev1.ConditionTrue}, - }, - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(monitor, pod). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: scheme} - req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-monitor", Namespace: "default"}} - - _, err := reconciler.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - // Fetch the monitor back from fake client and check Operational is persisted - updated := &cozyv1alpha1.WorkloadMonitor{} - if err := fakeClient.Get(context.TODO(), req.NamespacedName, updated); err != nil { - t.Fatalf("Failed to get updated WorkloadMonitor: %v", err) - } - - if updated.Status.Operational == nil { - t.Fatal("Expected Operational to be set, got nil") - } - if *updated.Status.Operational { - t.Error("Expected Operational=false (1 available < 2 minReplicas), got true") - } - if updated.Status.ObservedReplicas != 1 { - t.Errorf("Expected ObservedReplicas=1, got %d", updated.Status.ObservedReplicas) - } - if updated.Status.AvailableReplicas != 1 { - t.Errorf("Expected AvailableReplicas=1, got %d", updated.Status.AvailableReplicas) - } -} - -func TestReconcile_OperationalTrue_WhenEnoughReplicas(t *testing.T) { - scheme := runtime.NewScheme() - _ = cozyv1alpha1.AddToScheme(scheme) - _ = corev1.AddToScheme(scheme) - _ = cosiv1alpha1.AddToScheme(scheme) - - minReplicas := int32(1) - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-monitor", - Namespace: "default", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Selector: map[string]string{"app": "test"}, - MinReplicas: &minReplicas, - }, - } - - pod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-pod-1", - Namespace: "default", - Labels: map[string]string{"app": "test"}, - }, - Status: corev1.PodStatus{ - Conditions: []corev1.PodCondition{ - {Type: corev1.PodReady, Status: corev1.ConditionTrue}, - }, - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(monitor, pod). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: scheme} - req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-monitor", Namespace: "default"}} - - _, err := reconciler.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - updated := &cozyv1alpha1.WorkloadMonitor{} - if err := fakeClient.Get(context.TODO(), req.NamespacedName, updated); err != nil { - t.Fatalf("Failed to get updated WorkloadMonitor: %v", err) - } - - if updated.Status.Operational == nil { - t.Fatal("Expected Operational to be set, got nil") - } - if !*updated.Status.Operational { - t.Error("Expected Operational=true (1 available >= 1 minReplicas), got false") - } -} - -func TestGetMonitorLabels(t *testing.T) { - tests := []struct { - name string - labels map[string]string - expected map[string]string - }{ - { - name: "nil labels", - labels: nil, - expected: map[string]string{}, - }, - { - name: "only workloads.cozystack.io/* labels are propagated", - labels: map[string]string{ - "workloads.cozystack.io/resource-preset": "medium", - "app.kubernetes.io/name": "postgres", - "custom.example.com/team": "platform", - }, - expected: map[string]string{ - "workloads.cozystack.io/resource-preset": "medium", - }, - }, - { - name: "monitor label is reserved and excluded", - labels: map[string]string{ - "workloads.cozystack.io/resource-preset": "small", - "workloads.cozystack.io/monitor": "should-be-dropped", - }, - expected: map[string]string{ - "workloads.cozystack.io/resource-preset": "small", - }, - }, - { - name: "multiple workloads.cozystack.io labels propagate", - labels: map[string]string{ - "workloads.cozystack.io/resource-preset": "large", - "workloads.cozystack.io/tier": "db", - }, - expected: map[string]string{ - "workloads.cozystack.io/resource-preset": "large", - "workloads.cozystack.io/tier": "db", - }, - }, - { - name: "no matching labels returns empty map", - labels: map[string]string{ - "app.kubernetes.io/name": "postgres", - }, - expected: map[string]string{}, - }, - } - - r := &WorkloadMonitorReconciler{} - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{Labels: tc.labels}, - } - got := r.getMonitorLabels(monitor) - if len(got) != len(tc.expected) { - t.Fatalf("expected %d labels, got %d (%v)", len(tc.expected), len(got), got) - } - for k, v := range tc.expected { - if gv, ok := got[k]; !ok || gv != v { - t.Errorf("expected label %q=%q, got %q", k, v, gv) - } - } - }) - } -} - -func TestReconcile_MonitorLabelsPropagatedToPodWorkload(t *testing.T) { - scheme := runtime.NewScheme() - _ = cozyv1alpha1.AddToScheme(scheme) - _ = corev1.AddToScheme(scheme) - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-monitor", - Namespace: "default", - Labels: map[string]string{ - "workloads.cozystack.io/resource-preset": "medium", - "app.kubernetes.io/name": "ignored-not-propagated", - }, - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Selector: map[string]string{"app": "test"}, - Kind: "postgres", - Type: "postgres", - }, - } - - pod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-pod-1", - Namespace: "default", - Labels: map[string]string{ - "app": "test", - "app.kubernetes.io/name": "pod-wins-on-conflict", - }, - }, - Status: corev1.PodStatus{ - Conditions: []corev1.PodCondition{ - {Type: corev1.PodReady, Status: corev1.ConditionTrue}, - }, - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(monitor, pod). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: scheme} - req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-monitor", Namespace: "default"}} - if _, err := reconciler.Reconcile(context.TODO(), req); err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - workload := &cozyv1alpha1.Workload{} - if err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: "pod-test-pod-1", Namespace: "default"}, workload); err != nil { - t.Fatalf("Failed to get Workload: %v", err) - } - - if got := workload.Labels["workloads.cozystack.io/resource-preset"]; got != "medium" { - t.Errorf("expected monitor label propagated, got %q", got) - } - // Non-workloads.cozystack.io monitor labels must not be copied - if _, ok := workload.Labels["app.kubernetes.io/name"]; !ok { - t.Error("expected pod label to be present on Workload") - } - // Source-object label takes precedence on conflict - if got := workload.Labels["app.kubernetes.io/name"]; got != "pod-wins-on-conflict" { - t.Errorf("expected pod label to win on conflict, got %q", got) - } - // Reserved monitor label is always set from the monitor name - if got := workload.Labels["workloads.cozystack.io/monitor"]; got != "test-monitor" { - t.Errorf("expected monitor-name label, got %q", got) - } -} - -func TestReconcile_BackwardCompat_NoMonitorLabels(t *testing.T) { - scheme := runtime.NewScheme() - _ = cozyv1alpha1.AddToScheme(scheme) - _ = corev1.AddToScheme(scheme) - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-monitor", - Namespace: "default", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Selector: map[string]string{"app": "test"}, - }, - } - - pod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-pod-1", - Namespace: "default", - Labels: map[string]string{"app": "test"}, - }, - Status: corev1.PodStatus{ - Conditions: []corev1.PodCondition{ - {Type: corev1.PodReady, Status: corev1.ConditionTrue}, - }, - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(monitor, pod). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: scheme} - req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-monitor", Namespace: "default"}} - if _, err := reconciler.Reconcile(context.TODO(), req); err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - workload := &cozyv1alpha1.Workload{} - if err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: "pod-test-pod-1", Namespace: "default"}, workload); err != nil { - t.Fatalf("Failed to get Workload: %v", err) - } - for k := range workload.Labels { - if strings.HasPrefix(k, "workloads.cozystack.io/") && k != "workloads.cozystack.io/monitor" { - t.Errorf("unexpected workload label present: %q", k) - } - } -} - -func TestReconcile_OperationalTrue_WhenNoMinReplicas(t *testing.T) { - scheme := runtime.NewScheme() - _ = cozyv1alpha1.AddToScheme(scheme) - _ = corev1.AddToScheme(scheme) - _ = cosiv1alpha1.AddToScheme(scheme) - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-monitor", - Namespace: "default", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Selector: map[string]string{"app": "test"}, - // No MinReplicas — should default to operational=true - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(monitor). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: scheme} - req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-monitor", Namespace: "default"}} - - _, err := reconciler.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - updated := &cozyv1alpha1.WorkloadMonitor{} - if err := fakeClient.Get(context.TODO(), req.NamespacedName, updated); err != nil { - t.Fatalf("Failed to get updated WorkloadMonitor: %v", err) - } - - if updated.Status.Operational == nil { - t.Fatal("Expected Operational to be set, got nil") - } - if !*updated.Status.Operational { - t.Error("Expected Operational=true (no MinReplicas constraint), got false") - } -} - -func newTestScheme() *runtime.Scheme { - s := runtime.NewScheme() - _ = cozyv1alpha1.AddToScheme(s) - _ = corev1.AddToScheme(s) - _ = cosiv1alpha1.AddToScheme(s) - return s -} - -func TestReconcileBucketClaimCreatesWorkload(t *testing.T) { - s := newTestScheme() - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Kind: "bucket", - Type: "s3", - Selector: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - }, - }, - } - - bc := &cosiv1alpha1.BucketClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - Labels: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - }, - }, - Spec: cosiv1alpha1.BucketClaimSpec{ - BucketClassName: "seaweedfs", - Protocols: []cosiv1alpha1.Protocol{cosiv1alpha1.ProtocolS3}, - }, - Status: cosiv1alpha1.BucketClaimStatus{ - BucketReady: true, - BucketName: "cosi-abc123", - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(s). - WithObjects(monitor, bc). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: s} - req := reconcile.Request{NamespacedName: types.NamespacedName{ - Name: "my-bucket", - Namespace: "tenant-demo", - }} - - _, err := reconciler.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - workload := &cozyv1alpha1.Workload{} - err = fakeClient.Get(context.TODO(), types.NamespacedName{ - Name: "bucket-my-bucket", - Namespace: "tenant-demo", - }, workload) - if err != nil { - t.Fatalf("expected Workload to be created, got error: %v", err) - } - - if workload.Status.Kind != "bucket" { - t.Errorf("expected Kind=bucket, got %q", workload.Status.Kind) - } - if workload.Status.Type != "s3" { - t.Errorf("expected Type=s3, got %q", workload.Status.Type) - } - if !workload.Status.Operational { - t.Error("expected Operational=true for ready BucketClaim") - } -} - -func TestReconcileBucketClaimNotReady(t *testing.T) { - s := newTestScheme() - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Kind: "bucket", - Type: "s3", - Selector: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - }, - }, - } - - bc := &cosiv1alpha1.BucketClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - Labels: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - }, - }, - Spec: cosiv1alpha1.BucketClaimSpec{ - BucketClassName: "seaweedfs", - Protocols: []cosiv1alpha1.Protocol{cosiv1alpha1.ProtocolS3}, - }, - Status: cosiv1alpha1.BucketClaimStatus{ - BucketReady: false, - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(s). - WithObjects(monitor, bc). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: s} - req := reconcile.Request{NamespacedName: types.NamespacedName{ - Name: "my-bucket", - Namespace: "tenant-demo", - }} - - _, err := reconciler.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - workload := &cozyv1alpha1.Workload{} - err = fakeClient.Get(context.TODO(), types.NamespacedName{ - Name: "bucket-my-bucket", - Namespace: "tenant-demo", - }, workload) - if err != nil { - t.Fatalf("expected Workload to be created, got error: %v", err) - } - - if workload.Status.Operational { - t.Error("expected Operational=false for not-ready BucketClaim") - } -} - -func TestReconcile_MonitorLabelsPropagatedToBucketClaimWorkload(t *testing.T) { - s := newTestScheme() - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - Labels: map[string]string{ - "workloads.cozystack.io/resource-preset": "medium", - "app.kubernetes.io/name": "ignored-not-propagated", - }, - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Kind: "bucket", - Type: "s3", - Selector: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - }, - }, - } - - bc := &cosiv1alpha1.BucketClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - Labels: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - "app.kubernetes.io/name": "bucket-wins-on-conflict", - }, - }, - Spec: cosiv1alpha1.BucketClaimSpec{ - BucketClassName: "seaweedfs", - Protocols: []cosiv1alpha1.Protocol{cosiv1alpha1.ProtocolS3}, - }, - Status: cosiv1alpha1.BucketClaimStatus{ - BucketReady: true, - BucketName: "cosi-abc123", - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(s). - WithObjects(monitor, bc). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: s} - req := reconcile.Request{NamespacedName: types.NamespacedName{ - Name: "my-bucket", - Namespace: "tenant-demo", - }} - if _, err := reconciler.Reconcile(context.TODO(), req); err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - workload := &cozyv1alpha1.Workload{} - if err := fakeClient.Get(context.TODO(), types.NamespacedName{ - Name: "bucket-my-bucket", - Namespace: "tenant-demo", - }, workload); err != nil { - t.Fatalf("Failed to get Workload: %v", err) - } - - if got := workload.Labels["workloads.cozystack.io/resource-preset"]; got != "medium" { - t.Errorf("expected monitor label propagated, got %q", got) - } - // Source-object label takes precedence on conflict - if got := workload.Labels["app.kubernetes.io/name"]; got != "bucket-wins-on-conflict" { - t.Errorf("expected bucket claim label to win on conflict, got %q", got) - } - // Reserved monitor label is always set from the monitor name - if got := workload.Labels["workloads.cozystack.io/monitor"]; got != "my-bucket" { - t.Errorf("expected monitor-name label, got %q", got) - } -} - -func TestReconcileNoBucketClaimSkips(t *testing.T) { - s := newTestScheme() - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-postgres", - Namespace: "tenant-demo", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Kind: "postgres", - Type: "postgres", - Selector: map[string]string{ - "app.kubernetes.io/instance": "my-postgres", - }, - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(s). - WithObjects(monitor). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: s} - req := reconcile.Request{NamespacedName: types.NamespacedName{ - Name: "my-postgres", - Namespace: "tenant-demo", - }} - - _, err := reconciler.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - workloadList := &cozyv1alpha1.WorkloadList{} - err = fakeClient.List(context.TODO(), workloadList) - if err != nil { - t.Fatalf("List returned error: %v", err) - } - - for _, w := range workloadList.Items { - if w.Status.Kind == "bucket" { - t.Error("expected no bucket workloads to be created for postgres monitor") - } - } -} - -func TestQueryAllBucketMetrics(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, `{"status":"success","data":{"resultType":"vector","result":[ - {"metric":{"__name__":"SeaweedFS_s3_bucket_size_bytes","bucket":"bucket-aaa"},"value":[1713000000,"10485864"]}, - {"metric":{"__name__":"SeaweedFS_s3_bucket_physical_size_bytes","bucket":"bucket-aaa"},"value":[1713000000,"20971728"]}, - {"metric":{"__name__":"SeaweedFS_s3_bucket_size_bytes","bucket":"bucket-bbb"},"value":[1713000000,"0"]} - ]}}`) - })) - defer srv.Close() - - reconciler := &WorkloadMonitorReconciler{} - metrics := reconciler.queryAllBucketMetrics(context.TODO(), srv.URL, []string{"bucket-aaa", "bucket-bbb"}) - - bm, ok := metrics["bucket-aaa"] - if !ok { - t.Fatal("expected bucket-aaa in metrics") - } - if !bm.HasLogical || bm.LogicalSize != 10485864 { - t.Errorf("expected logical=10485864, got %d", bm.LogicalSize) - } - if !bm.HasPhysical || bm.PhysicalSize != 20971728 { - t.Errorf("expected physical=20971728, got %d", bm.PhysicalSize) - } - - bm2, ok := metrics["bucket-bbb"] - if !ok { - t.Fatal("expected bucket-bbb in metrics") - } - if !bm2.HasLogical || bm2.LogicalSize != 0 { - t.Errorf("expected logical=0 for empty bucket, got %d", bm2.LogicalSize) - } - if bm2.HasPhysical { - t.Error("expected no physical size for bucket-bbb") - } -} - -func TestQueryAllBucketMetricsEmpty(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, `{"status":"success","data":{"resultType":"vector","result":[]}}`) - })) - defer srv.Close() - - reconciler := &WorkloadMonitorReconciler{} - metrics := reconciler.queryAllBucketMetrics(context.TODO(), srv.URL, []string{"bucket-aaa", "bucket-bbb"}) - if len(metrics) != 0 { - t.Errorf("expected empty metrics, got %d", len(metrics)) - } -} - -func TestQueryAllBucketMetricsServerError(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) - })) - defer srv.Close() - - reconciler := &WorkloadMonitorReconciler{} - metrics := reconciler.queryAllBucketMetrics(context.TODO(), srv.URL, []string{"bucket-aaa", "bucket-bbb"}) - if len(metrics) != 0 { - t.Errorf("expected empty metrics on error, got %d", len(metrics)) - } -} - -func TestQueryAllBucketMetricsNoURL(t *testing.T) { - reconciler := &WorkloadMonitorReconciler{} - metrics := reconciler.queryAllBucketMetrics(context.TODO(), "", nil) - if len(metrics) != 0 { - t.Errorf("expected empty metrics when URL is empty, got %d", len(metrics)) - } -} - -func TestResolvePrometheusURL(t *testing.T) { - s := newTestScheme() - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tenant-demo", - Labels: map[string]string{ - "namespace.cozystack.io/monitoring": "tenant-root", - }, - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(s). - WithObjects(ns). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: s} - url := reconciler.resolvePrometheusURL(context.TODO(), "tenant-demo") - - expected := "http://vmselect-shortterm.tenant-root.svc:8481/select/0/prometheus" - if url != expected { - t.Errorf("expected %q, got %q", expected, url) - } -} - -func TestResolvePrometheusURLNoLabel(t *testing.T) { - s := newTestScheme() - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tenant-demo", - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(s). - WithObjects(ns). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: s} - url := reconciler.resolvePrometheusURL(context.TODO(), "tenant-demo") - - if url != "" { - t.Errorf("expected empty URL when no monitoring label, got %q", url) - } -} - -func TestReconcileBucketClaimRequeuesWhenBucketsExist(t *testing.T) { - s := newTestScheme() - - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tenant-demo", - }, - } - - monitor := &cozyv1alpha1.WorkloadMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - }, - Spec: cozyv1alpha1.WorkloadMonitorSpec{ - Kind: "bucket", - Type: "s3", - Selector: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - }, - }, - } - - bc := &cosiv1alpha1.BucketClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: "my-bucket", - Namespace: "tenant-demo", - Labels: map[string]string{ - "app.kubernetes.io/instance": "my-bucket", - }, - }, - Spec: cosiv1alpha1.BucketClaimSpec{ - BucketClassName: "seaweedfs", - Protocols: []cosiv1alpha1.Protocol{cosiv1alpha1.ProtocolS3}, - }, - Status: cosiv1alpha1.BucketClaimStatus{ - BucketReady: true, - BucketName: "cosi-abc123", - }, - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(s). - WithObjects(ns, monitor, bc). - WithStatusSubresource(monitor). - Build() - - reconciler := &WorkloadMonitorReconciler{Client: fakeClient, Scheme: s} - req := reconcile.Request{NamespacedName: types.NamespacedName{ - Name: "my-bucket", - Namespace: "tenant-demo", - }} - - result, err := reconciler.Reconcile(context.TODO(), req) - if err != nil { - t.Fatalf("Reconcile returned error: %v", err) - } - - if result.RequeueAfter == 0 { - t.Error("expected RequeueAfter > 0 when buckets exist") - } - - workload := &cozyv1alpha1.Workload{} - err = fakeClient.Get(context.TODO(), types.NamespacedName{ - Name: "bucket-my-bucket", - Namespace: "tenant-demo", - }, workload) - if err != nil { - t.Fatalf("expected Workload to be created, got error: %v", err) - } - - // Without monitoring label on namespace, no size metrics should be set - if _, ok := workload.Status.Resources["s3-storage-bytes"]; ok { - t.Error("expected no s3-storage-bytes when monitoring is not configured") - } - if len(workload.Status.Resources) != 0 { - t.Errorf("expected empty resources without monitoring, got %v", workload.Status.Resources) - } -} diff --git a/internal/crdinstall/install.go b/internal/crdinstall/install.go deleted file mode 100644 index 5143f2e6..00000000 --- a/internal/crdinstall/install.go +++ /dev/null @@ -1,112 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package crdinstall - -import ( - "context" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/cozystack/cozystack/internal/manifestutil" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -// Install applies Cozystack CRDs using embedded manifests. -// It extracts the manifests and applies them to the cluster using server-side apply, -// then waits for all CRDs to have the Established condition. -func Install(ctx context.Context, k8sClient client.Client, writeEmbeddedManifests func(string) error) error { - logger := log.FromContext(ctx) - - tmpDir, err := os.MkdirTemp("", "crd-install-*") - if err != nil { - return fmt.Errorf("failed to create temp directory: %w", err) - } - defer os.RemoveAll(tmpDir) - - manifestsDir := filepath.Join(tmpDir, "manifests") - if err := os.MkdirAll(manifestsDir, 0755); err != nil { - return fmt.Errorf("failed to create manifests directory: %w", err) - } - - if err := writeEmbeddedManifests(manifestsDir); err != nil { - return fmt.Errorf("failed to extract embedded manifests: %w", err) - } - - entries, err := os.ReadDir(manifestsDir) - if err != nil { - return fmt.Errorf("failed to read manifests directory: %w", err) - } - - var manifestFiles []string - for _, entry := range entries { - if strings.HasSuffix(entry.Name(), ".yaml") { - manifestFiles = append(manifestFiles, filepath.Join(manifestsDir, entry.Name())) - } - } - - if len(manifestFiles) == 0 { - return fmt.Errorf("no YAML manifest files found in directory") - } - - var objects []*unstructured.Unstructured - for _, manifestPath := range manifestFiles { - objs, err := manifestutil.ParseManifestFile(manifestPath) - if err != nil { - return fmt.Errorf("failed to parse manifests from %s: %w", manifestPath, err) - } - objects = append(objects, objs...) - } - - if len(objects) == 0 { - return fmt.Errorf("no objects found in manifests") - } - - // Validate all objects are CRDs — reject anything else to prevent - // accidental force-apply of arbitrary resources. - for _, obj := range objects { - if obj.GetAPIVersion() != "apiextensions.k8s.io/v1" || obj.GetKind() != "CustomResourceDefinition" { - return fmt.Errorf("unexpected object %s %s/%s in CRD manifests, only apiextensions.k8s.io/v1 CustomResourceDefinition is allowed", - obj.GetAPIVersion(), obj.GetKind(), obj.GetName()) - } - } - - logger.Info("Applying Cozystack CRDs", "count", len(objects)) - for _, obj := range objects { - patchOptions := &client.PatchOptions{ - FieldManager: "cozystack-operator", - Force: func() *bool { b := true; return &b }(), - } - - if err := k8sClient.Patch(ctx, obj, client.Apply, patchOptions); err != nil { - return fmt.Errorf("failed to apply CRD %s: %w", obj.GetName(), err) - } - logger.Info("Applied CRD", "name", obj.GetName()) - } - - crdNames := manifestutil.CollectCRDNames(objects) - if err := manifestutil.WaitForCRDsEstablished(ctx, k8sClient, crdNames); err != nil { - return fmt.Errorf("CRDs not established after apply: %w", err) - } - - logger.Info("CRD installation completed successfully") - return nil -} diff --git a/internal/crdinstall/install_test.go b/internal/crdinstall/install_test.go deleted file mode 100644 index 870a146c..00000000 --- a/internal/crdinstall/install_test.go +++ /dev/null @@ -1,302 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package crdinstall - -import ( - "context" - "fmt" - "os" - "path/filepath" - "strings" - "testing" - "time" - - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - "sigs.k8s.io/controller-runtime/pkg/client/interceptor" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" -) - -func TestWriteEmbeddedManifests(t *testing.T) { - tmpDir := t.TempDir() - - if err := WriteEmbeddedManifests(tmpDir); err != nil { - t.Fatalf("WriteEmbeddedManifests() error = %v", err) - } - - entries, err := os.ReadDir(tmpDir) - if err != nil { - t.Fatalf("failed to read output dir: %v", err) - } - - var yamlFiles []string - for _, e := range entries { - if strings.HasSuffix(e.Name(), ".yaml") { - yamlFiles = append(yamlFiles, e.Name()) - } - } - - if len(yamlFiles) == 0 { - t.Error("WriteEmbeddedManifests() produced no YAML files") - } - - expectedFiles := []string{ - "cozystack.io_packages.yaml", - "cozystack.io_packagesources.yaml", - } - for _, expected := range expectedFiles { - found := false - for _, actual := range yamlFiles { - if actual == expected { - found = true - break - } - } - if !found { - t.Errorf("expected file %q not found in output, got %v", expected, yamlFiles) - } - } - - // Verify files are non-empty - for _, f := range yamlFiles { - data, err := os.ReadFile(filepath.Join(tmpDir, f)) - if err != nil { - t.Errorf("failed to read %s: %v", f, err) - continue - } - if len(data) == 0 { - t.Errorf("file %s is empty", f) - } - } -} - -func TestWriteEmbeddedManifests_filePermissions(t *testing.T) { - tmpDir := t.TempDir() - - if err := WriteEmbeddedManifests(tmpDir); err != nil { - t.Fatalf("WriteEmbeddedManifests() error = %v", err) - } - - entries, err := os.ReadDir(tmpDir) - if err != nil { - t.Fatalf("failed to read output dir: %v", err) - } - - for _, e := range entries { - if !strings.HasSuffix(e.Name(), ".yaml") { - continue - } - info, err := e.Info() - if err != nil { - t.Errorf("failed to get info for %s: %v", e.Name(), err) - continue - } - perm := info.Mode().Perm() - if perm&0o077 != 0 { - t.Errorf("file %s has overly permissive mode %o, expected no group/other access", e.Name(), perm) - } - } -} - -// newCRDManifestWriter returns a function that writes test CRD YAML files. -func newCRDManifestWriter(crds ...string) func(string) error { - return func(dir string) error { - for i, crd := range crds { - filename := filepath.Join(dir, fmt.Sprintf("crd%d.yaml", i+1)) - if err := os.WriteFile(filename, []byte(crd), 0600); err != nil { - return err - } - } - return nil - } -} - -var testCRD1 = `apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: packages.cozystack.io -spec: - group: cozystack.io - names: - kind: Package - plural: packages - scope: Namespaced - versions: - - name: v1alpha1 - served: true - storage: true - schema: - openAPIV3Schema: - type: object -` - -var testCRD2 = `apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: packagesources.cozystack.io -spec: - group: cozystack.io - names: - kind: PackageSource - plural: packagesources - scope: Namespaced - versions: - - name: v1alpha1 - served: true - storage: true - schema: - openAPIV3Schema: - type: object -` - -// establishedInterceptor simulates CRDs becoming Established in the API server. -func establishedInterceptor() interceptor.Funcs { - return interceptor.Funcs{ - Get: func(ctx context.Context, c client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - if err := c.Get(ctx, key, obj, opts...); err != nil { - return err - } - u, ok := obj.(*unstructured.Unstructured) - if !ok { - return nil - } - if u.GetKind() == "CustomResourceDefinition" { - _ = unstructured.SetNestedSlice(u.Object, []interface{}{ - map[string]interface{}{ - "type": "Established", - "status": "True", - }, - }, "status", "conditions") - } - return nil - }, - } -} - -func TestInstall_appliesAllCRDs(t *testing.T) { - log.SetLogger(zap.New(zap.UseDevMode(true))) - - scheme := runtime.NewScheme() - if err := apiextensionsv1.AddToScheme(scheme); err != nil { - t.Fatalf("failed to add apiextensions to scheme: %v", err) - } - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithInterceptorFuncs(establishedInterceptor()). - Build() - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - ctx = log.IntoContext(ctx, log.FromContext(context.Background())) - - err := Install(ctx, fakeClient, newCRDManifestWriter(testCRD1, testCRD2)) - if err != nil { - t.Fatalf("Install() error = %v", err) - } -} - -func TestInstall_noManifests(t *testing.T) { - log.SetLogger(zap.New(zap.UseDevMode(true))) - - scheme := runtime.NewScheme() - fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - ctx = log.IntoContext(ctx, log.FromContext(context.Background())) - - err := Install(ctx, fakeClient, func(string) error { return nil }) - if err == nil { - t.Error("Install() expected error for empty manifests, got nil") - } - if !strings.Contains(err.Error(), "no YAML manifest files found") { - t.Errorf("Install() error = %v, want error containing 'no YAML manifest files found'", err) - } -} - -func TestInstall_writeManifestsFails(t *testing.T) { - log.SetLogger(zap.New(zap.UseDevMode(true))) - - scheme := runtime.NewScheme() - fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - ctx = log.IntoContext(ctx, log.FromContext(context.Background())) - - err := Install(ctx, fakeClient, func(string) error { return os.ErrPermission }) - if err == nil { - t.Error("Install() expected error when writeManifests fails, got nil") - } -} - -func TestInstall_rejectsNonCRDObjects(t *testing.T) { - log.SetLogger(zap.New(zap.UseDevMode(true))) - - scheme := runtime.NewScheme() - if err := apiextensionsv1.AddToScheme(scheme); err != nil { - t.Fatalf("failed to add apiextensions to scheme: %v", err) - } - - fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() - - nonCRD := `apiVersion: v1 -kind: Namespace -metadata: - name: should-not-be-applied -` - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - ctx = log.IntoContext(ctx, log.FromContext(context.Background())) - - err := Install(ctx, fakeClient, newCRDManifestWriter(nonCRD)) - if err == nil { - t.Fatal("Install() expected error for non-CRD object, got nil") - } - if !strings.Contains(err.Error(), "unexpected object") { - t.Errorf("Install() error = %v, want error containing 'unexpected object'", err) - } -} - -func TestInstall_crdNotEstablished(t *testing.T) { - log.SetLogger(zap.New(zap.UseDevMode(true))) - - scheme := runtime.NewScheme() - if err := apiextensionsv1.AddToScheme(scheme); err != nil { - t.Fatalf("failed to add apiextensions to scheme: %v", err) - } - - // No interceptor: CRDs will never get Established condition - fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - ctx = log.IntoContext(ctx, log.FromContext(context.Background())) - - err := Install(ctx, fakeClient, newCRDManifestWriter(testCRD1)) - if err == nil { - t.Fatal("Install() expected error when CRDs never become established, got nil") - } - if !strings.Contains(err.Error(), "CRDs not established") { - t.Errorf("Install() error = %v, want error containing 'CRDs not established'", err) - } -} diff --git a/internal/crdinstall/manifests.embed.go b/internal/crdinstall/manifests.embed.go deleted file mode 100644 index 7464e54e..00000000 --- a/internal/crdinstall/manifests.embed.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package crdinstall - -import ( - "embed" - "fmt" - "io/fs" - "os" - "path" - "path/filepath" -) - -//go:embed manifests/*.yaml -var embeddedCRDManifests embed.FS - -// WriteEmbeddedManifests extracts embedded CRD manifests to a directory. -func WriteEmbeddedManifests(dir string) error { - manifests, err := fs.ReadDir(embeddedCRDManifests, "manifests") - if err != nil { - return fmt.Errorf("failed to read embedded manifests: %w", err) - } - - for _, manifest := range manifests { - data, err := fs.ReadFile(embeddedCRDManifests, path.Join("manifests", manifest.Name())) - if err != nil { - return fmt.Errorf("failed to read file %s: %w", manifest.Name(), err) - } - - outputPath := filepath.Join(dir, manifest.Name()) - if err := os.WriteFile(outputPath, data, 0600); err != nil { - return fmt.Errorf("failed to write file %s: %w", outputPath, err) - } - } - - return nil -} diff --git a/internal/fluxinstall/install.go b/internal/fluxinstall/install.go index 4ae6f4cb..2097ecfb 100644 --- a/internal/fluxinstall/install.go +++ b/internal/fluxinstall/install.go @@ -17,15 +17,18 @@ limitations under the License. package fluxinstall import ( + "bufio" + "bytes" "context" "fmt" + "io" "os" "path/filepath" "strings" - - "github.com/cozystack/cozystack/internal/manifestutil" + "time" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + k8syaml "k8s.io/apimachinery/pkg/util/yaml" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" ) @@ -73,7 +76,7 @@ func Install(ctx context.Context, k8sClient client.Client, writeEmbeddedManifest // Parse all manifest files var objects []*unstructured.Unstructured for _, manifestPath := range manifestFiles { - objs, err := manifestutil.ParseManifestFile(manifestPath) + objs, err := parseManifests(manifestPath) if err != nil { return fmt.Errorf("failed to parse manifests from %s: %w", manifestPath, err) } @@ -107,6 +110,56 @@ func Install(ctx context.Context, k8sClient client.Client, writeEmbeddedManifest return nil } +// parseManifests parses YAML manifests into unstructured objects. +func parseManifests(manifestPath string) ([]*unstructured.Unstructured, error) { + data, err := os.ReadFile(manifestPath) + if err != nil { + return nil, fmt.Errorf("failed to read manifest file: %w", err) + } + + return readYAMLObjects(bytes.NewReader(data)) +} + +// readYAMLObjects parses multi-document YAML into unstructured objects. +func readYAMLObjects(reader io.Reader) ([]*unstructured.Unstructured, error) { + var objects []*unstructured.Unstructured + yamlReader := k8syaml.NewYAMLReader(bufio.NewReader(reader)) + + for { + doc, err := yamlReader.Read() + if err != nil { + if err == io.EOF { + break + } + return nil, fmt.Errorf("failed to read YAML document: %w", err) + } + + // Skip empty documents + if len(bytes.TrimSpace(doc)) == 0 { + continue + } + + obj := &unstructured.Unstructured{} + decoder := k8syaml.NewYAMLOrJSONDecoder(bytes.NewReader(doc), len(doc)) + if err := decoder.Decode(obj); err != nil { + // Skip documents that can't be decoded (might be comments or empty) + if err == io.EOF { + continue + } + return nil, fmt.Errorf("failed to decode YAML document: %w", err) + } + + // Skip empty objects (no kind) + if obj.GetKind() == "" { + continue + } + + objects = append(objects, obj) + } + + return objects, nil +} + // applyManifests applies Kubernetes objects using server-side apply. func applyManifests(ctx context.Context, k8sClient client.Client, objects []*unstructured.Unstructured) error { logger := log.FromContext(ctx) @@ -130,11 +183,8 @@ func applyManifests(ctx context.Context, k8sClient client.Client, objects []*uns return fmt.Errorf("failed to apply cluster definitions: %w", err) } - // Wait for CRDs to be established before applying dependent resources - crdNames := manifestutil.CollectCRDNames(stageOne) - if err := manifestutil.WaitForCRDsEstablished(ctx, k8sClient, crdNames); err != nil { - return fmt.Errorf("CRDs not established after apply: %w", err) - } + // Wait a bit for CRDs to be registered + time.Sleep(2 * time.Second) } // Apply stage two (everything else) @@ -165,6 +215,7 @@ func applyObjects(ctx context.Context, k8sClient client.Client, objects []*unstr return nil } + // extractNamespace extracts the namespace name from the Namespace object in the manifests. func extractNamespace(objects []*unstructured.Unstructured) (string, error) { for _, obj := range objects { @@ -335,3 +386,4 @@ func setEnvVar(env []interface{}, name, value string) []interface{} { return env } + diff --git a/internal/fluxinstall/manifests.embed.go b/internal/fluxinstall/manifests.embed.go index 6ff48d2d..e6a13a99 100644 --- a/internal/fluxinstall/manifests.embed.go +++ b/internal/fluxinstall/manifests.embed.go @@ -22,7 +22,6 @@ import ( "io/fs" "os" "path" - "path/filepath" ) //go:embed manifests/*.yaml @@ -41,8 +40,8 @@ func WriteEmbeddedManifests(dir string) error { return fmt.Errorf("failed to read file %s: %w", manifest.Name(), err) } - outputPath := filepath.Join(dir, manifest.Name()) - if err := os.WriteFile(outputPath, data, 0600); err != nil { + outputPath := path.Join(dir, manifest.Name()) + if err := os.WriteFile(outputPath, data, 0666); err != nil { return fmt.Errorf("failed to write file %s: %w", outputPath, err) } } diff --git a/internal/lineagecontrollerwebhook/webhook.go b/internal/lineagecontrollerwebhook/webhook.go index cf871fb0..299cbaee 100644 --- a/internal/lineagecontrollerwebhook/webhook.go +++ b/internal/lineagecontrollerwebhook/webhook.go @@ -8,28 +8,22 @@ import ( "strings" "github.com/cozystack/cozystack/pkg/lineage" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - appsv1alpha1 "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1" corev1alpha1 "github.com/cozystack/cozystack/pkg/apis/core/v1alpha1" - schedulerapi "github.com/cozystack/cozystack-scheduler/pkg/apis/v1alpha1" ) var ( - NoAncestors = errors.New("no managed apps found in lineage") - AncestryAmbiguous = errors.New("object ancestry is ambiguous") + NoAncestors = fmt.Errorf("no managed apps found in lineage") + AncestryAmbiguous = fmt.Errorf("object ancestry is ambiguous") ) const ( @@ -101,29 +95,26 @@ func (h *LineageControllerWebhook) Handle(ctx context.Context, req admission.Req return admission.Errored(400, fmt.Errorf("decode object: %w", err)) } - owner, err := h.getOwner(ctx, obj) - switch { - case err != nil && errors.Is(err, AncestryAmbiguous): - warn = append(warn, "object ancestry ambiguous, using first ancestor found") - case err != nil && errors.Is(err, NoAncestors): - // not a problem, mark object as unmanaged - case err != nil: - logger.Error(err, "error computing lineage labels") - return admission.Errored(500, fmt.Errorf("error computing lineage labels: %w", err)) - } - labels, err := h.computeLabels(ctx, obj, owner) - if err != nil { - logger.Error(err, "error computing lineage labels") - return admission.Errored(500, fmt.Errorf("error computing lineage labels: %w", err)) + labels, err := h.computeLabels(ctx, obj) + for { + if err != nil && errors.Is(err, NoAncestors) { + break // not a problem, mark object as unmanaged + } + if err != nil && errors.Is(err, AncestryAmbiguous) { + warn = append(warn, "object ancestry ambiguous, using first ancestor found") + break + } + if err != nil { + logger.Error(err, "error computing lineage labels") + return admission.Errored(500, fmt.Errorf("error computing lineage labels: %w", err)) + } + if err == nil { + break + } } h.applyLabels(obj, labels) - if err := h.applySchedulingClass(ctx, obj, owner, req.Namespace); err != nil { - logger.Error(err, "error applying scheduling class") - return admission.Errored(500, fmt.Errorf("error applying scheduling class: %w", err)) - } - mutated, err := json.Marshal(obj) if err != nil { return admission.Errored(500, fmt.Errorf("marshal mutated pod: %w", err)) @@ -132,29 +123,22 @@ func (h *LineageControllerWebhook) Handle(ctx context.Context, req admission.Req return admission.PatchResponseFromRaw(req.Object.Raw, mutated).WithWarnings(warn...) } -func (h *LineageControllerWebhook) getOwner(ctx context.Context, o *unstructured.Unstructured) (*unstructured.Unstructured, error) { +func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstructured.Unstructured) (map[string]string, error) { owners := lineage.WalkOwnershipGraph(ctx, h.dynClient, h.mapper, h, o) if len(owners) == 0 { - return nil, NoAncestors + return map[string]string{ManagedObjectKey: "false"}, NoAncestors } obj, err := owners[0].GetUnstructured(ctx, h.dynClient, h.mapper) if err != nil { return nil, err } - if len(owners) > 1 { - err = AncestryAmbiguous - } - return obj, err -} - -func (h *LineageControllerWebhook) computeLabels(ctx context.Context, obj *unstructured.Unstructured, owner *unstructured.Unstructured) (map[string]string, error) { - if owner == nil { - return nil, nil - } - gv, err := schema.ParseGroupVersion(owner.GetAPIVersion()) + gv, err := schema.ParseGroupVersion(obj.GetAPIVersion()) if err != nil { // should never happen, we got an APIVersion right from the API - return nil, fmt.Errorf("could not parse APIVersion %s to a group and version: %w", owner.GetAPIVersion(), err) + return nil, fmt.Errorf("could not parse APIVersion %s to a group and version: %w", obj.GetAPIVersion(), err) + } + if len(owners) > 1 { + err = AncestryAmbiguous } labels := map[string]string{ // truncate apigroup to first 63 chars @@ -169,25 +153,25 @@ func (h *LineageControllerWebhook) computeLabels(ctx context.Context, obj *unstr } return s }(gv.Group), - ManagerKindKey: owner.GetKind(), - ManagerNameKey: owner.GetName(), + ManagerKindKey: obj.GetKind(), + ManagerNameKey: obj.GetName(), } templateLabels := map[string]string{ - "kind": strings.ToLower(owner.GetKind()), - "name": owner.GetName(), - "namespace": obj.GetNamespace(), + "kind": strings.ToLower(obj.GetKind()), + "name": obj.GetName(), + "namespace": o.GetNamespace(), } cfg := h.config.Load().(*runtimeConfig) - crd := cfg.appCRDMap[appRef{gv.Group, owner.GetKind()}] - resourceSelectors := h.getResourceSelectors(obj.GroupVersionKind().GroupKind(), crd) + crd := cfg.appCRDMap[appRef{gv.Group, obj.GetKind()}] + resourceSelectors := h.getResourceSelectors(o.GroupVersionKind().GroupKind(), crd) labels[corev1alpha1.TenantResourceLabelKey] = func(b bool) string { if b { return corev1alpha1.TenantResourceLabelValue } return "false" - }(matchResourceToExcludeInclude(ctx, obj.GetName(), templateLabels, obj.GetLabels(), resourceSelectors)) - return labels, nil + }(matchResourceToExcludeInclude(ctx, o.GetName(), templateLabels, o.GetLabels(), resourceSelectors)) + return labels, err } func (h *LineageControllerWebhook) applyLabels(o *unstructured.Unstructured, labels map[string]string) { @@ -201,68 +185,6 @@ func (h *LineageControllerWebhook) applyLabels(o *unstructured.Unstructured, lab o.SetLabels(existing) } -// applySchedulingClass injects schedulerName and scheduling-class annotation -// into Pods whose namespace carries the scheduler.cozystack.io/scheduling-class label. -// If the referenced SchedulingClass CR does not exist (e.g. the scheduler -// package is not installed), the injection is silently skipped so that pods -// are not left Pending. -func (h *LineageControllerWebhook) applySchedulingClass(ctx context.Context, obj, owner *unstructured.Unstructured, namespace string) error { - if obj.GetKind() != "Pod" { - return nil - } - - // Determine scheduling class: owner Application field takes priority, - // then fall back to namespace label. - var schedulingClass string - if owner != nil { - var app appsv1alpha1.Application - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(owner.Object, &app); err == nil { - schedulingClass = app.SchedulingClass() - } - } - if schedulingClass == "" { - ns := &corev1.Namespace{} - if err := h.Get(ctx, client.ObjectKey{Name: namespace}, ns); err != nil { - return fmt.Errorf("getting namespace %s: %w", namespace, err) - } - schedulingClass = ns.Labels[schedulerapi.SchedulingClassLabel] - } - - if schedulingClass == "" { - return nil - } - - // Verify that the referenced SchedulingClass CR exists. - // If the CRD is not installed or the CR is missing, skip injection - // so that pods are not stuck Pending on a non-existent scheduler. - _, err := h.dynClient.Resource(schedulingClassGVR).Get(ctx, schedulingClass, metav1.GetOptions{}) - if err != nil { - logger := log.FromContext(ctx) - logger.Info("SchedulingClass not found, skipping scheduler injection", - "schedulingClass", schedulingClass, "namespace", namespace) - return nil - } - - if err := unstructured.SetNestedField(obj.Object, schedulerapi.SchedulerName, "spec", "schedulerName"); err != nil { - return fmt.Errorf("setting schedulerName: %w", err) - } - - annotations := obj.GetAnnotations() - if annotations == nil { - annotations = make(map[string]string) - } - annotations[schedulerapi.SchedulingClassAnnotation] = schedulingClass - obj.SetAnnotations(annotations) - - return nil -} - -var schedulingClassGVR = schema.GroupVersionResource{ - Group: schedulerapi.Group, - Version: schedulerapi.Version, - Resource: schedulerapi.Resource, -} - func (h *LineageControllerWebhook) decodeUnstructured(req admission.Request, out *unstructured.Unstructured) error { if h.decoder != nil { if err := h.decoder.Decode(req, out); err == nil { diff --git a/internal/manifestutil/crd.go b/internal/manifestutil/crd.go deleted file mode 100644 index 08468d1b..00000000 --- a/internal/manifestutil/crd.go +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package manifestutil - -import ( - "context" - "fmt" - "time" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -var crdGVK = schema.GroupVersionKind{ - Group: "apiextensions.k8s.io", - Version: "v1", - Kind: "CustomResourceDefinition", -} - -// WaitForCRDsEstablished polls the API server until all named CRDs have the -// Established condition set to True, or the context is cancelled. -func WaitForCRDsEstablished(ctx context.Context, k8sClient client.Client, crdNames []string) error { - if len(crdNames) == 0 { - return nil - } - - logger := log.FromContext(ctx) - ticker := time.NewTicker(500 * time.Millisecond) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return fmt.Errorf("context cancelled while waiting for CRDs to be established: %w", ctx.Err()) - default: - } - - allEstablished := true - var pendingCRD string - for _, name := range crdNames { - crd := &unstructured.Unstructured{} - crd.SetGroupVersionKind(crdGVK) - if err := k8sClient.Get(ctx, types.NamespacedName{Name: name}, crd); err != nil { - allEstablished = false - pendingCRD = name - break - } - - conditions, found, err := unstructured.NestedSlice(crd.Object, "status", "conditions") - if err != nil || !found { - allEstablished = false - pendingCRD = name - break - } - - established := false - for _, c := range conditions { - cond, ok := c.(map[string]interface{}) - if !ok { - continue - } - if cond["type"] == "Established" && cond["status"] == "True" { - established = true - break - } - } - if !established { - allEstablished = false - pendingCRD = name - break - } - } - - if allEstablished { - logger.Info("All CRDs established", "count", len(crdNames)) - return nil - } - - logger.V(1).Info("Waiting for CRD to be established", "crd", pendingCRD) - - select { - case <-ctx.Done(): - return fmt.Errorf("context cancelled while waiting for CRD %q to be established: %w", pendingCRD, ctx.Err()) - case <-ticker.C: - } - } -} - -// CollectCRDNames returns the names of all CustomResourceDefinition objects -// from the given list of unstructured objects. Only objects with -// apiVersion "apiextensions.k8s.io/v1" and kind "CustomResourceDefinition" -// are matched. -func CollectCRDNames(objects []*unstructured.Unstructured) []string { - var names []string - for _, obj := range objects { - if obj.GetAPIVersion() == "apiextensions.k8s.io/v1" && obj.GetKind() == "CustomResourceDefinition" { - names = append(names, obj.GetName()) - } - } - return names -} diff --git a/internal/manifestutil/crd_test.go b/internal/manifestutil/crd_test.go deleted file mode 100644 index 5d046353..00000000 --- a/internal/manifestutil/crd_test.go +++ /dev/null @@ -1,202 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package manifestutil - -import ( - "context" - "strings" - "testing" - "time" - - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - "sigs.k8s.io/controller-runtime/pkg/client/interceptor" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" -) - -func TestCollectCRDNames(t *testing.T) { - objects := []*unstructured.Unstructured{ - {Object: map[string]interface{}{ - "apiVersion": "v1", - "kind": "Namespace", - "metadata": map[string]interface{}{"name": "test-ns"}, - }}, - {Object: map[string]interface{}{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "CustomResourceDefinition", - "metadata": map[string]interface{}{"name": "packages.cozystack.io"}, - }}, - {Object: map[string]interface{}{ - "apiVersion": "apps/v1", - "kind": "Deployment", - "metadata": map[string]interface{}{"name": "test-deploy"}, - }}, - {Object: map[string]interface{}{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "CustomResourceDefinition", - "metadata": map[string]interface{}{"name": "packagesources.cozystack.io"}, - }}, - } - - names := CollectCRDNames(objects) - if len(names) != 2 { - t.Fatalf("CollectCRDNames() returned %d names, want 2", len(names)) - } - if names[0] != "packages.cozystack.io" { - t.Errorf("names[0] = %q, want %q", names[0], "packages.cozystack.io") - } - if names[1] != "packagesources.cozystack.io" { - t.Errorf("names[1] = %q, want %q", names[1], "packagesources.cozystack.io") - } -} - -func TestCollectCRDNames_ignoresWrongAPIVersion(t *testing.T) { - objects := []*unstructured.Unstructured{ - {Object: map[string]interface{}{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "CustomResourceDefinition", - "metadata": map[string]interface{}{"name": "real.crd.io"}, - }}, - {Object: map[string]interface{}{ - "apiVersion": "apiextensions.k8s.io/v1beta1", - "kind": "CustomResourceDefinition", - "metadata": map[string]interface{}{"name": "legacy.crd.io"}, - }}, - } - - names := CollectCRDNames(objects) - if len(names) != 1 { - t.Fatalf("CollectCRDNames() returned %d names, want 1", len(names)) - } - if names[0] != "real.crd.io" { - t.Errorf("names[0] = %q, want %q", names[0], "real.crd.io") - } -} - -func TestCollectCRDNames_noCRDs(t *testing.T) { - objects := []*unstructured.Unstructured{ - {Object: map[string]interface{}{ - "apiVersion": "v1", - "kind": "Namespace", - "metadata": map[string]interface{}{"name": "test"}, - }}, - } - - names := CollectCRDNames(objects) - if len(names) != 0 { - t.Errorf("CollectCRDNames() returned %d names, want 0", len(names)) - } -} - -func TestWaitForCRDsEstablished_success(t *testing.T) { - log.SetLogger(zap.New(zap.UseDevMode(true))) - - scheme := runtime.NewScheme() - if err := apiextensionsv1.AddToScheme(scheme); err != nil { - t.Fatalf("failed to add apiextensions to scheme: %v", err) - } - - // Create a CRD object in the fake client - crd := &unstructured.Unstructured{Object: map[string]interface{}{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "CustomResourceDefinition", - "metadata": map[string]interface{}{"name": "packages.cozystack.io"}, - }} - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(crd). - WithInterceptorFuncs(interceptor.Funcs{ - Get: func(ctx context.Context, c client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { - if err := c.Get(ctx, key, obj, opts...); err != nil { - return err - } - u, ok := obj.(*unstructured.Unstructured) - if !ok { - return nil - } - if u.GetKind() == "CustomResourceDefinition" { - _ = unstructured.SetNestedSlice(u.Object, []interface{}{ - map[string]interface{}{ - "type": "Established", - "status": "True", - }, - }, "status", "conditions") - } - return nil - }, - }). - Build() - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - ctx = log.IntoContext(ctx, log.FromContext(context.Background())) - - err := WaitForCRDsEstablished(ctx, fakeClient, []string{"packages.cozystack.io"}) - if err != nil { - t.Fatalf("WaitForCRDsEstablished() error = %v", err) - } -} - -func TestWaitForCRDsEstablished_timeout(t *testing.T) { - log.SetLogger(zap.New(zap.UseDevMode(true))) - - scheme := runtime.NewScheme() - if err := apiextensionsv1.AddToScheme(scheme); err != nil { - t.Fatalf("failed to add apiextensions to scheme: %v", err) - } - - // CRD exists but never gets Established condition - crd := &unstructured.Unstructured{Object: map[string]interface{}{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "CustomResourceDefinition", - "metadata": map[string]interface{}{"name": "packages.cozystack.io"}, - }} - - fakeClient := fake.NewClientBuilder(). - WithScheme(scheme). - WithObjects(crd). - Build() - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - ctx = log.IntoContext(ctx, log.FromContext(context.Background())) - - err := WaitForCRDsEstablished(ctx, fakeClient, []string{"packages.cozystack.io"}) - if err == nil { - t.Fatal("WaitForCRDsEstablished() expected error on timeout, got nil") - } - if !strings.Contains(err.Error(), "packages.cozystack.io") { - t.Errorf("error should mention stuck CRD name, got: %v", err) - } -} - -func TestWaitForCRDsEstablished_empty(t *testing.T) { - scheme := runtime.NewScheme() - fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build() - - ctx := context.Background() - err := WaitForCRDsEstablished(ctx, fakeClient, nil) - if err != nil { - t.Fatalf("WaitForCRDsEstablished() with empty names should return nil, got: %v", err) - } -} - diff --git a/internal/manifestutil/parse.go b/internal/manifestutil/parse.go deleted file mode 100644 index 009e4a96..00000000 --- a/internal/manifestutil/parse.go +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package manifestutil - -import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - k8syaml "k8s.io/apimachinery/pkg/util/yaml" -) - -// ParseManifestFile reads a YAML file and parses it into unstructured objects. -func ParseManifestFile(manifestPath string) ([]*unstructured.Unstructured, error) { - data, err := os.ReadFile(manifestPath) - if err != nil { - return nil, fmt.Errorf("failed to read manifest file: %w", err) - } - - return ReadYAMLObjects(bytes.NewReader(data)) -} - -// ReadYAMLObjects parses multi-document YAML from a reader into unstructured objects. -// Empty documents and documents without a kind are skipped. -func ReadYAMLObjects(reader io.Reader) ([]*unstructured.Unstructured, error) { - var objects []*unstructured.Unstructured - yamlReader := k8syaml.NewYAMLReader(bufio.NewReader(reader)) - - for { - doc, err := yamlReader.Read() - if err != nil { - if err == io.EOF { - break - } - return nil, fmt.Errorf("failed to read YAML document: %w", err) - } - - if len(bytes.TrimSpace(doc)) == 0 { - continue - } - - obj := &unstructured.Unstructured{} - decoder := k8syaml.NewYAMLOrJSONDecoder(bytes.NewReader(doc), len(doc)) - if err := decoder.Decode(obj); err != nil { - if err == io.EOF { - continue - } - return nil, fmt.Errorf("failed to decode YAML document: %w", err) - } - - if obj.GetKind() == "" { - continue - } - - objects = append(objects, obj) - } - - return objects, nil -} diff --git a/internal/manifestutil/parse_test.go b/internal/manifestutil/parse_test.go deleted file mode 100644 index 860405c7..00000000 --- a/internal/manifestutil/parse_test.go +++ /dev/null @@ -1,161 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package manifestutil - -import ( - "os" - "path/filepath" - "strings" - "testing" -) - -func TestReadYAMLObjects(t *testing.T) { - tests := []struct { - name string - input string - wantCount int - wantErr bool - }{ - { - name: "single document", - input: `apiVersion: v1 -kind: ConfigMap -metadata: - name: test -`, - wantCount: 1, - }, - { - name: "multiple documents", - input: `apiVersion: v1 -kind: ConfigMap -metadata: - name: test1 ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: test2 -`, - wantCount: 2, - }, - { - name: "empty input", - input: "", - wantCount: 0, - }, - { - name: "decoder rejects document without kind", - input: `apiVersion: v1 -metadata: - name: test -`, - wantErr: true, - }, - { - name: "whitespace-only document between separators is skipped", - input: `apiVersion: v1 -kind: ConfigMap -metadata: - name: test1 ---- - ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: test2 -`, - wantCount: 2, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - objects, err := ReadYAMLObjects(strings.NewReader(tt.input)) - if (err != nil) != tt.wantErr { - t.Errorf("ReadYAMLObjects() error = %v, wantErr %v", err, tt.wantErr) - return - } - if len(objects) != tt.wantCount { - t.Errorf("ReadYAMLObjects() returned %d objects, want %d", len(objects), tt.wantCount) - } - }) - } -} - -func TestReadYAMLObjects_preservesFields(t *testing.T) { - input := `apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: packages.cozystack.io -spec: - group: cozystack.io -` - objects, err := ReadYAMLObjects(strings.NewReader(input)) - if err != nil { - t.Fatalf("ReadYAMLObjects() error = %v", err) - } - if len(objects) != 1 { - t.Fatalf("expected 1 object, got %d", len(objects)) - } - - obj := objects[0] - if obj.GetKind() != "CustomResourceDefinition" { - t.Errorf("kind = %q, want %q", obj.GetKind(), "CustomResourceDefinition") - } - if obj.GetName() != "packages.cozystack.io" { - t.Errorf("name = %q, want %q", obj.GetName(), "packages.cozystack.io") - } - if obj.GetAPIVersion() != "apiextensions.k8s.io/v1" { - t.Errorf("apiVersion = %q, want %q", obj.GetAPIVersion(), "apiextensions.k8s.io/v1") - } -} - -func TestParseManifestFile(t *testing.T) { - tmpDir := t.TempDir() - manifestPath := filepath.Join(tmpDir, "test.yaml") - - content := `apiVersion: v1 -kind: ConfigMap -metadata: - name: cm1 ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: cm2 -` - if err := os.WriteFile(manifestPath, []byte(content), 0600); err != nil { - t.Fatalf("failed to write test manifest: %v", err) - } - - objects, err := ParseManifestFile(manifestPath) - if err != nil { - t.Fatalf("ParseManifestFile() error = %v", err) - } - if len(objects) != 2 { - t.Errorf("ParseManifestFile() returned %d objects, want 2", len(objects)) - } -} - -func TestParseManifestFile_notFound(t *testing.T) { - _, err := ParseManifestFile("/nonexistent/path/test.yaml") - if err == nil { - t.Error("ParseManifestFile() expected error for nonexistent file, got nil") - } -} diff --git a/internal/operator/package_reconciler.go b/internal/operator/package_reconciler.go index 0e724e49..79d78a87 100644 --- a/internal/operator/package_reconciler.go +++ b/internal/operator/package_reconciler.go @@ -45,16 +45,6 @@ const ( SecretCozystackValues = "cozystack-values" ) -// parseCRDPolicy maps ComponentInstall.UpgradeCRDs to a helmv2.CRDsPolicy. -// Empty / nil preserves the helm-controller default (Skip on upgrade); -// the CRD enum marker restricts the string to Skip/Create/CreateReplace. -func parseCRDPolicy(install *cozyv1alpha1.ComponentInstall) helmv2.CRDsPolicy { - if install == nil || install.UpgradeCRDs == "" { - return "" - } - return helmv2.CRDsPolicy(install.UpgradeCRDs) -} - // PackageReconciler reconciles Package resources type PackageReconciler struct { client.Client @@ -221,17 +211,16 @@ func (r *PackageReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct Namespace: "cozy-system", }, Install: &helmv2.Install{ - Timeout: &metav1.Duration{Duration: 10 * 60 * 1000000000}, // 10m + Timeout: &metav1.Duration{Duration: 10 * 60 * 1000000000}, // 10m Remediation: &helmv2.InstallRemediation{ Retries: -1, }, }, Upgrade: &helmv2.Upgrade{ - Timeout: &metav1.Duration{Duration: 10 * 60 * 1000000000}, // 10m + Timeout: &metav1.Duration{Duration: 10 * 60 * 1000000000}, // 10m Remediation: &helmv2.UpgradeRemediation{ Retries: -1, }, - CRDs: parseCRDPolicy(component.Install), }, }, } @@ -398,7 +387,6 @@ func (r *PackageReconciler) createOrUpdateHelmRelease(ctx context.Context, hr *h } hr.SetAnnotations(annotations) - hr.Spec.Suspend = existing.Spec.Suspend // Update Spec existing.Spec = hr.Spec existing.SetLabels(hr.GetLabels()) @@ -747,39 +735,53 @@ func (r *PackageReconciler) updateDependentPackagesDependencies(ctx context.Cont return nil } -// reconcileNamespaces creates or updates namespaces based on components in the variant. -// For each namespace, it checks ALL Packages sharing that namespace to determine whether -// the namespace should be privileged — it is privileged if ANY Package has a privileged -// component installed in it. +// reconcileNamespaces creates or updates namespaces based on components in the variant func (r *PackageReconciler) reconcileNamespaces(ctx context.Context, pkg *cozyv1alpha1.Package, variant *cozyv1alpha1.Variant) error { logger := log.FromContext(ctx) - // Collect namespaces from this Package's components - targetNamespaces := make(map[string]struct{}) + // Collect namespaces from components + // Map: namespace -> {isPrivileged} + type namespaceInfo struct { + privileged bool + } + namespacesMap := make(map[string]namespaceInfo) + for _, component := range variant.Components { + // Skip components without Install section if component.Install == nil { continue } + + // Check if component is disabled via Package spec if pkgComponent, ok := pkg.Spec.Components[component.Name]; ok { if pkgComponent.Enabled != nil && !*pkgComponent.Enabled { continue } } + + // Namespace must be set namespace := component.Install.Namespace if namespace == "" { return fmt.Errorf("component %s has empty namespace in Install section", component.Name) } - targetNamespaces[namespace] = struct{}{} - } - // Determine which namespaces should be privileged by checking ALL Packages - privileged, err := r.resolvePrivilegedNamespaces(ctx, targetNamespaces) - if err != nil { - return fmt.Errorf("failed to resolve privileged namespaces: %w", err) + info, exists := namespacesMap[namespace] + if !exists { + info = namespaceInfo{ + privileged: false, + } + } + + // If component is privileged, mark namespace as privileged + if component.Install.Privileged { + info.privileged = true + } + + namespacesMap[namespace] = info } // Create or update all namespaces - for nsName := range targetNamespaces { + for nsName, info := range namespacesMap { namespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: nsName, @@ -790,89 +792,36 @@ func (r *PackageReconciler) reconcileNamespaces(ctx context.Context, pkg *cozyv1 }, } + // Add system label only for non-tenant namespaces if !strings.HasPrefix(nsName, "tenant-") { namespace.Labels["cozystack.io/system"] = "true" } - if privileged[nsName] { + // Add privileged label if needed + if info.privileged { namespace.Labels["pod-security.kubernetes.io/enforce"] = "privileged" } if err := r.createOrUpdateNamespace(ctx, namespace); err != nil { - logger.Error(err, "failed to reconcile namespace", "name", nsName, "privileged", privileged[nsName]) + logger.Error(err, "failed to reconcile namespace", "name", nsName, "privileged", info.privileged) return fmt.Errorf("failed to reconcile namespace %s: %w", nsName, err) } - logger.Info("reconciled namespace", "name", nsName, "privileged", privileged[nsName]) + logger.Info("reconciled namespace", "name", nsName, "privileged", info.privileged) } return nil } -// resolvePrivilegedNamespaces checks all PackageSources and their corresponding Packages -// to determine which of the given namespaces require the privileged PodSecurity level. -// A namespace is privileged if ANY active Package has a component with privileged: true in it. -func (r *PackageReconciler) resolvePrivilegedNamespaces(ctx context.Context, namespaces map[string]struct{}) (map[string]bool, error) { - result := make(map[string]bool) - - packageSources := &cozyv1alpha1.PackageSourceList{} - if err := r.List(ctx, packageSources); err != nil { - return nil, fmt.Errorf("failed to list PackageSources: %w", err) - } - - for i := range packageSources.Items { - ps := &packageSources.Items[i] - - // Check if a Package exists for this PackageSource - pkg := &cozyv1alpha1.Package{} - if err := r.Get(ctx, types.NamespacedName{Name: ps.Name}, pkg); err != nil { - if apierrors.IsNotFound(err) { - continue - } - return nil, fmt.Errorf("failed to get Package %s: %w", ps.Name, err) - } - - // Resolve active variant - variantName := pkg.Spec.Variant - if variantName == "" { - variantName = "default" - } - - var variant *cozyv1alpha1.Variant - for j := range ps.Spec.Variants { - if ps.Spec.Variants[j].Name == variantName { - variant = &ps.Spec.Variants[j] - break - } - } - if variant == nil { - continue - } - - for _, component := range variant.Components { - if component.Install == nil { - continue - } - if pkgComponent, ok := pkg.Spec.Components[component.Name]; ok { - if pkgComponent.Enabled != nil && !*pkgComponent.Enabled { - continue - } - } - if _, relevant := namespaces[component.Install.Namespace]; !relevant { - continue - } - if component.Install.Privileged { - result[component.Install.Namespace] = true - } - } - } - - return result, nil -} - -// createOrUpdateNamespace creates or updates a namespace using server-side apply. +// createOrUpdateNamespace creates or updates a namespace using server-side apply func (r *PackageReconciler) createOrUpdateNamespace(ctx context.Context, namespace *corev1.Namespace) error { + // Ensure TypeMeta is set for server-side apply namespace.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Namespace")) - return r.Patch(ctx, namespace, client.Apply, client.FieldOwner("cozystack-package-controller"), client.ForceOwnership) + + // Use server-side apply with field manager + // This is atomic and avoids race conditions from Get/Create/Update pattern + // Labels and annotations will be merged automatically by the server + // Each label/annotation key is treated as a separate field, so existing ones are preserved + return r.Patch(ctx, namespace, client.Apply, client.FieldOwner("cozystack-package-controller")) } // cleanupOrphanedHelmReleases removes HelmReleases that are no longer needed diff --git a/internal/operator/package_reconciler_test.go b/internal/operator/package_reconciler_test.go deleted file mode 100644 index f0ee2c19..00000000 --- a/internal/operator/package_reconciler_test.go +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright 2025 The Cozystack Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package operator - -import ( - "encoding/json" - "os" - "path/filepath" - "testing" - - cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1" - helmv2 "github.com/fluxcd/helm-controller/api/v2" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "sigs.k8s.io/yaml" -) - -func TestParseCRDPolicy(t *testing.T) { - tests := []struct { - name string - install *cozyv1alpha1.ComponentInstall - want helmv2.CRDsPolicy - }{ - { - name: "nil install leaves flux default", - install: nil, - want: "", - }, - { - name: "empty upgradeCRDs leaves flux default", - install: &cozyv1alpha1.ComponentInstall{}, - want: "", - }, - { - name: "Skip is passed through", - install: &cozyv1alpha1.ComponentInstall{UpgradeCRDs: "Skip"}, - want: helmv2.Skip, - }, - { - name: "Create is passed through", - install: &cozyv1alpha1.ComponentInstall{UpgradeCRDs: "Create"}, - want: helmv2.Create, - }, - { - name: "CreateReplace is passed through", - install: &cozyv1alpha1.ComponentInstall{UpgradeCRDs: "CreateReplace"}, - want: helmv2.CreateReplace, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - got := parseCRDPolicy(tc.install) - if got != tc.want { - t.Errorf("parseCRDPolicy() = %q, want %q", got, tc.want) - } - }) - } -} - -// TestPackageSourceCRDHasUpgradeCRDsEnum guards the generated CRD schema: the -// invalid-value case from the spec is enforced at the API server via a -// kubebuilder enum marker, not in the reconciler. If someone drops the marker -// and forgets to regenerate, this test catches it. -func TestPackageSourceCRDHasUpgradeCRDsEnum(t *testing.T) { - path := filepath.Join("..", "crdinstall", "manifests", "cozystack.io_packagesources.yaml") - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read %s: %v", path, err) - } - - var crd apiextensionsv1.CustomResourceDefinition - if err := yaml.Unmarshal(data, &crd); err != nil { - t.Fatalf("unmarshal CRD: %v", err) - } - - var field *apiextensionsv1.JSONSchemaProps - for i := range crd.Spec.Versions { - v := &crd.Spec.Versions[i] - if v.Schema == nil || v.Schema.OpenAPIV3Schema == nil { - continue - } - spec, ok := v.Schema.OpenAPIV3Schema.Properties["spec"] - if !ok { - continue - } - variants, ok := spec.Properties["variants"] - if !ok || variants.Items == nil || variants.Items.Schema == nil { - continue - } - components, ok := variants.Items.Schema.Properties["components"] - if !ok || components.Items == nil || components.Items.Schema == nil { - continue - } - install, ok := components.Items.Schema.Properties["install"] - if !ok { - continue - } - f, ok := install.Properties["upgradeCRDs"] - if !ok { - continue - } - field = &f - break - } - - if field == nil { - t.Fatal("upgradeCRDs field not found in PackageSource CRD schema") - } - - got := map[string]bool{} - for _, e := range field.Enum { - var s string - if err := json.Unmarshal(e.Raw, &s); err != nil { - t.Fatalf("unmarshal enum value %q: %v", e.Raw, err) - } - got[s] = true - } - - for _, want := range []string{"Skip", "Create", "CreateReplace"} { - if !got[want] { - t.Errorf("enum value %q missing from upgradeCRDs; got %v", want, got) - } - } -} diff --git a/packages/apps/bucket/Makefile b/packages/apps/bucket/Makefile index 1e35bd53..27cd199b 100644 --- a/packages/apps/bucket/Makefile +++ b/packages/apps/bucket/Makefile @@ -1,5 +1,6 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'bucket' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/bucket/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md + yq -o json -i '.properties = {}' values.schema.json ../../../hack/update-crd.sh diff --git a/packages/apps/bucket/README.md b/packages/apps/bucket/README.md index 982225ce..89749b1d 100644 --- a/packages/apps/bucket/README.md +++ b/packages/apps/bucket/README.md @@ -1,13 +1,3 @@ # S3 bucket ## Parameters - -### Parameters - -| Name | Description | Type | Value | -| ---------------------- | -------------------------------------------------------------------------- | ------------------- | ------- | -| `locking` | Provisions bucket from the `-lock` BucketClass (with object lock enabled). | `bool` | `false` | -| `storagePool` | Selects a specific BucketClass by storage pool name. | `string` | `""` | -| `users` | Users configuration map. | `map[string]object` | `{}` | -| `users[name].readonly` | Whether the user has read-only access. | `bool` | `false` | - diff --git a/packages/apps/bucket/templates/bucketclaim.yaml b/packages/apps/bucket/templates/bucketclaim.yaml index 0639916f..5cfdc1c1 100644 --- a/packages/apps/bucket/templates/bucketclaim.yaml +++ b/packages/apps/bucket/templates/bucketclaim.yaml @@ -1,24 +1,19 @@ {{- $seaweedfs := .Values._namespace.seaweedfs }} -{{- $pool := .Values.storagePool }} apiVersion: objectstorage.k8s.io/v1alpha1 kind: BucketClaim metadata: name: {{ .Release.Name }} - labels: - app.kubernetes.io/instance: {{ .Release.Name }} spec: - bucketClassName: {{ $seaweedfs }}{{- if $pool }}-{{ $pool }}{{- end }}{{- if .Values.locking }}-lock{{- end }} + bucketClassName: {{ $seaweedfs }} protocols: - s3 -{{- range $name, $user := .Values.users }} --- apiVersion: objectstorage.k8s.io/v1alpha1 kind: BucketAccess metadata: - name: {{ $.Release.Name }}-{{ $name }} + name: {{ .Release.Name }} spec: - bucketAccessClassName: {{ $seaweedfs }}{{- if $pool }}-{{ $pool }}{{- end }}{{- if $user.readonly }}-readonly{{- end }} - bucketClaimName: {{ $.Release.Name }} - credentialsSecretName: {{ $.Release.Name }}-{{ $name }} + bucketAccessClassName: {{ $seaweedfs }} + bucketClaimName: {{ .Release.Name }} + credentialsSecretName: {{ .Release.Name }} protocol: s3 -{{- end }} diff --git a/packages/apps/bucket/templates/dashboard-resourcemap.yaml b/packages/apps/bucket/templates/dashboard-resourcemap.yaml index 82a51e16..5edc8b7a 100644 --- a/packages/apps/bucket/templates/dashboard-resourcemap.yaml +++ b/packages/apps/bucket/templates/dashboard-resourcemap.yaml @@ -8,9 +8,8 @@ rules: resources: - secrets resourceNames: - {{- range $name, $user := .Values.users }} - - {{ $.Release.Name }}-{{ $name }}-credentials - {{- end }} + - {{ .Release.Name }} + - {{ .Release.Name }}-credentials verbs: ["get", "list", "watch"] - apiGroups: - networking.k8s.io diff --git a/packages/apps/bucket/templates/helmrelease.yaml b/packages/apps/bucket/templates/helmrelease.yaml index d3290512..704470a8 100644 --- a/packages/apps/bucket/templates/helmrelease.yaml +++ b/packages/apps/bucket/templates/helmrelease.yaml @@ -23,4 +23,3 @@ spec: name: cozystack-values values: bucketName: {{ .Release.Name }} - users: {{ .Values.users | toJson }} diff --git a/packages/apps/bucket/values.schema.json b/packages/apps/bucket/values.schema.json index d302842c..167bc53e 100644 --- a/packages/apps/bucket/values.schema.json +++ b/packages/apps/bucket/values.schema.json @@ -1,30 +1,5 @@ { "title": "Chart Values", "type": "object", - "properties": { - "locking": { - "description": "Provisions bucket from the `-lock` BucketClass (with object lock enabled).", - "type": "boolean", - "default": false - }, - "storagePool": { - "description": "Selects a specific BucketClass by storage pool name.", - "type": "string", - "default": "" - }, - "users": { - "description": "Users configuration map.", - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "properties": { - "readonly": { - "description": "Whether the user has read-only access.", - "type": "boolean" - } - } - } - } - } + "properties": {} } diff --git a/packages/apps/bucket/values.yaml b/packages/apps/bucket/values.yaml index df284df7..0967ef42 100644 --- a/packages/apps/bucket/values.yaml +++ b/packages/apps/bucket/values.yaml @@ -1,11 +1 @@ -## @param {bool} locking=false - Provisions bucket from the `-lock` BucketClass (with object lock enabled). -locking: false - -## @param {string} [storagePool] - Selects a specific BucketClass by storage pool name. -storagePool: "" - -## @typedef {struct} User - Bucket user configuration. -## @field {bool} [readonly] - Whether the user has read-only access. - -## @param {map[string]User} users - Users configuration map. -users: {} +{} diff --git a/packages/apps/clickhouse/Makefile b/packages/apps/clickhouse/Makefile index 2d671d1d..2c77add9 100644 --- a/packages/apps/clickhouse/Makefile +++ b/packages/apps/clickhouse/Makefile @@ -4,7 +4,7 @@ include ../../../hack/common-envs.mk include ../../../hack/package.mk generate: - cozyvalues-gen -m 'clickhouse' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/clickhouse/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh image: diff --git a/packages/apps/clickhouse/templates/workloadmonitor.yaml b/packages/apps/clickhouse/templates/workloadmonitor.yaml index 62c951c2..9020ad41 100644 --- a/packages/apps/clickhouse/templates/workloadmonitor.yaml +++ b/packages/apps/clickhouse/templates/workloadmonitor.yaml @@ -3,8 +3,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 @@ -19,8 +17,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }}-keeper - labels: - workloads.cozystack.io/resource-preset: {{ .Values.clickhouseKeeper.resourcesPreset | quote }} spec: replicas: {{ .Values.clickhouseKeeper.replicas }} minReplicas: 1 diff --git a/packages/apps/clickhouse/values.schema.json b/packages/apps/clickhouse/values.schema.json index e4e1df7d..abb3aeb1 100644 --- a/packages/apps/clickhouse/values.schema.json +++ b/packages/apps/clickhouse/values.schema.json @@ -2,119 +2,6 @@ "title": "Chart Values", "type": "object", "properties": { - "replicas": { - "description": "Number of ClickHouse replicas.", - "type": "integer", - "default": 2 - }, - "shards": { - "description": "Number of ClickHouse shards.", - "type": "integer", - "default": 1 - }, - "resources": { - "description": "Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "small", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, - "size": { - "description": "Persistent Volume Claim size available for application data.", - "default": "10Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, - "logStorageSize": { - "description": "Size of Persistent Volume for logs.", - "default": "2Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "logTTL": { - "description": "TTL (expiration time) for `query_log` and `query_thread_log`.", - "type": "integer", - "default": 15 - }, - "users": { - "description": "Users configuration map.", - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "properties": { - "password": { - "description": "Password for the user.", - "type": "string" - }, - "readonly": { - "description": "User is readonly (default: false).", - "type": "boolean" - } - } - } - }, "backup": { "description": "Backup configuration.", "type": "object", @@ -216,6 +103,119 @@ "x-kubernetes-int-or-string": true } } + }, + "logStorageSize": { + "description": "Size of Persistent Volume for logs.", + "default": "2Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "logTTL": { + "description": "TTL (expiration time) for `query_log` and `query_thread_log`.", + "type": "integer", + "default": 15 + }, + "replicas": { + "description": "Number of ClickHouse replicas.", + "type": "integer", + "default": 2 + }, + "resources": { + "description": "Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory (RAM) available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "resourcesPreset": { + "description": "Default sizing preset used when `resources` is omitted.", + "type": "string", + "default": "small", + "enum": [ + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "shards": { + "description": "Number of ClickHouse shards.", + "type": "integer", + "default": 1 + }, + "size": { + "description": "Persistent Volume Claim size available for application data.", + "default": "10Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "" + }, + "users": { + "description": "Users configuration map.", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "password": { + "description": "Password for the user.", + "type": "string" + }, + "readonly": { + "description": "User is readonly (default: false).", + "type": "boolean" + } + } + } } } -} +} \ No newline at end of file diff --git a/packages/apps/openbao/.helmignore b/packages/apps/ferretdb/.helmignore similarity index 100% rename from packages/apps/openbao/.helmignore rename to packages/apps/ferretdb/.helmignore diff --git a/packages/system/vm-default-images/Chart.yaml b/packages/apps/ferretdb/Chart.yaml similarity index 57% rename from packages/system/vm-default-images/Chart.yaml rename to packages/apps/ferretdb/Chart.yaml index aac0ccca..3044103a 100644 --- a/packages/system/vm-default-images/Chart.yaml +++ b/packages/apps/ferretdb/Chart.yaml @@ -1,5 +1,7 @@ apiVersion: v2 -name: vm-default-images -description: Global Golden Image collection for virtual machines +name: ferretdb +description: Managed FerretDB service +icon: /logos/ferretdb.svg type: application version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process +appVersion: 2.4.0 diff --git a/packages/apps/ferretdb/Makefile b/packages/apps/ferretdb/Makefile new file mode 100644 index 00000000..40b7423f --- /dev/null +++ b/packages/apps/ferretdb/Makefile @@ -0,0 +1,12 @@ +include ../../../hack/package.mk + +generate: + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md + ../../../hack/update-crd.sh + +update: + tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/FerretDB/FerretDB | awk -F'[/^]' '{sub("^v", "", $$3)} END{print $$3}') && \ + pgtag=$$(skopeo list-tags docker://ghcr.io/ferretdb/postgres-documentdb | jq -r --arg tag "$$tag" '.Tags[] | select(endswith("ferretdb-" + $$tag))' | sort -V | tail -n1) && \ + sed -i "s|\(imageName: ghcr.io/ferretdb/postgres-documentdb:\).*|\1$$pgtag|" templates/postgres.yaml && \ + sed -i "s|\(image: ghcr.io/ferretdb/ferretdb:\).*|\1$$tag|" templates/ferretdb.yaml && \ + sed -i "s|\(appVersion: \).*|\1$$tag|" Chart.yaml diff --git a/packages/apps/ferretdb/README.md b/packages/apps/ferretdb/README.md new file mode 100644 index 00000000..91fc078e --- /dev/null +++ b/packages/apps/ferretdb/README.md @@ -0,0 +1,82 @@ +# Managed FerretDB Service + +FerretDB is an open source MongoDB alternative. +It translates MongoDB wire protocol queries to SQL and can be used as a direct replacement for MongoDB 5.0+. +Internally, FerretDB service is backed by Postgres. + +## Parameters + +### Common parameters + +| Name | Description | Type | Value | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- | +| `replicas` | Number of replicas. | `int` | `2` | +| `resources` | Explicit CPU and memory configuration for each FerretDB replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | +| `resources.cpu` | CPU available to each replica. | `quantity` | `""` | +| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` | +| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `micro` | +| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` | +| `storageClass` | StorageClass used to store the data. | `string` | `""` | +| `external` | Enable external access from outside the cluster. | `bool` | `false` | + + +### Application-specific parameters + +| Name | Description | Type | Value | +| ------------------------ | ---------------------------------------------------------------------------------- | ------------------- | ----- | +| `quorum` | Configuration for quorum-based synchronous replication. | `object` | `{}` | +| `quorum.minSyncReplicas` | Minimum number of synchronous replicas required for commit. | `int` | `0` | +| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas allowed (must be less than total replicas). | `int` | `0` | +| `users` | Users configuration map. | `map[string]object` | `{}` | +| `users[name].password` | Password for the user. | `string` | `""` | + + +### Backup parameters + +| Name | Description | Type | Value | +| ------------------------ | ------------------------------------------------------------ | -------- | ----------------------------------- | +| `backup` | Backup configuration. | `object` | `{}` | +| `backup.enabled` | Enable regular backups (default: false). | `bool` | `false` | +| `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * * *` | +| `backup.retentionPolicy` | Retention policy. | `string` | `30d` | +| `backup.endpointURL` | S3 endpoint URL for uploads. | `string` | `http://minio-gateway-service:9000` | +| `backup.destinationPath` | Path to store the backup (e.g. s3://bucket/path/to/folder/). | `string` | `s3://bucket/path/to/folder/` | +| `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `` | +| `backup.s3SecretKey` | Secret key for S3 authentication. | `string` | `` | + + +### Bootstrap (recovery) parameters + +| Name | Description | Type | Value | +| ------------------------ | ------------------------------------------------------------------- | -------- | ------- | +| `bootstrap` | Bootstrap configuration. | `object` | `{}` | +| `bootstrap.enabled` | Restore database cluster from a backup. | `bool` | `false` | +| `bootstrap.recoveryTime` | Timestamp (RFC3339) for point-in-time recovery; empty means latest. | `string` | `""` | +| `bootstrap.oldName` | Name of database cluster before deletion. | `string` | `""` | + + +## Parameter examples and reference + +### resources and resourcesPreset + +`resources` sets explicit CPU and memory configurations for each replica. +When left empty, the preset defined in `resourcesPreset` is applied. + +```yaml +resources: + cpu: 4000m + memory: 4Gi +``` + +`resourcesPreset` sets named CPU and memory configurations for each replica. +This setting is ignored if the corresponding `resources` value is set. + +| Preset name | CPU | memory | +|-------------|--------|---------| +| `nano` | `250m` | `128Mi` | +| `micro` | `500m` | `256Mi` | +| `small` | `1` | `512Mi` | +| `medium` | `1` | `1Gi` | +| `large` | `2` | `2Gi` | +| `xlarge` | `4` | `4Gi` | +| `2xlarge` | `8` | `8Gi` | diff --git a/packages/apps/harbor/charts/cozy-lib b/packages/apps/ferretdb/charts/cozy-lib similarity index 100% rename from packages/apps/harbor/charts/cozy-lib rename to packages/apps/ferretdb/charts/cozy-lib diff --git a/packages/apps/ferretdb/logos/ferretdb.svg b/packages/apps/ferretdb/logos/ferretdb.svg new file mode 100644 index 00000000..7d5c8b40 --- /dev/null +++ b/packages/apps/ferretdb/logos/ferretdb.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/packages/apps/mariadb/templates/.gitkeep b/packages/apps/ferretdb/templates/.gitkeep similarity index 100% rename from packages/apps/mariadb/templates/.gitkeep rename to packages/apps/ferretdb/templates/.gitkeep diff --git a/packages/apps/mariadb/templates/_resources.tpl b/packages/apps/ferretdb/templates/_resources.tpl similarity index 100% rename from packages/apps/mariadb/templates/_resources.tpl rename to packages/apps/ferretdb/templates/_resources.tpl diff --git a/packages/apps/ferretdb/templates/backup.yaml b/packages/apps/ferretdb/templates/backup.yaml new file mode 100644 index 00000000..96dea599 --- /dev/null +++ b/packages/apps/ferretdb/templates/backup.yaml @@ -0,0 +1,12 @@ +{{- if .Values.backup.enabled }} +--- +apiVersion: postgresql.cnpg.io/v1 +kind: ScheduledBackup +metadata: + name: {{ .Release.Name }}-postgres +spec: + schedule: {{ .Values.backup.schedule | quote }} + backupOwnerReference: self + cluster: + name: {{ .Release.Name }}-postgres +{{- end }} diff --git a/packages/apps/openbao/templates/dashboard-resourcemap.yaml b/packages/apps/ferretdb/templates/dashboard-resourcemap.yaml similarity index 84% rename from packages/apps/openbao/templates/dashboard-resourcemap.yaml rename to packages/apps/ferretdb/templates/dashboard-resourcemap.yaml index 452a07db..af40a6fa 100644 --- a/packages/apps/openbao/templates/dashboard-resourcemap.yaml +++ b/packages/apps/ferretdb/templates/dashboard-resourcemap.yaml @@ -9,7 +9,13 @@ rules: - services resourceNames: - {{ .Release.Name }} - - {{ .Release.Name }}-internal + verbs: ["get", "list", "watch"] +- apiGroups: + - "" + resources: + - secrets + resourceNames: + - {{ .Release.Name }}-credentials verbs: ["get", "list", "watch"] - apiGroups: - cozystack.io diff --git a/packages/apps/ferretdb/templates/external-svc.yaml b/packages/apps/ferretdb/templates/external-svc.yaml new file mode 100644 index 00000000..b4550cce --- /dev/null +++ b/packages/apps/ferretdb/templates/external-svc.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} + labels: + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }} + {{- if .Values.external }} + externalTrafficPolicy: Local + {{- if (include "cozy-lib.network.disableLoadBalancerNodePorts" $ | fromYaml) }} + allocateLoadBalancerNodePorts: false + {{- end }} + {{- end }} + ports: + - name: ferretdb + port: 27017 + selector: + app: {{ .Release.Name }} diff --git a/packages/apps/ferretdb/templates/ferretdb.yaml b/packages/apps/ferretdb/templates/ferretdb.yaml new file mode 100644 index 00000000..e73d42a3 --- /dev/null +++ b/packages/apps/ferretdb/templates/ferretdb.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: ferretdb + image: ghcr.io/ferretdb/ferretdb:2.4.0 + ports: + - containerPort: 27017 + env: + - name: POSTGRESQL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-postgres-superuser + key: password + - name: FERRETDB_POSTGRESQL_URL + value: "postgresql://postgres:$(POSTGRESQL_PASSWORD)@{{ .Release.Name }}-postgres-rw:5432/postgres" diff --git a/packages/apps/ferretdb/templates/postgres.yaml b/packages/apps/ferretdb/templates/postgres.yaml new file mode 100644 index 00000000..f1b1ce2c --- /dev/null +++ b/packages/apps/ferretdb/templates/postgres.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: {{ .Release.Name }}-postgres +spec: + instances: {{ .Values.replicas }} + {{- if .Values.backup.enabled }} + backup: + barmanObjectStore: + destinationPath: {{ .Values.backup.destinationPath }} + endpointURL: {{ .Values.backup.endpointURL }} + s3Credentials: + accessKeyId: + name: {{ .Release.Name }}-s3-creds + key: AWS_ACCESS_KEY_ID + secretAccessKey: + name: {{ .Release.Name }}-s3-creds + key: AWS_SECRET_ACCESS_KEY + retentionPolicy: {{ .Values.backup.retentionPolicy }} + {{- end }} + + bootstrap: + initdb: + postInitSQL: + - 'CREATE EXTENSION IF NOT EXISTS documentdb CASCADE;' + {{- if .Values.bootstrap.enabled }} + recovery: + source: {{ .Values.bootstrap.oldName }} + {{- if .Values.bootstrap.recoveryTime }} + recoveryTarget: + targetTime: {{ .Values.bootstrap.recoveryTime }} + {{- end }} + {{- end }} + {{- if .Values.bootstrap.enabled }} + externalClusters: + - name: {{ .Values.bootstrap.oldName }} + barmanObjectStore: + destinationPath: {{ .Values.backup.destinationPath }} + endpointURL: {{ .Values.backup.endpointURL }} + s3Credentials: + accessKeyId: + name: {{ .Release.Name }}-s3-creds + key: AWS_ACCESS_KEY_ID + secretAccessKey: + name: {{ .Release.Name }}-s3-creds + key: AWS_SECRET_ACCESS_KEY + {{- end }} + imageName: ghcr.io/ferretdb/postgres-documentdb:17-0.105.0-ferretdb-2.4.0 + postgresUID: 999 + postgresGID: 999 + enableSuperuserAccess: true + {{- if .Values._cluster.scheduling }} + {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} + {{- if $rawConstraints }} + {{- $rawConstraints | fromYaml | toYaml | nindent 2 }} + labelSelector: + matchLabels: + cnpg.io/cluster: {{ .Release.Name }}-postgres + {{- end }} + {{- end }} + minSyncReplicas: {{ .Values.quorum.minSyncReplicas }} + maxSyncReplicas: {{ .Values.quorum.maxSyncReplicas }} + resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 4 }} + monitoring: + enablePodMonitor: true + + postgresql: + shared_preload_libraries: + - pg_cron + - pg_documentdb_core + - pg_documentdb + parameters: + cron.database_name: 'postgres' + pg_hba: + - host postgres postgres 127.0.0.1/32 trust + - host postgres postgres ::1/128 trust + + storage: + size: {{ required ".Values.size is required" .Values.size }} + {{- with .Values.storageClass }} + storageClass: {{ . }} + {{- end }} + + inheritedMetadata: + labels: + policy.cozystack.io/allow-to-apiserver: "true" + app.kubernetes.io/instance: {{ .Release.Name }} + + {{- if .Values.users }} + managed: + roles: + {{- range $user, $config := .Values.users }} + - name: {{ $user }} + ensure: present + passwordSecret: + name: {{ printf "%s-user-%s" $.Release.Name $user }} + login: true + {{- end }} + {{- end }} + +{{- range $user, $config := .Values.users }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-user-%s" $.Release.Name $user }} + labels: + cnpg.io/reload: "true" +type: kubernetes.io/basic-auth +data: + username: {{ $user | b64enc }} + password: {{ $config.password | b64enc }} +{{- end }} diff --git a/packages/apps/mariadb/templates/workloadmonitor.yaml b/packages/apps/ferretdb/templates/workloadmonitor.yaml similarity index 67% rename from packages/apps/mariadb/templates/workloadmonitor.yaml rename to packages/apps/ferretdb/templates/workloadmonitor.yaml index 36cb59f0..a1b364d0 100644 --- a/packages/apps/mariadb/templates/workloadmonitor.yaml +++ b/packages/apps/ferretdb/templates/workloadmonitor.yaml @@ -3,13 +3,11 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 - kind: mariadb - type: mariadb + kind: ferretdb + type: ferretdb selector: app.kubernetes.io/instance: {{ $.Release.Name }} version: {{ $.Chart.Version }} diff --git a/packages/apps/ferretdb/values.schema.json b/packages/apps/ferretdb/values.schema.json new file mode 100644 index 00000000..f22a2340 --- /dev/null +++ b/packages/apps/ferretdb/values.schema.json @@ -0,0 +1,190 @@ +{ + "title": "Chart Values", + "type": "object", + "properties": { + "backup": { + "description": "Backup configuration.", + "type": "object", + "default": {}, + "required": [ + "destinationPath", + "enabled", + "endpointURL", + "retentionPolicy", + "s3AccessKey", + "s3SecretKey", + "schedule" + ], + "properties": { + "destinationPath": { + "description": "Path to store the backup (e.g. s3://bucket/path/to/folder/).", + "type": "string", + "default": "s3://bucket/path/to/folder/" + }, + "enabled": { + "description": "Enable regular backups (default: false).", + "type": "boolean", + "default": false + }, + "endpointURL": { + "description": "S3 endpoint URL for uploads.", + "type": "string", + "default": "http://minio-gateway-service:9000" + }, + "retentionPolicy": { + "description": "Retention policy.", + "type": "string", + "default": "30d" + }, + "s3AccessKey": { + "description": "Access key for S3 authentication.", + "type": "string", + "default": "\u003cyour-access-key\u003e" + }, + "s3SecretKey": { + "description": "Secret key for S3 authentication.", + "type": "string", + "default": "\u003cyour-secret-key\u003e" + }, + "schedule": { + "description": "Cron schedule for automated backups.", + "type": "string", + "default": "0 2 * * * *" + } + } + }, + "bootstrap": { + "description": "Bootstrap configuration.", + "type": "object", + "default": {}, + "properties": { + "enabled": { + "description": "Restore database cluster from a backup.", + "type": "boolean", + "default": false + }, + "oldName": { + "description": "Name of database cluster before deletion.", + "type": "string", + "default": "" + }, + "recoveryTime": { + "description": "Timestamp (RFC3339) for point-in-time recovery; empty means latest.", + "type": "string", + "default": "" + } + } + }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, + "quorum": { + "description": "Configuration for quorum-based synchronous replication.", + "type": "object", + "default": {}, + "required": [ + "maxSyncReplicas", + "minSyncReplicas" + ], + "properties": { + "maxSyncReplicas": { + "description": "Maximum number of synchronous replicas allowed (must be less than total replicas).", + "type": "integer", + "default": 0 + }, + "minSyncReplicas": { + "description": "Minimum number of synchronous replicas required for commit.", + "type": "integer", + "default": 0 + } + } + }, + "replicas": { + "description": "Number of replicas.", + "type": "integer", + "default": 2 + }, + "resources": { + "description": "Explicit CPU and memory configuration for each FerretDB replica. When omitted, the preset defined in `resourcesPreset` is applied.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory (RAM) available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "resourcesPreset": { + "description": "Default sizing preset used when `resources` is omitted.", + "type": "string", + "default": "micro", + "enum": [ + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + }, + "size": { + "description": "Persistent Volume Claim size available for application data.", + "default": "10Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "" + }, + "users": { + "description": "Users configuration map.", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "password": { + "description": "Password for the user.", + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/packages/apps/ferretdb/values.yaml b/packages/apps/ferretdb/values.yaml new file mode 100644 index 00000000..fc905466 --- /dev/null +++ b/packages/apps/ferretdb/values.yaml @@ -0,0 +1,98 @@ +## +## @section Common parameters +## + +## @typedef {struct} Resources - Explicit CPU and memory configuration for each FerretDB replica. +## @field {quantity} [cpu] - CPU available to each replica. +## @field {quantity} [memory] - Memory (RAM) available to each replica. + +## @enum {string} ResourcesPreset - Default sizing preset. +## @value nano +## @value micro +## @value small +## @value medium +## @value large +## @value xlarge +## @value 2xlarge + +## @param {int} replicas - Number of replicas. +replicas: 2 + +## @param {Resources} [resources] - Explicit CPU and memory configuration for each FerretDB replica. When omitted, the preset defined in `resourcesPreset` is applied. +resources: {} + +## @param {ResourcesPreset} resourcesPreset="micro" - Default sizing preset used when `resources` is omitted. +resourcesPreset: "micro" + +## @param {quantity} size - Persistent Volume Claim size available for application data. +size: 10Gi + +## @param {string} storageClass - StorageClass used to store the data. +storageClass: "" + +## @param {bool} external - Enable external access from outside the cluster. +external: false + +## +## @section Application-specific parameters +## + +## @typedef {struct} Quorum - Configuration for quorum-based synchronous replication. +## @field {int} minSyncReplicas - Minimum number of synchronous replicas required for commit. +## @field {int} maxSyncReplicas - Maximum number of synchronous replicas allowed (must be less than total replicas). + +## @param {Quorum} quorum - Configuration for quorum-based synchronous replication. +quorum: + minSyncReplicas: 0 + maxSyncReplicas: 0 + +## @typedef {struct} User - User configuration. +## @field {string} [password] - Password for the user. + +## @param {map[string]User} users - Users configuration map. +users: {} +## Example: +## users: +## user1: +## password: strongpassword +## user2: +## password: hackme +## + +## +## @section Backup parameters +## + +## @typedef {struct} Backup - Backup configuration. +## @field {bool} enabled - Enable regular backups (default: false). +## @field {string} schedule - Cron schedule for automated backups. +## @field {string} retentionPolicy - Retention policy. +## @field {string} endpointURL - S3 endpoint URL for uploads. +## @field {string} destinationPath - Path to store the backup (e.g. s3://bucket/path/to/folder/). +## @field {string} s3AccessKey - Access key for S3 authentication. +## @field {string} s3SecretKey - Secret key for S3 authentication. + +## @param {Backup} backup - Backup configuration. +backup: + enabled: false + schedule: "0 2 * * * *" + retentionPolicy: 30d + endpointURL: http://minio-gateway-service:9000 + destinationPath: s3://bucket/path/to/folder/ + s3AccessKey: "" + s3SecretKey: "" + +## +## @section Bootstrap (recovery) parameters +## + +## @typedef {struct} Bootstrap - Bootstrap configuration for restoring a database cluster from a backup. +## @field {bool} [enabled] - Restore database cluster from a backup. +## @field {string} [recoveryTime] - Timestamp (RFC3339) for point-in-time recovery; empty means latest. +## @field {string} [oldName] - Name of database cluster before deletion. + +## @param {Bootstrap} bootstrap - Bootstrap configuration. +bootstrap: + enabled: false + recoveryTime: "" + oldName: "" diff --git a/packages/apps/foundationdb/Makefile b/packages/apps/foundationdb/Makefile index 1a07cd5b..76c84980 100644 --- a/packages/apps/foundationdb/Makefile +++ b/packages/apps/foundationdb/Makefile @@ -1,4 +1,4 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'foundationdb' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/foundationdb/types.go \ No newline at end of file + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md \ No newline at end of file diff --git a/packages/apps/foundationdb/README.md b/packages/apps/foundationdb/README.md index 30f5714e..4f7b6878 100644 --- a/packages/apps/foundationdb/README.md +++ b/packages/apps/foundationdb/README.md @@ -1,4 +1,4 @@ -# Managed FoundationDB Service +# FoundationDB A managed FoundationDB service for Cozystack. diff --git a/packages/apps/foundationdb/templates/workloadmonitor.yaml b/packages/apps/foundationdb/templates/workloadmonitor.yaml index 2e2a3d19..306797f3 100644 --- a/packages/apps/foundationdb/templates/workloadmonitor.yaml +++ b/packages/apps/foundationdb/templates/workloadmonitor.yaml @@ -8,7 +8,6 @@ metadata: app.kubernetes.io/name: foundationdb app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.cluster.processCounts.storage }} minReplicas: {{ include "foundationdb.minReplicas" . }} diff --git a/packages/apps/foundationdb/values.schema.json b/packages/apps/foundationdb/values.schema.json index 1fc77d59..7b3a1ba5 100644 --- a/packages/apps/foundationdb/values.schema.json +++ b/packages/apps/foundationdb/values.schema.json @@ -2,6 +2,82 @@ "title": "Chart Values", "type": "object", "properties": { + "automaticReplacements": { + "description": "Enable automatic pod replacements.", + "type": "boolean", + "default": true + }, + "backup": { + "description": "Backup configuration.", + "type": "object", + "default": {}, + "required": [ + "enabled", + "retentionPolicy", + "s3" + ], + "properties": { + "enabled": { + "description": "Enable backups.", + "type": "boolean", + "default": false + }, + "retentionPolicy": { + "description": "Retention policy for backups.", + "type": "string", + "default": "7d" + }, + "s3": { + "description": "S3 configuration for backups.", + "type": "object", + "default": {}, + "required": [ + "bucket", + "credentials", + "endpoint", + "region" + ], + "properties": { + "bucket": { + "description": "S3 bucket name.", + "type": "string", + "default": "" + }, + "credentials": { + "description": "S3 credentials.", + "type": "object", + "default": {}, + "required": [ + "accessKeyId", + "secretAccessKey" + ], + "properties": { + "accessKeyId": { + "description": "S3 access key ID.", + "type": "string", + "default": "" + }, + "secretAccessKey": { + "description": "S3 secret access key.", + "type": "string", + "default": "" + } + } + }, + "endpoint": { + "description": "S3 endpoint URL.", + "type": "string", + "default": "" + }, + "region": { + "description": "S3 region.", + "type": "string", + "default": "us-east-1" + } + } + } + } + }, "cluster": { "description": "Cluster configuration.", "type": "object", @@ -79,33 +155,35 @@ } } }, - "storage": { - "description": "Storage configuration.", + "customParameters": { + "description": "Custom parameters to pass to FoundationDB.", + "type": "array", + "default": [], + "items": { + "type": "string" + } + }, + "imageType": { + "description": "Container image deployment type.", + "type": "string", + "default": "unified", + "enum": [ + "unified", + "split" + ] + }, + "monitoring": { + "description": "Monitoring configuration.", "type": "object", "default": {}, "required": [ - "size", - "storageClass" + "enabled" ], "properties": { - "size": { - "description": "Size of persistent volumes for each instance.", - "default": "16Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "Storage class (if not set, uses cluster default).", - "type": "string", - "default": "" + "enabled": { + "description": "Enable WorkloadMonitor integration.", + "type": "boolean", + "default": true } } }, @@ -154,109 +232,6 @@ "2xlarge" ] }, - "backup": { - "description": "Backup configuration.", - "type": "object", - "default": {}, - "required": [ - "enabled", - "retentionPolicy", - "s3" - ], - "properties": { - "enabled": { - "description": "Enable backups.", - "type": "boolean", - "default": false - }, - "retentionPolicy": { - "description": "Retention policy for backups.", - "type": "string", - "default": "7d" - }, - "s3": { - "description": "S3 configuration for backups.", - "type": "object", - "default": {}, - "required": [ - "bucket", - "credentials", - "endpoint", - "region" - ], - "properties": { - "bucket": { - "description": "S3 bucket name.", - "type": "string", - "default": "" - }, - "credentials": { - "description": "S3 credentials.", - "type": "object", - "default": {}, - "required": [ - "accessKeyId", - "secretAccessKey" - ], - "properties": { - "accessKeyId": { - "description": "S3 access key ID.", - "type": "string", - "default": "" - }, - "secretAccessKey": { - "description": "S3 secret access key.", - "type": "string", - "default": "" - } - } - }, - "endpoint": { - "description": "S3 endpoint URL.", - "type": "string", - "default": "" - }, - "region": { - "description": "S3 region.", - "type": "string", - "default": "us-east-1" - } - } - } - } - }, - "monitoring": { - "description": "Monitoring configuration.", - "type": "object", - "default": {}, - "required": [ - "enabled" - ], - "properties": { - "enabled": { - "description": "Enable WorkloadMonitor integration.", - "type": "boolean", - "default": true - } - } - }, - "customParameters": { - "description": "Custom parameters to pass to FoundationDB.", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, - "imageType": { - "description": "Container image deployment type.", - "type": "string", - "default": "unified", - "enum": [ - "unified", - "split" - ] - }, "securityContext": { "description": "Security context for containers.", "type": "object", @@ -278,10 +253,35 @@ } } }, - "automaticReplacements": { - "description": "Enable automatic pod replacements.", - "type": "boolean", - "default": true + "storage": { + "description": "Storage configuration.", + "type": "object", + "default": {}, + "required": [ + "size", + "storageClass" + ], + "properties": { + "size": { + "description": "Size of persistent volumes for each instance.", + "default": "16Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "storageClass": { + "description": "Storage class (if not set, uses cluster default).", + "type": "string", + "default": "" + } + } } } -} +} \ No newline at end of file diff --git a/packages/apps/harbor/Makefile b/packages/apps/harbor/Makefile deleted file mode 100644 index 43c25998..00000000 --- a/packages/apps/harbor/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -NAME=harbor - -include ../../../hack/package.mk - -generate: - cozyvalues-gen -m 'harbor' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/harbor/types.go - ../../../hack/update-crd.sh diff --git a/packages/apps/harbor/README.md b/packages/apps/harbor/README.md deleted file mode 100644 index 7789d9fe..00000000 --- a/packages/apps/harbor/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Managed Harbor Container Registry - -Harbor is an open-source trusted cloud-native registry project that stores, signs, and scans content. - -## Parameters - -### Common parameters - -| Name | Description | Type | Value | -| -------------- | -------------------------------------------------------------------------------------------- | -------- | ----- | -| `host` | Hostname for external access to Harbor (defaults to 'harbor' subdomain for the tenant host). | `string` | `""` | -| `storageClass` | StorageClass used to store the data. | `string` | `""` | - - -### Component configuration - -| Name | Description | Type | Value | -| ----------------------------- | -------------------------------------------------------------------------------------------------------- | ---------- | ------- | -| `core` | Core API server configuration. | `object` | `{}` | -| `core.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `core.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `core.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `core.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `registry` | Container image registry configuration. | `object` | `{}` | -| `registry.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `registry.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `registry.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `registry.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `jobservice` | Background job service configuration. | `object` | `{}` | -| `jobservice.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `jobservice.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `jobservice.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `jobservice.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` | -| `trivy` | Trivy vulnerability scanner configuration. | `object` | `{}` | -| `trivy.enabled` | Enable or disable the vulnerability scanner. | `bool` | `true` | -| `trivy.size` | Persistent Volume size for vulnerability database cache. | `quantity` | `5Gi` | -| `trivy.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `trivy.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `trivy.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `trivy.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` | -| `database` | PostgreSQL database configuration. | `object` | `{}` | -| `database.size` | Persistent Volume size for database storage. | `quantity` | `5Gi` | -| `database.replicas` | Number of database instances. | `int` | `2` | -| `redis` | Redis cache configuration. | `object` | `{}` | -| `redis.size` | Persistent Volume size for cache storage. | `quantity` | `1Gi` | -| `redis.replicas` | Number of Redis replicas. | `int` | `2` | - diff --git a/packages/apps/harbor/logos/harbor.svg b/packages/apps/harbor/logos/harbor.svg deleted file mode 100644 index 682254c3..00000000 --- a/packages/apps/harbor/logos/harbor.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/apps/harbor/templates/bucket.yaml b/packages/apps/harbor/templates/bucket.yaml deleted file mode 100644 index a9e60988..00000000 --- a/packages/apps/harbor/templates/bucket.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- $seaweedfs := .Values._namespace.seaweedfs }} -apiVersion: objectstorage.k8s.io/v1alpha1 -kind: BucketClaim -metadata: - name: {{ .Release.Name }}-registry -spec: - bucketClassName: {{ $seaweedfs }} - protocols: - - s3 ---- -apiVersion: objectstorage.k8s.io/v1alpha1 -kind: BucketAccess -metadata: - name: {{ .Release.Name }}-registry -spec: - bucketAccessClassName: {{ $seaweedfs }} - bucketClaimName: {{ .Release.Name }}-registry - credentialsSecretName: {{ .Release.Name }}-registry-bucket - protocol: s3 diff --git a/packages/apps/harbor/templates/dashboard-resourcemap.yaml b/packages/apps/harbor/templates/dashboard-resourcemap.yaml deleted file mode 100644 index f8d91a61..00000000 --- a/packages/apps/harbor/templates/dashboard-resourcemap.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ .Release.Name }}-dashboard-resources -rules: -- apiGroups: - - "" - resources: - - services - resourceNames: - - {{ .Release.Name }} - verbs: ["get", "list", "watch"] -- apiGroups: - - "" - resources: - - secrets - resourceNames: - - {{ .Release.Name }}-credentials - verbs: ["get", "list", "watch"] -- apiGroups: - - networking.k8s.io - resources: - - ingresses - resourceNames: - - {{ .Release.Name }}-ingress - verbs: ["get", "list", "watch"] -- apiGroups: - - cozystack.io - resources: - - workloadmonitors - resourceNames: - - {{ .Release.Name }}-core - - {{ .Release.Name }}-registry - - {{ .Release.Name }}-portal - verbs: ["get", "list", "watch"] ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ .Release.Name }}-dashboard-resources -subjects: -{{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "super-admin" .Release.Namespace) }} -roleRef: - kind: Role - name: {{ .Release.Name }}-dashboard-resources - apiGroup: rbac.authorization.k8s.io diff --git a/packages/apps/harbor/templates/harbor.yaml b/packages/apps/harbor/templates/harbor.yaml deleted file mode 100644 index bf780967..00000000 --- a/packages/apps/harbor/templates/harbor.yaml +++ /dev/null @@ -1,205 +0,0 @@ -{{- $host := .Values._namespace.host }} -{{- $harborHost := .Values.host | default (printf "%s.%s" .Release.Name $host) }} - -{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }} -{{- $adminPassword := randAlphaNum 16 }} -{{- $redisPassword := randAlphaNum 32 }} -{{- if $existingSecret }} - {{- $adminPassword = index $existingSecret.data "admin-password" | b64dec }} - {{- if hasKey $existingSecret.data "redis-password" }} - {{- $redisPassword = index $existingSecret.data "redis-password" | b64dec }} - {{- end }} -{{- end }} - -{{- $existingCoreSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-core" .Release.Name) }} -{{- $tokenKey := "" }} -{{- $tokenCert := "" }} -{{- if $existingCoreSecret }} - {{- if hasKey $existingCoreSecret.data "tls.key" }} - {{- $tokenKey = index $existingCoreSecret.data "tls.key" | b64dec }} - {{- end }} - {{- if hasKey $existingCoreSecret.data "tls.crt" }} - {{- $tokenCert = index $existingCoreSecret.data "tls.crt" | b64dec }} - {{- end }} -{{- end }} - -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-credentials -stringData: - admin-password: {{ $adminPassword | quote }} - redis-password: {{ $redisPassword | quote }} - url: https://{{ $harborHost }} - ---- - -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ .Release.Name }}-system - labels: - sharding.fluxcd.io/key: tenants -spec: - chartRef: - kind: ExternalArtifact - name: cozystack-harbor-application-default-harbor-system - namespace: cozy-system - interval: 5m - timeout: 15m - install: - remediation: - retries: -1 - upgrade: - force: true - remediation: - retries: -1 - valuesFrom: - - kind: Secret - name: cozystack-values - - kind: Secret - name: {{ .Release.Name }}-credentials - valuesKey: redis-password - targetPath: redis.password - - kind: Secret - name: {{ .Release.Name }}-credentials - valuesKey: redis-password - targetPath: harbor.redis.external.password - values: - bucket: - secretName: {{ .Release.Name }}-registry-bucket - db: - replicas: {{ .Values.database.replicas }} - size: {{ .Values.database.size }} - {{- with .Values.storageClass }} - storageClass: {{ . }} - {{- end }} - redis: - replicas: {{ .Values.redis.replicas }} - size: {{ .Values.redis.size }} - {{- with .Values.storageClass }} - storageClass: {{ . }} - {{- end }} - harbor: - fullnameOverride: {{ .Release.Name }} - harborAdminPassword: {{ $adminPassword | quote }} - externalURL: https://{{ $harborHost }} - expose: - type: clusterIP - clusterIP: - name: {{ .Release.Name }} - tls: - enabled: false - persistence: - enabled: true - resourcePolicy: "keep" - imageChartStorage: - type: s3 - s3: - existingSecret: {{ .Release.Name }}-registry-s3 - region: us-east-1 - bucket: {{ .Release.Name }}-registry - secure: false - v4auth: true - {{- if .Values.trivy.enabled }} - persistentVolumeClaim: - trivy: - size: {{ .Values.trivy.size }} - {{- with .Values.storageClass }} - storageClass: {{ . }} - {{- end }} - {{- end }} - portal: - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list "nano" (dict) $) | nindent 10 }} - core: - {{- if and $tokenKey $tokenCert }} - tokenKey: {{ $tokenKey | quote }} - tokenCert: {{ $tokenCert | quote }} - {{- end }} - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.core.resourcesPreset .Values.core.resources $) | nindent 10 }} - registry: - registry: - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.registry.resourcesPreset .Values.registry.resources $) | nindent 12 }} - controller: - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.registry.resourcesPreset .Values.registry.resources $) | nindent 12 }} - jobservice: - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.jobservice.resourcesPreset .Values.jobservice.resources $) | nindent 10 }} - trivy: - enabled: {{ .Values.trivy.enabled }} - {{- if .Values.trivy.enabled }} - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.trivy.resourcesPreset .Values.trivy.resources $) | nindent 10 }} - {{- end }} - database: - type: external - external: - host: "{{ .Release.Name }}-db-rw" - port: "5432" - username: app - coreDatabase: app - sslmode: require - existingSecret: "{{ .Release.Name }}-db-app" - redis: - type: external - external: - addr: "rfs-{{ .Release.Name }}-redis:26379" - sentinelMasterSet: "mymaster" - coreDatabaseIndex: "0" - jobserviceDatabaseIndex: "1" - registryDatabaseIndex: "2" - trivyAdapterIndex: "5" - metrics: - enabled: true - serviceMonitor: - enabled: true - ---- - -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ $.Release.Name }}-core - labels: - workloads.cozystack.io/resource-preset: {{ .Values.core.resourcesPreset | quote }} -spec: - replicas: 1 - minReplicas: 1 - kind: harbor - type: core - selector: - release: {{ $.Release.Name }}-system - component: core - version: {{ $.Chart.Version }} - ---- - -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ $.Release.Name }}-registry - labels: - workloads.cozystack.io/resource-preset: {{ .Values.registry.resourcesPreset | quote }} -spec: - replicas: 1 - minReplicas: 1 - kind: harbor - type: registry - selector: - release: {{ $.Release.Name }}-system - component: registry - version: {{ $.Chart.Version }} - ---- - -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ $.Release.Name }}-portal -spec: - replicas: 1 - minReplicas: 1 - kind: harbor - type: portal - selector: - release: {{ $.Release.Name }}-system - component: portal - version: {{ $.Chart.Version }} diff --git a/packages/apps/harbor/templates/ingress.yaml b/packages/apps/harbor/templates/ingress.yaml deleted file mode 100644 index 70933f5f..00000000 --- a/packages/apps/harbor/templates/ingress.yaml +++ /dev/null @@ -1,37 +0,0 @@ -{{- $ingress := .Values._namespace.ingress }} -{{- $host := .Values._namespace.host }} -{{- $harborHost := .Values.host | default (printf "%s.%s" .Release.Name $host) }} -{{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }} ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ .Release.Name }}-ingress - annotations: - nginx.ingress.kubernetes.io/proxy-body-size: "0" - nginx.ingress.kubernetes.io/proxy-read-timeout: "900" - nginx.ingress.kubernetes.io/proxy-send-timeout: "900" - nginx.ingress.kubernetes.io/ssl-redirect: "true" - nginx.ingress.kubernetes.io/backend-protocol: "HTTP" - {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} - {{- end }} - cert-manager.io/cluster-issuer: {{ $clusterIssuer }} -spec: - ingressClassName: {{ $ingress }} - tls: - - hosts: - - {{ $harborHost | quote }} - secretName: {{ .Release.Name }}-ingress-tls - rules: - - host: {{ $harborHost | quote }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ .Release.Name }} - port: - number: 80 diff --git a/packages/apps/harbor/values.schema.json b/packages/apps/harbor/values.schema.json deleted file mode 100644 index 23860ca3..00000000 --- a/packages/apps/harbor/values.schema.json +++ /dev/null @@ -1,315 +0,0 @@ -{ - "title": "Chart Values", - "type": "object", - "properties": { - "host": { - "description": "Hostname for external access to Harbor (defaults to 'harbor' subdomain for the tenant host).", - "type": "string", - "default": "" - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, - "core": { - "description": "Core API server configuration.", - "type": "object", - "default": {}, - "properties": { - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "small", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - } - } - }, - "registry": { - "description": "Container image registry configuration.", - "type": "object", - "default": {}, - "properties": { - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "small", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - } - } - }, - "jobservice": { - "description": "Background job service configuration.", - "type": "object", - "default": {}, - "properties": { - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "nano", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - } - } - }, - "trivy": { - "description": "Trivy vulnerability scanner configuration.", - "type": "object", - "default": {}, - "required": [ - "enabled", - "size" - ], - "properties": { - "enabled": { - "description": "Enable or disable the vulnerability scanner.", - "type": "boolean", - "default": true - }, - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "nano", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, - "size": { - "description": "Persistent Volume size for vulnerability database cache.", - "default": "5Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "database": { - "description": "PostgreSQL database configuration.", - "type": "object", - "default": {}, - "required": [ - "replicas", - "size" - ], - "properties": { - "replicas": { - "description": "Number of database instances.", - "type": "integer", - "default": 2 - }, - "size": { - "description": "Persistent Volume size for database storage.", - "default": "5Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "redis": { - "description": "Redis cache configuration.", - "type": "object", - "default": {}, - "required": [ - "replicas", - "size" - ], - "properties": { - "replicas": { - "description": "Number of Redis replicas.", - "type": "integer", - "default": 2 - }, - "size": { - "description": "Persistent Volume size for cache storage.", - "default": "1Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - } - } -} diff --git a/packages/apps/harbor/values.yaml b/packages/apps/harbor/values.yaml deleted file mode 100644 index de44eaff..00000000 --- a/packages/apps/harbor/values.yaml +++ /dev/null @@ -1,84 +0,0 @@ -## -## @section Common parameters -## - -## @param {string} [host] - Hostname for external access to Harbor (defaults to 'harbor' subdomain for the tenant host). -host: "" - -## @param {string} storageClass - StorageClass used to store the data. -storageClass: "" - -## -## @section Component configuration -## - -## @typedef {struct} Resources - Resource configuration. -## @field {quantity} [cpu] - Number of CPU cores allocated. -## @field {quantity} [memory] - Amount of memory allocated. - -## @enum {string} ResourcesPreset - Default sizing preset. -## @value nano -## @value micro -## @value small -## @value medium -## @value large -## @value xlarge -## @value 2xlarge - -## @typedef {struct} Core - Core API server configuration. -## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. -## @field {ResourcesPreset} [resourcesPreset] - Default sizing preset used when `resources` is omitted. - -## @param {Core} core - Core API server configuration. -core: - resources: {} - resourcesPreset: "small" - -## @typedef {struct} Registry - Container image registry configuration. -## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. -## @field {ResourcesPreset} [resourcesPreset] - Default sizing preset used when `resources` is omitted. - -## @param {Registry} registry - Container image registry configuration. -registry: - resources: {} - resourcesPreset: "small" - -## @typedef {struct} Jobservice - Background job service configuration. -## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. -## @field {ResourcesPreset} [resourcesPreset] - Default sizing preset used when `resources` is omitted. - -## @param {Jobservice} jobservice - Background job service configuration. -jobservice: - resources: {} - resourcesPreset: "nano" - -## @typedef {struct} Trivy - Trivy vulnerability scanner configuration. -## @field {bool} enabled - Enable or disable the vulnerability scanner. -## @field {quantity} size - Persistent Volume size for vulnerability database cache. -## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. -## @field {ResourcesPreset} [resourcesPreset] - Default sizing preset used when `resources` is omitted. - -## @param {Trivy} trivy - Trivy vulnerability scanner configuration. -trivy: - enabled: true - size: 5Gi - resources: {} - resourcesPreset: "nano" - -## @typedef {struct} Database - PostgreSQL database configuration (provisioned via CloudNativePG). -## @field {quantity} size - Persistent Volume size for database storage. -## @field {int} replicas - Number of database instances. - -## @param {Database} database - PostgreSQL database configuration. -database: - size: 5Gi - replicas: 2 - -## @typedef {struct} Redis - Redis cache configuration (provisioned via redis-operator). -## @field {quantity} size - Persistent Volume size for cache storage. -## @field {int} replicas - Number of Redis replicas. - -## @param {Redis} redis - Redis cache configuration. -redis: - size: 1Gi - replicas: 2 diff --git a/packages/apps/http-cache/Makefile b/packages/apps/http-cache/Makefile index 899f0288..2cc11f87 100644 --- a/packages/apps/http-cache/Makefile +++ b/packages/apps/http-cache/Makefile @@ -17,7 +17,7 @@ image-nginx: rm -f images/nginx-cache.json generate: - cozyvalues-gen -m 'httpcache' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/httpcache/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh update: diff --git a/packages/apps/http-cache/images/nginx-cache.tag b/packages/apps/http-cache/images/nginx-cache.tag index b08a374e..ee4d8890 100644 --- a/packages/apps/http-cache/images/nginx-cache.tag +++ b/packages/apps/http-cache/images/nginx-cache.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:d397781152ab9123b11b8191d92eba7a0d2faa376aa2c15ddeb67842a9b59bab +ghcr.io/cozystack/cozystack/nginx-cache:0.0.0@sha256:9e34fd50393b418d9516aadb488067a3a63675b045811beb1c0afc9c61e149e8 diff --git a/packages/apps/http-cache/templates/workloadmonitor.yaml b/packages/apps/http-cache/templates/workloadmonitor.yaml index a38a395a..150d8bbe 100644 --- a/packages/apps/http-cache/templates/workloadmonitor.yaml +++ b/packages/apps/http-cache/templates/workloadmonitor.yaml @@ -3,8 +3,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }}-haproxy - labels: - workloads.cozystack.io/resource-preset: {{ .Values.haproxy.resourcesPreset | quote }} spec: replicas: {{ .Values.haproxy.replicas }} minReplicas: 1 @@ -18,8 +16,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }}-nginx - labels: - workloads.cozystack.io/resource-preset: {{ .Values.nginx.resourcesPreset | quote }} spec: replicas: {{ .Values.nginx.replicas }} minReplicas: 1 diff --git a/packages/apps/http-cache/values.schema.json b/packages/apps/http-cache/values.schema.json index 14609cc3..7fd1a37a 100644 --- a/packages/apps/http-cache/values.schema.json +++ b/packages/apps/http-cache/values.schema.json @@ -2,30 +2,6 @@ "title": "Chart Values", "type": "object", "properties": { - "size": { - "description": "Persistent Volume Claim size available for application data.", - "default": "10Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, "endpoints": { "description": "Endpoints configuration, as a list of \u003cip:port\u003e.", "type": "array", @@ -34,6 +10,11 @@ "type": "string" } }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, "haproxy": { "description": "HAProxy configuration.", "type": "object", @@ -159,6 +140,25 @@ ] } } + }, + "size": { + "description": "Persistent Volume Claim size available for application data.", + "default": "10Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "" } } -} +} \ No newline at end of file diff --git a/packages/apps/kafka/Makefile b/packages/apps/kafka/Makefile index c1084e86..2cffdfa7 100644 --- a/packages/apps/kafka/Makefile +++ b/packages/apps/kafka/Makefile @@ -2,5 +2,5 @@ include ../../../hack/package.mk PRESET_ENUM := ["nano","micro","small","medium","large","xlarge","2xlarge"] generate: - cozyvalues-gen -m 'kafka' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/kafka/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh diff --git a/packages/apps/kafka/templates/workloadmonitor.yaml b/packages/apps/kafka/templates/workloadmonitor.yaml index c31eb425..4b161b04 100644 --- a/packages/apps/kafka/templates/workloadmonitor.yaml +++ b/packages/apps/kafka/templates/workloadmonitor.yaml @@ -3,8 +3,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.kafka.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 @@ -21,8 +19,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }}-zookeeper - labels: - workloads.cozystack.io/resource-preset: {{ .Values.zookeeper.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 diff --git a/packages/apps/kafka/values.schema.json b/packages/apps/kafka/values.schema.json index e3b6db12..4b375b63 100644 --- a/packages/apps/kafka/values.schema.json +++ b/packages/apps/kafka/values.schema.json @@ -7,39 +7,6 @@ "type": "boolean", "default": false }, - "topics": { - "description": "Topics configuration.", - "type": "array", - "default": [], - "items": { - "type": "object", - "required": [ - "config", - "name", - "partitions", - "replicas" - ], - "properties": { - "config": { - "description": "Topic configuration.", - "type": "object", - "x-kubernetes-preserve-unknown-fields": true - }, - "name": { - "description": "Topic name.", - "type": "string" - }, - "partitions": { - "description": "Number of partitions.", - "type": "integer" - }, - "replicas": { - "description": "Number of replicas.", - "type": "integer" - } - } - } - }, "kafka": { "description": "Kafka configuration.", "type": "object", @@ -124,6 +91,39 @@ } } }, + "topics": { + "description": "Topics configuration.", + "type": "array", + "default": [], + "items": { + "type": "object", + "required": [ + "config", + "name", + "partitions", + "replicas" + ], + "properties": { + "config": { + "description": "Topic configuration.", + "type": "object", + "x-kubernetes-preserve-unknown-fields": true + }, + "name": { + "description": "Topic name.", + "type": "string" + }, + "partitions": { + "description": "Number of partitions.", + "type": "integer" + }, + "replicas": { + "description": "Number of replicas.", + "type": "integer" + } + } + } + }, "zookeeper": { "description": "ZooKeeper configuration.", "type": "object", @@ -209,4 +209,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/apps/kubernetes/.helmignore b/packages/apps/kubernetes/.helmignore index cdada667..3de7d4a5 100644 --- a/packages/apps/kubernetes/.helmignore +++ b/packages/apps/kubernetes/.helmignore @@ -2,4 +2,3 @@ /logos /Makefile /hack -/images/*/* diff --git a/packages/apps/kubernetes/Makefile b/packages/apps/kubernetes/Makefile index 4fea42ef..e6ed7c6f 100644 --- a/packages/apps/kubernetes/Makefile +++ b/packages/apps/kubernetes/Makefile @@ -1,14 +1,11 @@ -KUBERNETES_VERSIONS = $(shell awk -F'"' '{print $$2}' files/versions.yaml) +KUBERNETES_VERSION = v1.33 KUBERNETES_PKG_TAG = $(shell awk '$$1 == "version:" {print $$2}' Chart.yaml) include ../../../hack/common-envs.mk include ../../../hack/package.mk -test: - helm unittest . - generate: - cozyvalues-gen -m 'kubernetes' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/kubernetes/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh update: @@ -18,19 +15,17 @@ update: image: image-ubuntu-container-disk image-kubevirt-cloud-provider image-kubevirt-csi-driver image-cluster-autoscaler image-ubuntu-container-disk: - $(foreach ver,$(KUBERNETES_VERSIONS), \ - docker buildx build images/ubuntu-container-disk \ - --build-arg KUBERNETES_VERSION=$(ver) \ - --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(ver)) \ - --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(ver)-$(TAG)) \ - --cache-from type=registry,ref=$(REGISTRY)/ubuntu-container-disk:$(call settag,$(ver)) \ - --cache-to type=inline \ - --metadata-file images/ubuntu-container-disk-$(ver).json \ - $(BUILDX_ARGS) && \ - echo "$(REGISTRY)/ubuntu-container-disk:$(call settag,$(ver))@$$(yq e '."containerimage.digest"' images/ubuntu-container-disk-$(ver).json -o json -r)" \ - > images/ubuntu-container-disk-$(ver).tag && \ - rm -f images/ubuntu-container-disk-$(ver).json; \ - ) + docker buildx build images/ubuntu-container-disk \ + --build-arg KUBERNETES_VERSION=${KUBERNETES_VERSION} \ + --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION)) \ + --tag $(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION)-$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/ubuntu-container-disk:latest \ + --cache-to type=inline \ + --metadata-file images/ubuntu-container-disk.json \ + $(BUILDX_ARGS) + echo "$(REGISTRY)/ubuntu-container-disk:$(call settag,$(KUBERNETES_VERSION))@$$(yq e '."containerimage.digest"' images/ubuntu-container-disk.json -o json -r)" \ + > images/ubuntu-container-disk.tag + rm -f images/ubuntu-container-disk.json image-kubevirt-cloud-provider: docker buildx build images/kubevirt-cloud-provider \ @@ -70,4 +65,3 @@ image-cluster-autoscaler: echo "$(REGISTRY)/cluster-autoscaler:$(call settag,$(KUBERNETES_PKG_TAG))@$$(yq e '."containerimage.digest"' images/cluster-autoscaler.json -o json -r)" \ > images/cluster-autoscaler.tag rm -f images/cluster-autoscaler.json - diff --git a/packages/apps/kubernetes/README.md b/packages/apps/kubernetes/README.md index bed1117a..b2fe102f 100644 --- a/packages/apps/kubernetes/README.md +++ b/packages/apps/kubernetes/README.md @@ -104,7 +104,7 @@ See the reference for components utilized in this service: | `nodeGroups[name].resources.memory` | Memory (RAM) available. | `quantity` | `""` | | `nodeGroups[name].gpus` | List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | `[]object` | `[]` | | `nodeGroups[name].gpus[i].name` | Name of GPU, such as "nvidia.com/AD102GL_L40S". | `string` | `""` | -| `version` | Kubernetes major.minor version to deploy | `string` | `v1.35` | +| `version` | Kubernetes major.minor version to deploy | `string` | `v1.33` | | `host` | External hostname for Kubernetes cluster. Defaults to `.` if empty. | `string` | `""` | @@ -128,9 +128,6 @@ See the reference for components utilized in this service: | `addons.gpuOperator` | NVIDIA GPU Operator. | `object` | `{}` | | `addons.gpuOperator.enabled` | Enable GPU Operator. | `bool` | `false` | | `addons.gpuOperator.valuesOverride` | Custom Helm values overrides. | `object` | `{}` | -| `addons.hami` | HAMi GPU virtualization middleware. | `object` | `{}` | -| `addons.hami.enabled` | Enable HAMi (requires GPU Operator). | `bool` | `false` | -| `addons.hami.valuesOverride` | Custom Helm values overrides. | `object` | `{}` | | `addons.fluxcd` | FluxCD GitOps operator. | `object` | `{}` | | `addons.fluxcd.enabled` | Enable FluxCD. | `bool` | `false` | | `addons.fluxcd.valuesOverride` | Custom Helm values overrides. | `object` | `{}` | @@ -148,33 +145,31 @@ See the reference for components utilized in this service: ### Kubernetes Control Plane Configuration -| Name | Description | Type | Value | -| --------------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------- | ------- | -| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` | -| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` | -| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` | -| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` | -| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `large` | -| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` | -| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` | -| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` | -| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` | -| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` | -| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` | -| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` | -| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` | -| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` | -| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | -| `images` | Optional image overrides for air-gapped or rate-limited registries. | `object` | `{}` | -| `images.waitForKubeconfig` | Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag. | `string` | `""` | +| Name | Description | Type | Value | +| --------------------------------------------------- | ------------------------------------------------ | ---------- | ------- | +| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` | +| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` | +| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` | +| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` | +| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `large` | +| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` | +| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` | +| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | +| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` | +| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` | +| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | +| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` | +| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` | +| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` | +| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` | +| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` | +| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` | ## Parameter examples and reference diff --git a/packages/apps/kubernetes/files/konnectivity-versions.yaml b/packages/apps/kubernetes/files/konnectivity-versions.yaml deleted file mode 100644 index 09ef4fa7..00000000 --- a/packages/apps/kubernetes/files/konnectivity-versions.yaml +++ /dev/null @@ -1,4 +0,0 @@ -# Konnectivity proxy version overrides per Kubernetes minor version. -# When empty or absent, Kamaji auto-derives v0.{minor}.0 from the Kubernetes version. -# Add entries here only when the auto-derived image tag does not exist in the registry. -"v1.35": "v0.34.0" diff --git a/packages/apps/kubernetes/files/versions.yaml b/packages/apps/kubernetes/files/versions.yaml index 58942b97..51a36034 100644 --- a/packages/apps/kubernetes/files/versions.yaml +++ b/packages/apps/kubernetes/files/versions.yaml @@ -1,6 +1,6 @@ -"v1.35": "v1.35.1" -"v1.34": "v1.34.4" -"v1.33": "v1.33.8" -"v1.32": "v1.32.12" +"v1.33": "v1.33.0" +"v1.32": "v1.32.10" "v1.31": "v1.31.14" "v1.30": "v1.30.14" +"v1.29": "v1.29.15" +"v1.28": "v1.28.15" diff --git a/packages/apps/kubernetes/images/busybox.tag b/packages/apps/kubernetes/images/busybox.tag deleted file mode 100644 index 39de220a..00000000 --- a/packages/apps/kubernetes/images/busybox.tag +++ /dev/null @@ -1 +0,0 @@ -docker.io/library/busybox:1.37.0@sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e diff --git a/packages/apps/kubernetes/images/cluster-autoscaler.tag b/packages/apps/kubernetes/images/cluster-autoscaler.tag index d9fd9a52..03a5ad61 100644 --- a/packages/apps/kubernetes/images/cluster-autoscaler.tag +++ b/packages/apps/kubernetes/images/cluster-autoscaler.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:e9d0aa7e651b03a6713b380101a61832818a91b5f989da9754f58693898c4056 +ghcr.io/cozystack/cozystack/cluster-autoscaler:0.0.0@sha256:6f2b1d6b0b2bdc66f1cbb30c59393369cbf070cb8f5fec748f176952273483cc diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag index 00aa2caa..02f8f103 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver.tag +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:72154a97054e16cdf3dea6129d962b8d7e86b55cf9386095e8ac2ce7c8b69172 +ghcr.io/cozystack/cozystack/kubevirt-csi-driver:0.0.0@sha256:726d9287e8caaea94eaf24c4f44734e3fbf4f8aa032b66b81848ebf95297cffe diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile b/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile index b156d08e..5ae5817f 100644 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile +++ b/packages/apps/kubernetes/images/kubevirt-csi-driver/Dockerfile @@ -1,23 +1,31 @@ +# Source: https://github.com/kubevirt/csi-driver/blob/main/Dockerfile ARG builder_image=docker.io/library/golang:1.22.5 FROM ${builder_image} AS builder +RUN git clone https://github.com/kubevirt/csi-driver /src/kubevirt-csi-driver \ + && cd /src/kubevirt-csi-driver \ + && git checkout a8d6605bc9997bcfda3fb9f1f82ba6445b4984cc ARG TARGETOS ARG TARGETARCH +ENV GOOS=$TARGETOS +ENV GOARCH=$TARGETARCH -WORKDIR /src +WORKDIR /src/kubevirt-csi-driver -COPY go.mod go.sum ./ -RUN go mod download - -COPY *.go ./ -RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build \ - -ldflags "-X kubevirt.io/csi-driver/pkg/service.VendorVersion=0.2.0" \ - -o kubevirt-csi-driver . +RUN make build FROM quay.io/centos/centos:stream9 +ARG git_url=https://github.com/kubevirt/csi-driver.git -RUN dnf install -y e2fsprogs xfsprogs nfs-utils && dnf clean all - -COPY --from=builder /src/kubevirt-csi-driver . +LABEL maintainers="The KubeVirt Project " \ + description="KubeVirt CSI Driver" \ + multi.GIT_URL=${git_url} ENTRYPOINT ["./kubevirt-csi-driver"] + +RUN dnf install -y e2fsprogs xfsprogs && dnf clean all + +ARG git_sha=NONE +LABEL multi.GIT_SHA=${git_sha} + +COPY --from=builder /src/kubevirt-csi-driver/kubevirt-csi-driver . diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver/controller.go b/packages/apps/kubernetes/images/kubevirt-csi-driver/controller.go deleted file mode 100644 index edddec09..00000000 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver/controller.go +++ /dev/null @@ -1,577 +0,0 @@ -package main - -import ( - "context" - "fmt" - "net/url" - "time" - - csi "github.com/container-storage-interface/spec/lib/go/csi" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/retry" - "k8s.io/klog/v2" - cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" - - kubevirtclient "kubevirt.io/csi-driver/pkg/kubevirt" - "kubevirt.io/csi-driver/pkg/service" - "kubevirt.io/csi-driver/pkg/util" -) - -const ( - nfsVolumeKey = "nfsVolume" - nfsExportKey = "nfsExport" - busParameter = "bus" - serialParameter = "serial" -) - -var ciliumNetworkPolicyGVR = schema.GroupVersionResource{ - Group: "cilium.io", - Version: "v2", - Resource: "ciliumnetworkpolicies", -} - -var _ csi.ControllerServer = &WrappedControllerService{} - -// WrappedControllerService embeds the upstream ControllerService and adds RWX Filesystem (NFS) support. -type WrappedControllerService struct { - *service.ControllerService - infraClient kubernetes.Interface - dynamicClient dynamic.Interface - virtClient kubevirtclient.Client - infraNamespace string - infraClusterLabels map[string]string - storageClassEnforcement util.StorageClassEnforcement -} - -// isRWXFilesystem checks if the volume capabilities request RWX access with filesystem mode. -func isRWXFilesystem(caps []*csi.VolumeCapability) bool { - hasRWX := false - hasMount := false - for _, cap := range caps { - if cap == nil { - continue - } - if cap.GetMount() != nil { - hasMount = true - } - if am := cap.GetAccessMode(); am != nil && am.Mode == csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER { - hasRWX = true - } - } - return hasRWX && hasMount -} - -// CreateVolume intercepts RWX Filesystem requests and creates a DataVolume in the infra -// cluster with AccessMode=RWX and VolumeMode=Filesystem. Upstream rejects RWX+Filesystem, -// so we handle DataVolume creation ourselves. Using DataVolume (not bare PVC) preserves -// compatibility with upstream snapshot and clone operations. -// For all other requests, delegates to upstream. -func (w *WrappedControllerService) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "missing request") - } - if !isRWXFilesystem(req.GetVolumeCapabilities()) { - return w.ControllerService.CreateVolume(ctx, req) - } - - if len(req.GetName()) == 0 { - return nil, status.Error(codes.InvalidArgument, "name missing in request") - } - - // Storage class enforcement - storageClassName := req.Parameters[kubevirtclient.InfraStorageClassNameParameter] - if !w.storageClassEnforcement.AllowAll { - if storageClassName == "" { - if !w.storageClassEnforcement.AllowDefault { - return nil, status.Error(codes.InvalidArgument, "infraStorageclass is not in the allowed list") - } - } else if !util.Contains(w.storageClassEnforcement.AllowList, storageClassName) { - return nil, status.Error(codes.InvalidArgument, "infraStorageclass is not in the allowed list") - } - } - - storageSize := req.GetCapacityRange().GetRequiredBytes() - dvName := req.Name - - // Determine DataVolume source (blank, snapshot, or clone) - source, err := w.determineDvSource(ctx, req) - if err != nil { - return nil, err - } - - // Handle CSI clone: CDI doesn't allow cloning PVCs in use by a pod, - // so use DataSourceRef instead (same approach as upstream) - sourcePVCName := "" - if source.PVC != nil { - sourcePVCName = source.PVC.Name - source = nil - } - - volumeMode := corev1.PersistentVolumeFilesystem - dv := &cdiv1.DataVolume{ - TypeMeta: metav1.TypeMeta{ - Kind: "DataVolume", - APIVersion: cdiv1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: dvName, - Namespace: w.infraNamespace, - Labels: w.infraClusterLabels, - Annotations: map[string]string{ - "cdi.kubevirt.io/storage.deleteAfterCompletion": "false", - "cdi.kubevirt.io/storage.bind.immediate.requested": "true", - }, - }, - Spec: cdiv1.DataVolumeSpec{ - Storage: &cdiv1.StorageSpec{ - AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteMany}, - VolumeMode: &volumeMode, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceStorage: *resource.NewScaledQuantity(storageSize, 0), - }, - }, - }, - Source: source, - }, - } - - if sourcePVCName != "" { - dv.Spec.Storage.DataSourceRef = &corev1.TypedObjectReference{ - Kind: "PersistentVolumeClaim", - Name: sourcePVCName, - } - } - - if storageClassName != "" { - dv.Spec.Storage.StorageClassName = &storageClassName - } - - // Idempotency: check if DataVolume already exists - if existingDv, err := w.virtClient.GetDataVolume(ctx, w.infraNamespace, dvName); errors.IsNotFound(err) { - klog.Infof("Creating NFS DataVolume %s/%s", w.infraNamespace, dvName) - dv, err = w.virtClient.CreateDataVolume(ctx, w.infraNamespace, dv) - if err != nil { - klog.Errorf("Failed creating NFS DataVolume %s: %v", dvName, err) - return nil, err - } - } else if err != nil { - return nil, err - } else { - if existingDv != nil && existingDv.Spec.Storage != nil { - existingRequest := existingDv.Spec.Storage.Resources.Requests[corev1.ResourceStorage] - newRequest := dv.Spec.Storage.Resources.Requests[corev1.ResourceStorage] - if newRequest.Cmp(existingRequest) != 0 { - return nil, status.Error(codes.AlreadyExists, "requested storage size does not match existing size") - } - dv = existingDv - } - } - - serial := string(dv.GetUID()) - - return &csi.CreateVolumeResponse{ - Volume: &csi.Volume{ - CapacityBytes: storageSize, - VolumeId: dvName, - VolumeContext: map[string]string{ - busParameter: "scsi", - serialParameter: serial, - nfsVolumeKey: "true", - }, - ContentSource: req.GetVolumeContentSource(), - }, - }, nil -} - -// determineDvSource determines the DataVolume source from the CSI request content source. -// Mirrors upstream logic for blank, snapshot, and clone sources. -func (w *WrappedControllerService) determineDvSource(ctx context.Context, req *csi.CreateVolumeRequest) (*cdiv1.DataVolumeSource, error) { - res := &cdiv1.DataVolumeSource{} - if req.GetVolumeContentSource() != nil { - source := req.GetVolumeContentSource() - switch source.Type.(type) { - case *csi.VolumeContentSource_Snapshot: - snapshot, err := w.virtClient.GetVolumeSnapshot(ctx, w.infraNamespace, source.GetSnapshot().GetSnapshotId()) - if errors.IsNotFound(err) { - return nil, status.Errorf(codes.NotFound, "source snapshot %s not found", source.GetSnapshot().GetSnapshotId()) - } else if err != nil { - return nil, err - } - if snapshot != nil { - res.Snapshot = &cdiv1.DataVolumeSourceSnapshot{ - Name: snapshot.Name, - Namespace: w.infraNamespace, - } - } - case *csi.VolumeContentSource_Volume: - volume, err := w.virtClient.GetDataVolume(ctx, w.infraNamespace, source.GetVolume().GetVolumeId()) - if errors.IsNotFound(err) { - return nil, status.Errorf(codes.NotFound, "source volume %s not found", source.GetVolume().GetVolumeId()) - } else if err != nil { - return nil, err - } - if volume != nil { - res.PVC = &cdiv1.DataVolumeSourcePVC{ - Name: volume.Name, - Namespace: w.infraNamespace, - } - } - default: - return nil, status.Error(codes.InvalidArgument, "unknown content type") - } - } else { - res.Blank = &cdiv1.DataVolumeBlankImage{} - } - return res, nil -} - -// ControllerPublishVolume for NFS volumes: annotates infra PVC for WFFC binding, -// waits for PVC bound, extracts NFS export from PV, and creates CiliumNetworkPolicy. -// For RWO volumes, delegates to upstream (hotplug SCSI). -func (w *WrappedControllerService) ControllerPublishVolume(ctx context.Context, req *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) { - if req.GetVolumeContext()[nfsVolumeKey] != "true" { - return w.ControllerService.ControllerPublishVolume(ctx, req) - } - - if len(req.GetVolumeId()) == 0 { - return nil, status.Error(codes.InvalidArgument, "volume id missing in request") - } - if len(req.GetNodeId()) == 0 { - return nil, status.Error(codes.InvalidArgument, "node id missing in request") - } - - dvName := req.GetVolumeId() - vmNamespace, vmName, err := cache.SplitMetaNamespaceKey(req.GetNodeId()) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to parse node ID %q: %v", req.GetNodeId(), err) - } - - klog.V(3).Infof("Publishing NFS volume %s to node %s/%s", dvName, vmNamespace, vmName) - - // Get VMI for CiliumNetworkPolicy ownerReference - vmi, err := w.virtClient.GetVirtualMachine(ctx, vmNamespace, vmName) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to get VMI %s/%s: %v", vmNamespace, vmName, err) - } - - // Wait for PVC to be bound (CDI handles immediate binding via annotation) - klog.V(3).Infof("Waiting for PVC %s to be bound", dvName) - if err := wait.PollUntilContextTimeout(ctx, time.Second, 2*time.Minute, true, func(ctx context.Context) (bool, error) { - p, err := w.infraClient.CoreV1().PersistentVolumeClaims(w.infraNamespace).Get(ctx, dvName, metav1.GetOptions{}) - if err != nil { - return false, err - } - return p.Status.Phase == corev1.ClaimBound, nil - }); err != nil { - return nil, status.Errorf(codes.Internal, "timed out waiting for PVC %s to be bound: %v", dvName, err) - } - - // Read PV to get NFS export - pvc, err := w.infraClient.CoreV1().PersistentVolumeClaims(w.infraNamespace).Get(ctx, dvName, metav1.GetOptions{}) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to re-read PVC %s: %v", dvName, err) - } - pv, err := w.infraClient.CoreV1().PersistentVolumes().Get(ctx, pvc.Spec.VolumeName, metav1.GetOptions{}) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to get PV %s: %v", pvc.Spec.VolumeName, err) - } - nfsExport, err := getNFSExport(pv) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to extract NFS export from PV %s: %v", pv.Name, err) - } - klog.V(3).Infof("NFS export for volume %s: %s", dvName, nfsExport) - - // Parse NFS URL for CiliumNetworkPolicy port - _, port, _, err := parseNFSExport(nfsExport) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to parse NFS export URL: %v", err) - } - - // Create or update CiliumNetworkPolicy allowing egress to NFS server - cnpName := fmt.Sprintf("csi-nfs-%s", dvName) - vmiOwnerRef := map[string]interface{}{ - "apiVersion": "kubevirt.io/v1", - "kind": "VirtualMachineInstance", - "name": vmName, - "uid": string(vmi.UID), - } - cnp := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "cilium.io/v2", - "kind": "CiliumNetworkPolicy", - "metadata": map[string]interface{}{ - "name": cnpName, - "namespace": vmNamespace, - "ownerReferences": []interface{}{vmiOwnerRef}, - }, - "spec": map[string]interface{}{ - "endpointSelector": buildEndpointSelector([]string{vmName}), - "egress": []interface{}{ - map[string]interface{}{ - "toEndpoints": []interface{}{ - map[string]interface{}{ - "matchLabels": map[string]interface{}{ - "k8s:app.kubernetes.io/component": "linstor-csi-nfs-server", - "k8s:io.kubernetes.pod.namespace": "cozy-linstor", - }, - }, - }, - "toPorts": []interface{}{ - map[string]interface{}{ - "ports": []interface{}{ - map[string]interface{}{ - "port": port, - "protocol": "TCP", - }, - }, - }, - }, - }, - }, - }, - }, - } - - if _, err := w.dynamicClient.Resource(ciliumNetworkPolicyGVR).Namespace(vmNamespace).Create(ctx, cnp, metav1.CreateOptions{}); err != nil { - if !errors.IsAlreadyExists(err) { - return nil, status.Errorf(codes.Internal, "failed to create CiliumNetworkPolicy %s: %v", cnpName, err) - } - // CNP exists — add ownerReference for this VMI - if err := w.addCNPOwnerReference(ctx, vmNamespace, cnpName, vmiOwnerRef); err != nil { - return nil, err - } - } - - klog.V(3).Infof("Successfully published NFS volume %s", dvName) - return &csi.ControllerPublishVolumeResponse{ - PublishContext: map[string]string{ - nfsExportKey: nfsExport, - }, - }, nil -} - -// ControllerUnpublishVolume for NFS volumes: deletes CiliumNetworkPolicy. -// For RWO volumes, delegates to upstream (hotplug removal). -func (w *WrappedControllerService) ControllerUnpublishVolume(ctx context.Context, req *csi.ControllerUnpublishVolumeRequest) (*csi.ControllerUnpublishVolumeResponse, error) { - dvName := req.GetVolumeId() - - // Determine if NFS by checking infra PVC access modes - pvc, err := w.infraClient.CoreV1().PersistentVolumeClaims(w.infraNamespace).Get(ctx, dvName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return &csi.ControllerUnpublishVolumeResponse{}, nil - } - return nil, err - } - - if !hasRWXAccessMode(pvc) { - return w.ControllerService.ControllerUnpublishVolume(ctx, req) - } - - // NFS volume: remove VMI ownerReference from CiliumNetworkPolicy - vmNamespace, vmName, err := cache.SplitMetaNamespaceKey(req.GetNodeId()) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to parse node ID %q: %v", req.GetNodeId(), err) - } - - cnpName := fmt.Sprintf("csi-nfs-%s", dvName) - klog.V(3).Infof("Removing VMI %s ownerReference from CiliumNetworkPolicy %s/%s", vmName, vmNamespace, cnpName) - if err := w.removeCNPOwnerReference(ctx, vmNamespace, cnpName, vmName); err != nil { - return nil, err - } - - klog.V(3).Infof("Successfully unpublished NFS volume %s", dvName) - return &csi.ControllerUnpublishVolumeResponse{}, nil -} - -// ControllerExpandVolume delegates to upstream for the actual DataVolume/PVC resize. -// For NFS volumes, LINSTOR handles NFS server resize automatically, so no node expansion is needed. -func (w *WrappedControllerService) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) { - resp, err := w.ControllerService.ControllerExpandVolume(ctx, req) - if err != nil { - return nil, err - } - - // For NFS volumes, no node-side expansion is needed - pvc, err := w.infraClient.CoreV1().PersistentVolumeClaims(w.infraNamespace).Get(ctx, req.GetVolumeId(), metav1.GetOptions{}) - if err != nil { - klog.Warningf("Failed to check PVC access mode for %s/%s: %v", w.infraNamespace, req.GetVolumeId(), err) - } else if hasRWXAccessMode(pvc) { - resp.NodeExpansionRequired = false - } - - return resp, nil -} - -// addCNPOwnerReference adds a VMI ownerReference to an existing CiliumNetworkPolicy. -func (w *WrappedControllerService) addCNPOwnerReference(ctx context.Context, namespace, cnpName string, ownerRef map[string]interface{}) error { - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - existing, err := w.dynamicClient.Resource(ciliumNetworkPolicyGVR).Namespace(namespace).Get(ctx, cnpName, metav1.GetOptions{}) - if err != nil { - return status.Errorf(codes.Internal, "failed to get CiliumNetworkPolicy %s: %v", cnpName, err) - } - - ownerRefs, _, _ := unstructured.NestedSlice(existing.Object, "metadata", "ownerReferences") - uid, _, _ := unstructured.NestedString(ownerRef, "uid") - for _, ref := range ownerRefs { - if refMap, ok := ref.(map[string]interface{}); ok { - if refMap["uid"] == uid { - return nil // already present - } - } - } - - ownerRefs = append(ownerRefs, ownerRef) - if err := unstructured.SetNestedSlice(existing.Object, ownerRefs, "metadata", "ownerReferences"); err != nil { - return status.Errorf(codes.Internal, "failed to set ownerReferences: %v", err) - } - - // Rebuild endpointSelector to include all VMs - selector := buildEndpointSelector(vmNamesFromOwnerRefs(ownerRefs)) - if err := unstructured.SetNestedField(existing.Object, selector, "spec", "endpointSelector"); err != nil { - return status.Errorf(codes.Internal, "failed to set endpointSelector: %v", err) - } - - if _, err := w.dynamicClient.Resource(ciliumNetworkPolicyGVR).Namespace(namespace).Update(ctx, existing, metav1.UpdateOptions{}); err != nil { - return err - } - klog.V(3).Infof("Added ownerReference to CiliumNetworkPolicy %s", cnpName) - return nil - }) -} - -// removeCNPOwnerReference removes a VMI ownerReference from a CiliumNetworkPolicy. -// Deletes the CNP if no ownerReferences remain. -func (w *WrappedControllerService) removeCNPOwnerReference(ctx context.Context, namespace, cnpName, vmName string) error { - return retry.RetryOnConflict(retry.DefaultRetry, func() error { - existing, err := w.dynamicClient.Resource(ciliumNetworkPolicyGVR).Namespace(namespace).Get(ctx, cnpName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return nil - } - return status.Errorf(codes.Internal, "failed to get CiliumNetworkPolicy %s: %v", cnpName, err) - } - - ownerRefs, _, _ := unstructured.NestedSlice(existing.Object, "metadata", "ownerReferences") - var remaining []interface{} - for _, ref := range ownerRefs { - if refMap, ok := ref.(map[string]interface{}); ok { - if refMap["name"] == vmName { - continue - } - } - remaining = append(remaining, ref) - } - - if len(remaining) == 0 { - // Last owner — delete CNP - if err := w.dynamicClient.Resource(ciliumNetworkPolicyGVR).Namespace(namespace).Delete(ctx, cnpName, metav1.DeleteOptions{}); err != nil { - if !errors.IsNotFound(err) { - return status.Errorf(codes.Internal, "failed to delete CiliumNetworkPolicy %s: %v", cnpName, err) - } - } - klog.V(3).Infof("Deleted CiliumNetworkPolicy %s (no more owners)", cnpName) - return nil - } - - if err := unstructured.SetNestedSlice(existing.Object, remaining, "metadata", "ownerReferences"); err != nil { - return status.Errorf(codes.Internal, "failed to set ownerReferences: %v", err) - } - - // Rebuild endpointSelector from remaining VMs - selector := buildEndpointSelector(vmNamesFromOwnerRefs(remaining)) - if err := unstructured.SetNestedField(existing.Object, selector, "spec", "endpointSelector"); err != nil { - return status.Errorf(codes.Internal, "failed to set endpointSelector: %v", err) - } - - if _, err := w.dynamicClient.Resource(ciliumNetworkPolicyGVR).Namespace(namespace).Update(ctx, existing, metav1.UpdateOptions{}); err != nil { - return err - } - klog.V(3).Infof("Removed VMI %s ownerReference from CiliumNetworkPolicy %s", vmName, cnpName) - return nil - }) -} - -// buildEndpointSelector returns an endpointSelector using matchExpressions -// so that multiple VMs can be listed in a single selector. -func buildEndpointSelector(vmNames []string) map[string]interface{} { - values := make([]interface{}, len(vmNames)) - for i, name := range vmNames { - values[i] = name - } - return map[string]interface{}{ - "matchExpressions": []interface{}{ - map[string]interface{}{ - "key": "kubevirt.io/vm", - "operator": "In", - "values": values, - }, - }, - } -} - -// vmNamesFromOwnerRefs extracts VM names from ownerReferences. -func vmNamesFromOwnerRefs(ownerRefs []interface{}) []string { - var names []string - for _, ref := range ownerRefs { - if refMap, ok := ref.(map[string]interface{}); ok { - if name, ok := refMap["name"].(string); ok { - names = append(names, name) - } - } - } - return names -} - -func hasRWXAccessMode(pvc *corev1.PersistentVolumeClaim) bool { - for _, mode := range pvc.Spec.AccessModes { - if mode == corev1.ReadWriteMany { - return true - } - } - return false -} - -// getNFSExport extracts the NFS export URL from a PersistentVolume. -// Supports both native NFS PVs and CSI PVs with nfs-export volume attribute. -func getNFSExport(pv *corev1.PersistentVolume) (string, error) { - if pv.Spec.NFS != nil { - return fmt.Sprintf("nfs://%s:2049%s", pv.Spec.NFS.Server, pv.Spec.NFS.Path), nil - } - if pv.Spec.CSI != nil && pv.Spec.CSI.VolumeAttributes != nil { - if export, ok := pv.Spec.CSI.VolumeAttributes["linstor.csi.linbit.com/nfs-export"]; ok { - return export, nil - } - } - return "", fmt.Errorf("no NFS export info found in PV %s", pv.Name) -} - -// parseNFSExport parses an NFS URL of the form nfs://host:port/path. -func parseNFSExport(nfsURL string) (host, port, path string, err error) { - u, err := url.Parse(nfsURL) - if err != nil { - return "", "", "", fmt.Errorf("failed to parse NFS URL %q: %w", nfsURL, err) - } - host = u.Hostname() - port = u.Port() - if port == "" { - port = "2049" - } - path = u.Path - if path == "" { - path = "/" - } - return host, port, path, nil -} diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver/go.mod b/packages/apps/kubernetes/images/kubevirt-csi-driver/go.mod deleted file mode 100644 index 96a96107..00000000 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver/go.mod +++ /dev/null @@ -1,101 +0,0 @@ -module cozystack.io/kubevirt-csi-driver - -go 1.22.0 - -toolchain go1.22.5 - -require ( - github.com/container-storage-interface/spec v1.10.0 - google.golang.org/grpc v1.65.0 - gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.31.4 - k8s.io/apimachinery v0.31.4 - k8s.io/client-go v12.0.0+incompatible - k8s.io/klog/v2 v2.130.1 - k8s.io/mount-utils v0.33.1 - kubevirt.io/containerized-data-importer-api v1.59.0 - kubevirt.io/csi-driver v0.0.0-20250702202414-a8d6605bc999 -) - -require ( - github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/imdario/mergo v0.3.15 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/kubernetes-csi/csi-lib-utils v0.18.1 // indirect - github.com/kubernetes-csi/external-snapshotter/client/v6 v6.3.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/moby/sys/mountinfo v0.7.1 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/opencontainers/runc v1.1.13 // indirect - github.com/opencontainers/runtime-spec v1.0.3-0.20220909204839-494a5a6aca78 // indirect - github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 // indirect - github.com/openshift/custom-resource-status v1.1.2 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/x448/float16 v0.8.4 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.3.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.26.4 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - kubevirt.io/api v1.2.2 // indirect - kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect -) - -replace ( - k8s.io/api => k8s.io/api v0.31.4 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.31.4 - k8s.io/apimachinery => k8s.io/apimachinery v0.31.4 - k8s.io/apiserver => k8s.io/apiserver v0.31.4 - k8s.io/cli-runtime => k8s.io/cli-runtime v0.31.4 - k8s.io/client-go => k8s.io/client-go v0.31.4 - k8s.io/cloud-provider => k8s.io/cloud-provider v0.31.4 - k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.31.4 - k8s.io/code-generator => k8s.io/code-generator v0.31.4 - k8s.io/component-base => k8s.io/component-base v0.31.4 - k8s.io/component-helpers => k8s.io/component-helpers v0.31.4 - k8s.io/controller-manager => k8s.io/controller-manager v0.31.4 - k8s.io/cri-api => k8s.io/cri-api v0.31.4 - k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.31.4 - k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.31.4 - k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.31.4 - k8s.io/kube-proxy => k8s.io/kube-proxy v0.31.4 - k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.31.4 - k8s.io/kubectl => k8s.io/kubectl v0.31.4 - k8s.io/kubelet => k8s.io/kubelet v0.31.4 - k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.31.4 - k8s.io/metrics => k8s.io/metrics v0.31.4 - k8s.io/mount-utils => k8s.io/mount-utils v0.31.4 - k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.31.4 - k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.31.4 - kubevirt.io/csi-driver => github.com/kubevirt/csi-driver v0.0.0-20250702202414-a8d6605bc999 -) diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver/go.sum b/packages/apps/kubernetes/images/kubevirt-csi-driver/go.sum deleted file mode 100644 index a0c4ac81..00000000 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver/go.sum +++ /dev/null @@ -1,543 +0,0 @@ -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= -github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= -github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/container-storage-interface/spec v1.10.0 h1:YkzWPV39x+ZMTa6Ax2czJLLwpryrQ+dPesB34mrRMXA= -github.com/container-storage-interface/spec v1.10.0/go.mod h1:DtUvaQszPml1YJfIK7c00mlv6/g4wNMLanLgiUbKFRI= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kubernetes-csi/csi-lib-utils v0.18.1 h1:vpg1kbQ6lFVCz7mY71zcqVE7W0GAQXXBoFfHvbW3gdw= -github.com/kubernetes-csi/csi-lib-utils v0.18.1/go.mod h1:PIcn27zmbY0KBue4JDdZVfDF56tjcS3jKroZPi+pMoY= -github.com/kubernetes-csi/external-snapshotter/client/v6 v6.3.0 h1:qS4r4ljINLWKJ9m9Ge3Q3sGZ/eIoDVDT2RhAdQFHb1k= -github.com/kubernetes-csi/external-snapshotter/client/v6 v6.3.0/go.mod h1:oGXx2XTEzs9ikW2V6IC1dD8trgjRsS/Mvc2JRiC618Y= -github.com/kubevirt/csi-driver v0.0.0-20250702202414-a8d6605bc999 h1:nq11swNPIRarVZm/YTOWh9rbuEqivgpA1c4RUEFSL90= -github.com/kubevirt/csi-driver v0.0.0-20250702202414-a8d6605bc999/go.mod h1:Pzl14YlqPpoK/ZdS79tUSuHbC2L/NPqOIjFTN5kTmUg= -github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= -github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= -github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= -github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= -github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= -github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= -github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= -github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= -github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs= -github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA= -github.com/opencontainers/runtime-spec v1.0.3-0.20220909204839-494a5a6aca78 h1:R5M2qXZiK/mWPMT4VldCOiSL9HIAMuxQZWdG0CSM5+4= -github.com/opencontainers/runtime-spec v1.0.3-0.20220909204839-494a5a6aca78/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 h1:t/CahSnpqY46sQR01SoS+Jt0jtjgmhgE6lFmRnO4q70= -github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k= -github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= -github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= -github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.4 h1:I2QNzitPVsPeLQvexMEsj945QumYraqv9m74isPDKhM= -k8s.io/api v0.31.4/go.mod h1:d+7vgXLvmcdT1BCo79VEgJxHHryww3V5np2OYTr6jdw= -k8s.io/apiextensions-apiserver v0.31.4 h1:FxbqzSvy92Ca9DIs5jqot883G0Ln/PGXfm/07t39LS0= -k8s.io/apiextensions-apiserver v0.31.4/go.mod h1:hIW9YU8UsqZqIWGG99/gsdIU0Ar45Qd3A12QOe/rvpg= -k8s.io/apimachinery v0.31.4 h1:8xjE2C4CzhYVm9DGf60yohpNUh5AEBnPxCryPBECmlM= -k8s.io/apimachinery v0.31.4/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.4 h1:t4QEXt4jgHIkKKlx06+W3+1JOwAFU/2OPiOo7H92eRQ= -k8s.io/client-go v0.31.4/go.mod h1:kvuMro4sFYIa8sulL5Gi5GFqUPvfH2O/dXuKstbaaeg= -k8s.io/code-generator v0.31.4/go.mod h1:yMDt13Kn7m4MMZ4LxB1KBzdZjEyxzdT4b4qXq+lnI90= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/mount-utils v0.31.4 h1:9aWJ5BpJvs6fdIo36wWIuCC6ZMNllUT0JSFsVNJloFI= -k8s.io/mount-utils v0.31.4/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -kubevirt.io/api v1.2.2 h1:PeA937vsZawmKAsiiDQZJ/BbGH4OhEWsIzWrCNfmYXk= -kubevirt.io/api v1.2.2/go.mod h1:SbeR9ma4EwnaOZEUkh/lNz0kzYm5LPpEDE30vKXC5Zg= -kubevirt.io/containerized-data-importer-api v1.59.0 h1:GdDt9BlR0qHejpMaPfASbsG8JWDmBf1s7xZBj5W9qn0= -kubevirt.io/containerized-data-importer-api v1.59.0/go.mod h1:4yOGtCE7HvgKp7wftZZ3TBvDJ0x9d6N6KaRjRYcUFpE= -kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= -kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver/main.go b/packages/apps/kubernetes/images/kubevirt-csi-driver/main.go deleted file mode 100644 index 396cee42..00000000 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver/main.go +++ /dev/null @@ -1,219 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "os" - "strings" - - csi "github.com/container-storage-interface/spec/lib/go/csi" - "gopkg.in/yaml.v2" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/dynamic" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - klog "k8s.io/klog/v2" - mount "k8s.io/mount-utils" - - snapcli "kubevirt.io/csi-driver/pkg/generated/external-snapshotter/client-go/clientset/versioned" - "kubevirt.io/csi-driver/pkg/kubevirt" - "kubevirt.io/csi-driver/pkg/service" - "kubevirt.io/csi-driver/pkg/util" -) - -var ( - endpoint = flag.String("endpoint", "unix:/csi/csi.sock", "CSI endpoint") - nodeName = flag.String("node-name", "", "The node name - the node this pods runs on") - infraClusterNamespace = flag.String("infra-cluster-namespace", "", "The infra-cluster namespace") - infraClusterKubeconfig = flag.String("infra-cluster-kubeconfig", "", "the infra-cluster kubeconfig file. If not set, defaults to in cluster config.") - infraClusterLabels = flag.String("infra-cluster-labels", "", "The infra-cluster labels to use when creating resources in infra cluster. 'name=value' fields separated by a comma") - volumePrefix = flag.String("volume-prefix", "pvc", "The prefix expected for persistent volumes") - - infraStorageClassEnforcement = os.Getenv("INFRA_STORAGE_CLASS_ENFORCEMENT") - - tenantClusterKubeconfig = flag.String("tenant-cluster-kubeconfig", "", "the tenant cluster kubeconfig file. If not set, defaults to in cluster config.") - - runNodeService = flag.Bool("run-node-service", true, "Specifies rather or not to run the node service, the default is true") - runControllerService = flag.Bool("run-controller-service", true, "Specifies rather or not to run the controller service, the default is true") -) - -func init() { - klog.InitFlags(nil) -} - -func main() { - flag.Parse() - handle() - os.Exit(0) -} - -func handle() { - var tenantRestConfig *rest.Config - var infraRestConfig *rest.Config - var identityClientset *kubernetes.Clientset - - if service.VendorVersion == "" { - klog.Fatal("VendorVersion must be set at compile time") - } - klog.V(2).Infof("Driver vendor %v %v", service.VendorName, service.VendorVersion) - - if (infraClusterLabels == nil || *infraClusterLabels == "") && *runControllerService { - klog.Fatal("infra-cluster-labels must be set") - } - if volumePrefix == nil || *volumePrefix == "" { - klog.Fatal("volume-prefix must be set") - } - - inClusterConfig, err := rest.InClusterConfig() - if err != nil { - klog.Fatalf("Failed to build in cluster config: %v", err) - } - - if *tenantClusterKubeconfig != "" { - tenantRestConfig, err = clientcmd.BuildConfigFromFlags("", *tenantClusterKubeconfig) - if err != nil { - klog.Fatalf("failed to build tenant cluster config: %v", err) - } - } else { - tenantRestConfig = inClusterConfig - } - - if *infraClusterKubeconfig != "" { - infraRestConfig, err = clientcmd.BuildConfigFromFlags("", *infraClusterKubeconfig) - if err != nil { - klog.Fatalf("failed to build infra cluster config: %v", err) - } - } else { - infraRestConfig = inClusterConfig - } - - tenantClientSet, err := kubernetes.NewForConfig(tenantRestConfig) - if err != nil { - klog.Fatalf("Failed to build tenant client set: %v", err) - } - tenantSnapshotClientSet, err := snapcli.NewForConfig(tenantRestConfig) - if err != nil { - klog.Fatalf("Failed to build tenant snapshot client set: %v", err) - } - - infraClusterLabelsMap := parseLabels() - klog.V(5).Infof("Storage class enforcement string: \n%s", infraStorageClassEnforcement) - storageClassEnforcement := configureStorageClassEnforcement(infraStorageClassEnforcement) - - virtClient, err := kubevirt.NewClient(infraRestConfig, infraClusterLabelsMap, tenantClientSet, tenantSnapshotClientSet, storageClassEnforcement, *volumePrefix) - if err != nil { - klog.Fatal(err) - } - - var nodeID string - if *nodeName != "" { - node, err := tenantClientSet.CoreV1().Nodes().Get(context.TODO(), *nodeName, v1.GetOptions{}) - if err != nil { - klog.Fatal(fmt.Errorf("failed to find node by name %v: %v", *nodeName, err)) - } - if node.Spec.ProviderID == "" { - klog.Fatal("provider name missing from node, something's not right") - } - vmName := strings.TrimPrefix(node.Spec.ProviderID, `kubevirt://`) - vmNamespace, ok := node.Annotations["cluster.x-k8s.io/cluster-namespace"] - if !ok { - klog.Fatal("cannot infer infra vm namespace") - } - nodeID = fmt.Sprintf("%s/%s", vmNamespace, vmName) - klog.Infof("Node name: %v, Node ID: %s", *nodeName, nodeID) - } - - identityClientset = tenantClientSet - if *runControllerService { - identityClientset, err = kubernetes.NewForConfig(infraRestConfig) - if err != nil { - klog.Fatalf("Failed to build infra client set: %v", err) - } - } - - // Create upstream driver (provides Identity, Controller, Node services) - upstreamDriver := service.NewKubevirtCSIDriver(virtClient, - identityClientset, - *infraClusterNamespace, - infraClusterLabelsMap, - storageClassEnforcement, - nodeID, - *runNodeService, - *runControllerService) - - // Wrap controller and node services with NFS/RWX support - var cs csi.ControllerServer - if *runControllerService { - infraKubernetesClient, err := kubernetes.NewForConfig(infraRestConfig) - if err != nil { - klog.Fatalf("Failed to build infra kubernetes client: %v", err) - } - infraDynamicClient, err := dynamic.NewForConfig(infraRestConfig) - if err != nil { - klog.Fatalf("Failed to build infra dynamic client: %v", err) - } - cs = &WrappedControllerService{ - ControllerService: upstreamDriver.ControllerService, - infraClient: infraKubernetesClient, - dynamicClient: infraDynamicClient, - virtClient: virtClient, - infraNamespace: *infraClusterNamespace, - infraClusterLabels: infraClusterLabelsMap, - storageClassEnforcement: storageClassEnforcement, - } - } - - var ns csi.NodeServer - if *runNodeService { - ns = &WrappedNodeService{ - NodeService: upstreamDriver.NodeService, - mounter: mount.New(""), - } - } - - // Run gRPC server with upstream Identity + wrapped Controller/Node - s := service.NewNonBlockingGRPCServer() - s.Start(*endpoint, upstreamDriver.IdentityService, cs, ns) - s.Wait() -} - -func configureStorageClassEnforcement(infraStorageClassEnforcement string) util.StorageClassEnforcement { - var storageClassEnforcement util.StorageClassEnforcement - - if infraStorageClassEnforcement == "" { - storageClassEnforcement = util.StorageClassEnforcement{ - AllowAll: true, - AllowDefault: true, - } - } else { - err := yaml.Unmarshal([]byte(infraStorageClassEnforcement), &storageClassEnforcement) - if err != nil { - klog.Fatalf("Failed to parse infra-storage-class-enforcement %v", err) - } - } - return storageClassEnforcement -} - -func parseLabels() map[string]string { - infraClusterLabelsMap := map[string]string{} - - if *infraClusterLabels == "" { - return infraClusterLabelsMap - } - - labelStrings := strings.Split(*infraClusterLabels, ",") - - for _, label := range labelStrings { - labelPair := strings.SplitN(label, "=", 2) - - if len(labelPair) != 2 { - klog.Fatal("Bad labels format. Should be 'key=value,key=value,...'") - } - - infraClusterLabelsMap[labelPair[0]] = labelPair[1] - } - - return infraClusterLabelsMap -} diff --git a/packages/apps/kubernetes/images/kubevirt-csi-driver/node.go b/packages/apps/kubernetes/images/kubevirt-csi-driver/node.go deleted file mode 100644 index a367f27f..00000000 --- a/packages/apps/kubernetes/images/kubevirt-csi-driver/node.go +++ /dev/null @@ -1,161 +0,0 @@ -package main - -import ( - "context" - "fmt" - "os" - "path/filepath" - - csi "github.com/container-storage-interface/spec/lib/go/csi" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "k8s.io/klog/v2" - mount "k8s.io/mount-utils" - - "kubevirt.io/csi-driver/pkg/service" -) - -var _ csi.NodeServer = &WrappedNodeService{} - -// WrappedNodeService embeds the upstream NodeService and adds NFS mount support. -type WrappedNodeService struct { - *service.NodeService - mounter mount.Interface -} - -// NodeStageVolume for NFS volumes is a no-op (NFS doesn't need staging). -// For RWO volumes, delegates to upstream (lsblk + mkfs). -func (w *WrappedNodeService) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) { - if req.GetPublishContext()[nfsExportKey] != "" { - klog.V(3).Infof("NFS volume %s: skipping stage", req.GetVolumeId()) - return &csi.NodeStageVolumeResponse{}, nil - } - return w.NodeService.NodeStageVolume(ctx, req) -} - -// NodePublishVolume for NFS volumes: mounts the /data subdir of the NFS export -// at the target path, hiding internal artifacts (disk.img, lost+found). -// For RWO volumes, delegates to upstream (mount block device). -func (w *WrappedNodeService) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) { - nfsExport := req.GetPublishContext()[nfsExportKey] - if nfsExport == "" { - return w.NodeService.NodePublishVolume(ctx, req) - } - - klog.V(3).Infof("Publishing NFS volume %s at %s", req.GetVolumeId(), req.GetTargetPath()) - - host, port, path, err := parseNFSExport(nfsExport) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to parse NFS export: %v", err) - } - - targetPath := req.GetTargetPath() - - // Check if already mounted - notMnt, err := w.mounter.IsLikelyNotMountPoint(targetPath) - if err != nil { - if !os.IsNotExist(err) { - return nil, status.Errorf(codes.Internal, "failed to check mount point %s: %v", targetPath, err) - } - if err := os.MkdirAll(targetPath, 0750); err != nil { - return nil, status.Errorf(codes.Internal, "failed to create target path %s: %v", targetPath, err) - } - notMnt = true - } - if !notMnt { - klog.V(3).Infof("NFS volume %s already mounted at %s", req.GetVolumeId(), targetPath) - return &csi.NodePublishVolumeResponse{}, nil - } - - mountOptions := []string{ - "nfsvers=4.2", - fmt.Sprintf("port=%s", port), - } - if req.GetReadonly() { - mountOptions = append(mountOptions, "ro") - } - - // Temp-mount the NFS root to ensure /data subdir exists and migrate any - // user files that were written before this fix (backward compatibility). - tmpMount, err := os.MkdirTemp("", fmt.Sprintf("nfs-init-%s-", req.GetVolumeId())) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to create temp mount dir: %v", err) - } - defer os.Remove(tmpMount) - - rootSource := fmt.Sprintf("%s:%s", host, path) - rootOpts := []string{"nfsvers=4.2", fmt.Sprintf("port=%s", port)} - if err := w.mounter.Mount(rootSource, tmpMount, "nfs", rootOpts); err != nil { - return nil, status.Errorf(codes.Internal, "NFS temp mount failed: %v", err) - } - defer func() { - if err := w.mounter.Unmount(tmpMount); err != nil { - klog.Warningf("Failed to unmount temp dir %s: %v", tmpMount, err) - } - }() - - dataDir := filepath.Join(tmpMount, "data") - if err := os.MkdirAll(dataDir, 0777); err != nil { - return nil, status.Errorf(codes.Internal, "failed to create /data subdir: %v", err) - } - - // Auto-migrate: move user files from root into /data (skip internal artifacts). - // Fail the publish if migration cannot complete to avoid hiding user data. - entries, err := os.ReadDir(tmpMount) - if err != nil { - return nil, status.Errorf(codes.Internal, "failed to read NFS root for migration (volume %s): %v", req.GetVolumeId(), err) - } - for _, entry := range entries { - name := entry.Name() - if name == "data" || name == "disk.img" || name == "lost+found" { - continue - } - src := filepath.Join(tmpMount, name) - dst := filepath.Join(dataDir, name) - if _, err := os.Stat(dst); err == nil { - continue // already exists in /data, skip - } - klog.Infof("Migrating %s to /data/%s for volume %s", name, name, req.GetVolumeId()) - if err := os.Rename(src, dst); err != nil { - if os.IsNotExist(err) { - continue // benign: concurrent publish already moved it - } - return nil, status.Errorf(codes.Internal, "failed to migrate %s for volume %s: %v", name, req.GetVolumeId(), err) - } - } - - // Mount only the /data subdir at the pod's target path. - dataSource := fmt.Sprintf("%s:%s/data", host, path) - klog.V(3).Infof("Mounting NFS %s at %s with options %v", dataSource, targetPath, mountOptions) - if err := w.mounter.Mount(dataSource, targetPath, "nfs", mountOptions); err != nil { - return nil, status.Errorf(codes.Internal, "NFS mount of %s at %s failed: %v", dataSource, targetPath, err) - } - - return &csi.NodePublishVolumeResponse{}, nil -} - -// NodeExpandVolume for NFS volumes is a no-op (LINSTOR handles NFS resize automatically). -// This should not normally be called for NFS since ControllerExpandVolume returns -// NodeExpansionRequired=false, but we handle it gracefully as a safety net. -func (w *WrappedNodeService) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { - if isNFSMount(req.GetVolumePath(), w.mounter) { - klog.V(3).Infof("NFS volume %s: skipping node expansion", req.GetVolumeId()) - return &csi.NodeExpandVolumeResponse{}, nil - } - return w.NodeService.NodeExpandVolume(ctx, req) -} - -// isNFSMount checks if the given path is an NFS mount point. -func isNFSMount(path string, m mount.Interface) bool { - mountPoints, err := m.List() - if err != nil { - klog.Warningf("Failed to list mount points: %v", err) - return false - } - for _, mp := range mountPoints { - if mp.Path == path && (mp.Type == "nfs" || mp.Type == "nfs4") { - return true - } - } - return false -} diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tag b/packages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tag deleted file mode 100644 index f49fffe6..00000000 --- a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.30.tag +++ /dev/null @@ -1 +0,0 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.30@sha256:f460ed1fd5a721aed423e6c3b8be0105d7f693cd86ad992d9c15fd4b27e58cec diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tag b/packages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tag deleted file mode 100644 index b5bdc79a..00000000 --- a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.31.tag +++ /dev/null @@ -1 +0,0 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.31@sha256:aaa2dfa8ee53ae26295f44d2491330f51412457bbe4aa6ba256297cc0bd8a0da diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tag b/packages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tag deleted file mode 100644 index ca285644..00000000 --- a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.32.tag +++ /dev/null @@ -1 +0,0 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.32@sha256:7acb4728ef6b9c0ff3344bf486bb00f2a083f2098452344a362242235013db01 diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tag b/packages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tag deleted file mode 100644 index bb58690a..00000000 --- a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.33.tag +++ /dev/null @@ -1 +0,0 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:a2024339ab9edb980a96b43ad2744b7aa31afaef0983ddbc6a546068b4cfa87a diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tag b/packages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tag deleted file mode 100644 index 36eed7a7..00000000 --- a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.34.tag +++ /dev/null @@ -1 +0,0 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.34@sha256:97bcf946a5687889c6a421d14e5adece11f0978151b2165dc87b28f77f7607db diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tag b/packages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tag deleted file mode 100644 index faae83d2..00000000 --- a/packages/apps/kubernetes/images/ubuntu-container-disk-v1.35.tag +++ /dev/null @@ -1 +0,0 @@ -ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.35@sha256:364c6d454891f1eb1a598fddb69cf328a14dbc451a8ac65812b038a7756da60a diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.tag b/packages/apps/kubernetes/images/ubuntu-container-disk.tag new file mode 100644 index 00000000..930a3fd2 --- /dev/null +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.tag @@ -0,0 +1 @@ +ghcr.io/cozystack/cozystack/ubuntu-container-disk:v1.33@sha256:71a74ca30f75967bae309be2758f19aa3d37c60b19426b9b622ff1c33a80362f diff --git a/packages/apps/kubernetes/templates/_helpers.tpl b/packages/apps/kubernetes/templates/_helpers.tpl index 40a8ae7a..36c06b64 100644 --- a/packages/apps/kubernetes/templates/_helpers.tpl +++ b/packages/apps/kubernetes/templates/_helpers.tpl @@ -49,52 +49,3 @@ Selector labels app.kubernetes.io/name: {{ include "kubernetes.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} - -{{/* -wait-for-kubeconfig init container shared by the control-plane-side -Deployments (cluster-autoscaler, kccm, kcsi-controller) that mount the -*-admin-kubeconfig Secret provisioned asynchronously by Kamaji. The -Secret volume is declared optional so kubelet does not FailedMount while -Kamaji is still bootstrapping; this container polls the mounted path and -exits only when super-admin.svc appears, which happens after kubelet's -optional-Secret refresh cycle. - -The 10m deadline stays strictly below the 15m HelmRelease -Install.Timeout set by cozystack-api for the Kubernetes kind (via the -release.cozystack.io/helm-install-timeout annotation) so the -CrashLoopBackOff surfaces before flux remediation fires and uninstalls -the Cluster CR. - -The default image lives in images/busybox.tag and points directly at -docker.io by digest (not mirrored to ghcr.io like the other .tag files -here): the payload is a one-shot sh loop and the digest pin makes the -pull immutable. Operators in air-gapped or rate-limited environments -can override it via .Values.images.waitForKubeconfig (any registry -reference kubelet can pull). When the value is empty the chart falls -back to the bundled digest pin, preserving the prior default. - -Call site owns the surrounding volumes block; the kubeconfig volume -must exist on the pod and mount at /etc/kubernetes/kubeconfig. -*/}} -{{- define "kubernetes.waitForAdminKubeconfig" -}} -- name: wait-for-kubeconfig - image: "{{ default (.Files.Get "images/busybox.tag" | trim) .Values.images.waitForKubeconfig }}" - command: - - sh - - -c - - | - set -eu - deadline=$(( $(date +%s) + 600 )) - until [ -s /etc/kubernetes/kubeconfig/super-admin.svc ]; do - if [ "$(date +%s)" -ge "$deadline" ]; then - echo "admin kubeconfig was not provisioned within 10m; exiting so the pod goes CrashLoopBackOff and surfaces in dashboards" >&2 - exit 1 - fi - echo "waiting for admin kubeconfig (provisioned by Kamaji, visible after kubelet Secret refresh)..." - sleep 5 - done - volumeMounts: - - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true -{{- end }} diff --git a/packages/apps/kubernetes/templates/_versions.tpl b/packages/apps/kubernetes/templates/_versions.tpl index 403caff1..fcd4cee1 100644 --- a/packages/apps/kubernetes/templates/_versions.tpl +++ b/packages/apps/kubernetes/templates/_versions.tpl @@ -5,10 +5,3 @@ {{- end }} {{- index $versionMap .Values.version }} {{- end }} - -{{- define "kubernetes.konnectivityVersion" }} -{{- $konnVersionMap := .Files.Get "files/konnectivity-versions.yaml" | fromYaml }} -{{- if hasKey $konnVersionMap .Values.version }} -{{- index $konnVersionMap .Values.version }} -{{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml index 298d86db..a00e0155 100644 --- a/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml +++ b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml @@ -1,14 +1,3 @@ -{{- /* - Gate the control-plane-side workloads on the parent tenant having an etcd - DataStore. Without it no KamajiControlPlane is ever created, Kamaji never - provisions -admin-kubeconfig, and rendering these Deployments would cause - the wait-for-kubeconfig init to CrashLoopBackOff indefinitely, consuming - the parent HelmRelease install timeout and triggering the very uninstall - remediation cycle this chart is supposed to avoid. Rendering them only - when $etcd is set keeps the HelmRelease Ready while flux retries on its - interval and picks up the DataStore as soon as the Tenant chart finishes. -*/}} -{{- if .Values._namespace.etcd }} --- apiVersion: apps/v1 kind: Deployment @@ -34,8 +23,6 @@ spec: - key: node-role.kubernetes.io/control-plane operator: Exists effect: "NoSchedule" - initContainers: - {{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }} containers: - image: "{{ $.Files.Get "images/cluster-autoscaler.tag" | trim }}" name: cluster-autoscaler @@ -69,7 +56,6 @@ spec: name: cloud-config - secret: secretName: {{ .Release.Name }}-admin-kubeconfig - optional: true name: kubeconfig serviceAccountName: {{ .Release.Name }}-cluster-autoscaler terminationGracePeriodSeconds: 10 @@ -119,4 +105,3 @@ rules: - list - update - watch -{{- end }} diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index e1494e64..3d9c854a 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -1,15 +1,4 @@ {{- $etcd := .Values._namespace.etcd }} -{{- /* - When $etcd is empty, the parent Tenant application has not populated - _namespace.etcd in cozystack-values yet - either the operator forgot to - set etcd: true on an ancestor Tenant, or the Tenant HelmRelease is still - reconciling. Either way, rendering a KamajiControlPlane with an empty - dataStoreName would be rejected by Kamaji's admission webhook and the - HelmRelease would fail to install, triggering remediation. Instead, emit - a single ConfigMap as a user-visible status beacon and skip the rest so - flux marks the HelmRelease Ready and retries its 5m reconcile loop until - the Tenant chart catches up. -*/}} {{- $ingress := .Values._namespace.ingress }} {{- $host := .Values._namespace.host }} {{- $kubevirtmachinetemplateNames := list }} @@ -81,13 +70,11 @@ spec: memory: guest: {{ .group.resources.memory }} {{- end }} - resources: - {{- include "cozy-lib.resources.sanitize" (list (dict "ephemeral-storage" .group.ephemeralStorage) $) | nindent 14 }} evictionStrategy: External volumes: - name: system containerDisk: - image: "{{ $.Files.Get (printf "images/ubuntu-container-disk-%s.tag" $.Values.version) | trim }}" + image: "{{ $.Files.Get "images/ubuntu-container-disk.tag" | trim }}" - name: ephemeral emptyDisk: capacity: {{ .group.ephemeralStorage | default "20Gi" }} @@ -95,26 +82,6 @@ spec: - name: default pod: {} {{- end }} -{{- if not $etcd }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Release.Name }}-awaiting-etcd - namespace: {{ .Release.Namespace }} - labels: - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/name: kubernetes - app.kubernetes.io/instance: {{ .Release.Name }} -data: - status: "awaiting-etcd" - message: | - No DataStore is available for this tenant Kubernetes cluster. The parent - Tenant application has not populated _namespace.etcd. Set spec.etcd: true - on an ancestor Tenant (usually tenant-root) and wait for its HelmRelease - to reconcile - this HelmRelease will pick up the DataStore on its next - 5m reconcile loop and provision the cluster. -{{- else }} --- apiVersion: cluster.x-k8s.io/v1beta1 kind: Cluster @@ -159,16 +126,8 @@ spec: dataStoreName: "{{ $etcd }}" addons: konnectivity: - {{- $konnVersion := include "kubernetes.konnectivityVersion" $ | trim }} - {{- if $konnVersion }} - agent: - version: {{ $konnVersion }} - {{- end }} server: port: 8132 - {{- if $konnVersion }} - version: {{ $konnVersion }} - {{- end }} resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.controlPlane.konnectivity.server.resourcesPreset .Values.controlPlane.konnectivity.server.resources $) | nindent 10 }} kubelet: cgroupfs: systemd @@ -282,9 +241,6 @@ spec: joinConfiguration: nodeRegistration: kubeletExtraArgs: {} - # Ignore this for 1.31 - ignorePreflightErrors: - - FileExisting-conntrack discovery: bootstrapToken: apiServerEndpoint: {{ $.Release.Name }}.{{ $.Release.Namespace }}.svc:6443 @@ -435,4 +391,3 @@ metadata: spec: {{- .spec | toYaml | nindent 2 }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/csi/deploy.yaml b/packages/apps/kubernetes/templates/csi/deploy.yaml index de62104c..b79a6d64 100644 --- a/packages/apps/kubernetes/templates/csi/deploy.yaml +++ b/packages/apps/kubernetes/templates/csi/deploy.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} kind: Deployment apiVersion: apps/v1 metadata: @@ -25,8 +24,6 @@ spec: - key: node-role.kubernetes.io/control-plane operator: Exists effect: "NoSchedule" - initContainers: - {{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }} containers: - name: csi-driver imagePullPolicy: Always @@ -35,7 +32,6 @@ spec: - "--endpoint=$(CSI_ENDPOINT)" - "--infra-cluster-namespace=$(INFRACLUSTER_NAMESPACE)" - "--infra-cluster-labels=$(INFRACLUSTER_LABELS)" - - "--run-node-service=false" - "--v=5" ports: - name: healthz @@ -237,6 +233,4 @@ spec: emptyDir: {} - secret: secretName: {{ .Release.Name }}-admin-kubeconfig - optional: true name: kubeconfig -{{- end }} diff --git a/packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml b/packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml index fb11ab25..793871d2 100644 --- a/packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml +++ b/packages/apps/kubernetes/templates/csi/infra-cluster-service-account.yaml @@ -24,9 +24,6 @@ rules: - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "patch"] -- apiGroups: ["cilium.io"] - resources: ["ciliumnetworkpolicies"] - verbs: ["get", "create", "update", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml index fd9dac7e..be07a8b9 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager-crds.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.certManager.enabled .Values._namespace.etcd }} +{{- if .Values.addons.certManager.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml index 700b666e..991ed70f 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cert-manager.yaml @@ -1,14 +1,4 @@ -{{- define "cozystack.defaultCertManagerValues" -}} -{{- if $.Values.addons.gatewayAPI.enabled }} -cert-manager: - config: - apiVersion: controller.config.cert-manager.io/v1alpha1 - kind: ControllerConfiguration - enableGatewayAPI: true -{{- end }} -{{- end }} - -{{- if and .Values.addons.certManager.enabled .Values._namespace.etcd }} +{{- if .Values.addons.certManager.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -39,8 +29,11 @@ spec: force: true remediation: retries: -1 + {{- with .Values.addons.certManager.valuesOverride }} values: - {{- toYaml (deepCopy .Values.addons.certManager.valuesOverride | mergeOverwrite (fromYaml (include "cozystack.defaultCertManagerValues" .))) | nindent 4 }} + {{- toYaml . | nindent 4 }} + {{- end }} + dependsOn: {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} - name: {{ .Release.Name }} diff --git a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml index d8c90cbf..64027e94 100644 --- a/packages/apps/kubernetes/templates/helmreleases/cilium.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/cilium.yaml @@ -3,7 +3,6 @@ cilium: k8sServiceHost: {{ .Release.Name }}.{{ .Release.Namespace }}.svc k8sServicePort: 6443 routingMode: tunnel - MTU: 1350 enableIPv4Masquerade: true ipv4NativeRoutingCIDR: "" {{- if $.Values.addons.gatewayAPI.enabled }} @@ -14,7 +13,6 @@ cilium: {{- end }} {{- end }} -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -56,4 +54,3 @@ spec: - name: {{ .Release.Name }}-gateway-api-crds namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/coredns.yaml b/packages/apps/kubernetes/templates/helmreleases/coredns.yaml index 0711a51d..bdb6c682 100644 --- a/packages/apps/kubernetes/templates/helmreleases/coredns.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/coredns.yaml @@ -4,7 +4,6 @@ coredns: clusterIP: "10.95.0.10" {{- end }} -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -43,4 +42,3 @@ spec: {{- end }} - name: {{ .Release.Name }}-cilium namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/csi.yaml b/packages/apps/kubernetes/templates/helmreleases/csi.yaml index 109d78e1..dd2c69a6 100644 --- a/packages/apps/kubernetes/templates/helmreleases/csi.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/csi.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -40,4 +39,3 @@ spec: - name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml index 25fff01c..76499dfe 100644 --- a/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/fluxcd.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.fluxcd.enabled .Values._namespace.etcd }} +{{- if .Values.addons.fluxcd.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml index b4172ed1..2bcc8d4d 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gateway-api-crds.yaml @@ -1,4 +1,4 @@ -{{- if and $.Values.addons.gatewayAPI.enabled $.Values._namespace.etcd }} +{{- if $.Values.addons.gatewayAPI.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml index 655dc868..5ef48912 100644 --- a/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/gpu-operator.yaml @@ -1,12 +1,4 @@ -{{- define "cozystack.defaultGpuOperatorValues" -}} -{{- if .Values.addons.hami.enabled }} -gpu-operator: - devicePlugin: - enabled: false -{{- end }} -{{- end }} - -{{- if and .Values.addons.gpuOperator.enabled .Values._namespace.etcd }} +{{- if .Values.addons.gpuOperator.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -37,12 +29,9 @@ spec: force: true remediation: retries: -1 - {{- $defaults := fromYaml (include "cozystack.defaultGpuOperatorValues" .) }} - {{- $overrides := deepCopy (default (dict) .Values.addons.gpuOperator.valuesOverride) }} - {{- $merged := mergeOverwrite (default (dict) $defaults) $overrides }} - {{- if $merged }} + {{- with .Values.addons.gpuOperator.valuesOverride }} values: - {{- toYaml $merged | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} dependsOn: diff --git a/packages/apps/kubernetes/templates/helmreleases/hami.yaml b/packages/apps/kubernetes/templates/helmreleases/hami.yaml deleted file mode 100644 index f1538c7c..00000000 --- a/packages/apps/kubernetes/templates/helmreleases/hami.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if and .Values.addons.hami.enabled .Values._namespace.etcd }} -{{- if not .Values.addons.gpuOperator.enabled }} -{{- fail "addons.hami requires addons.gpuOperator to be enabled" }} -{{- end }} -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ .Release.Name }}-hami - labels: - cozystack.io/repository: system - cozystack.io/target-cluster-name: {{ .Release.Name }} - sharding.fluxcd.io/key: tenants -spec: - releaseName: hami - chartRef: - kind: ExternalArtifact - name: cozystack-kubernetes-application-kubevirt-kubernetes-hami - namespace: cozy-system - kubeConfig: - secretRef: - name: {{ .Release.Name }}-admin-kubeconfig - key: super-admin.svc - targetNamespace: cozy-hami - storageNamespace: cozy-hami - interval: 5m - timeout: 10m - install: - createNamespace: true - remediation: - retries: -1 - upgrade: - force: true - remediation: - retries: -1 - {{- with .Values.addons.hami.valuesOverride }} - values: - {{- toYaml . | nindent 4 }} - {{- end }} - - dependsOn: - {{- if lookup "helm.toolkit.fluxcd.io/v2" "HelmRelease" .Release.Namespace .Release.Name }} - - name: {{ .Release.Name }} - namespace: {{ .Release.Namespace }} - {{- end }} - - name: {{ .Release.Name }}-cilium - namespace: {{ .Release.Namespace }} - - name: {{ .Release.Name }}-gpu-operator - namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml index 6e2183d3..5cafff90 100644 --- a/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/ingress-nginx.yaml @@ -20,7 +20,7 @@ ingress-nginx: node-role.kubernetes.io/ingress-nginx: "" {{- end }} -{{- if and .Values.addons.ingressNginx.enabled .Values._namespace.etcd }} +{{- if .Values.addons.ingressNginx.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml b/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml index 3e6f9660..3cc81a14 100644 --- a/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/metrics-server.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -37,4 +36,3 @@ spec: namespace: {{ .Release.Namespace }} - name: {{ .Release.Name }}-prometheus-operator-crds namespace: {{ .Release.Namespace }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml index a811f7dd..ff54b6e2 100644 --- a/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/monitoring-agents.yaml @@ -1,6 +1,5 @@ {{- $targetTenant := .Values._namespace.monitoring }} -{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -50,7 +49,7 @@ spec: cluster: {{ .Release.Name }} tenant: {{ .Release.Namespace }} remoteWrite: - url: http://vminsert-shortterm.{{ $targetTenant }}.svc.{{ $clusterDomain }}:8480/insert/0/prometheus + url: http://vminsert-shortterm.{{ $targetTenant }}.svc:8480/insert/0/prometheus fluent-bit: readinessProbe: httpGet: @@ -73,8 +72,8 @@ spec: [OUTPUT] Name http Match kube.* - Host vlinsert-generic.{{ $targetTenant }}.svc.{{ $clusterDomain }} - port 9481 + Host vlogs-generic.{{ $targetTenant }}.svc + port 9428 compress gzip uri /insert/jsonline?_stream_fields=stream,kubernetes_pod_name,kubernetes_container_name,kubernetes_namespace_name&_msg_field=log&_time_field=date format json_lines diff --git a/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml index 3038a058..600a7994 100644 --- a/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/prometheus-operator-crds.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -32,4 +31,3 @@ spec: - name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/helmreleases/velero.yaml b/packages/apps/kubernetes/templates/helmreleases/velero.yaml index 781b9c49..ad236d53 100644 --- a/packages/apps/kubernetes/templates/helmreleases/velero.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/velero.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.velero.enabled .Values._namespace.etcd }} +{{- if .Values.addons.velero.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml index 55a5faac..a3b7a9b4 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler-crds.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml index 74fb5a39..178df3e3 100644 --- a/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/vertical-pod-autoscaler.yaml @@ -24,7 +24,7 @@ vertical-pod-autoscaler: memory: 1600Mi {{- end }} -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml index 7302f8f5..99744277 100644 --- a/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/victoria-metrics-operator.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.addons.monitoringAgents.enabled .Values._namespace.etcd }} +{{- if .Values.addons.monitoringAgents.enabled }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: diff --git a/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml b/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml index d50fd93c..025f01b7 100644 --- a/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml +++ b/packages/apps/kubernetes/templates/helmreleases/volumesnapshot-crd.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -34,4 +33,3 @@ spec: - name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} {{- end }} -{{- end }} diff --git a/packages/apps/kubernetes/templates/kccm/manager.yaml b/packages/apps/kubernetes/templates/kccm/manager.yaml index bd9e2798..81426d4e 100644 --- a/packages/apps/kubernetes/templates/kccm/manager.yaml +++ b/packages/apps/kubernetes/templates/kccm/manager.yaml @@ -1,4 +1,3 @@ -{{- if .Values._namespace.etcd }} apiVersion: apps/v1 kind: Deployment metadata: @@ -23,8 +22,6 @@ spec: - key: node-role.kubernetes.io/control-plane operator: Exists effect: "NoSchedule" - initContainers: - {{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }} containers: - name: kubevirt-cloud-controller-manager args: @@ -58,7 +55,5 @@ spec: name: cloud-config - secret: secretName: {{ .Release.Name }}-admin-kubeconfig - optional: true name: kubeconfig serviceAccountName: {{ .Release.Name }}-kccm -{{- end }} diff --git a/packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml b/packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml deleted file mode 100644 index 507e00af..00000000 --- a/packages/apps/kubernetes/tests/admin_kubeconfig_wait_test.yaml +++ /dev/null @@ -1,155 +0,0 @@ -suite: admin-kubeconfig wait guards - -release: - name: test - namespace: tenant-root - -values: - - values-ci.yaml - -tests: - - it: cluster-autoscaler mounts admin-kubeconfig as optional - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.secretName - value: test-admin-kubeconfig - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.optional - value: true - - - it: cluster-autoscaler waits for admin-kubeconfig via initContainer - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.initContainers[0].name - value: wait-for-kubeconfig - - contains: - path: spec.template.spec.initContainers[0].volumeMounts - content: - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true - - - it: kccm mounts admin-kubeconfig as optional - template: templates/kccm/manager.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.secretName - value: test-admin-kubeconfig - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.optional - value: true - - - it: kccm waits for admin-kubeconfig via initContainer - template: templates/kccm/manager.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.initContainers[0].name - value: wait-for-kubeconfig - - contains: - path: spec.template.spec.initContainers[0].volumeMounts - content: - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true - - - it: csi controller mounts admin-kubeconfig as optional - template: templates/csi/deploy.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.secretName - value: test-admin-kubeconfig - - equal: - path: spec.template.spec.volumes[?(@.name=="kubeconfig")].secret.optional - value: true - - - it: csi controller waits for admin-kubeconfig via initContainer - template: templates/csi/deploy.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - equal: - path: spec.template.spec.initContainers[0].name - value: wait-for-kubeconfig - - contains: - path: spec.template.spec.initContainers[0].volumeMounts - content: - name: kubeconfig - mountPath: /etc/kubernetes/kubeconfig - readOnly: true - - - it: wait-for-kubeconfig defaults to bundled busybox digest pin - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - asserts: - - matchRegex: - path: spec.template.spec.initContainers[0].image - pattern: '^docker\.io/library/busybox:[^@]+@sha256:[0-9a-f]{64}$' - - - it: wait-for-kubeconfig honours images.waitForKubeconfig override - template: templates/cluster-autoscaler/deployment.yaml - documentSelector: - path: kind - value: Deployment - set: - images: - waitForKubeconfig: "registry.example.test/library/busybox:1.37.0@sha256:0000000000000000000000000000000000000000000000000000000000000000" - asserts: - - equal: - path: spec.template.spec.initContainers[0].image - value: "registry.example.test/library/busybox:1.37.0@sha256:0000000000000000000000000000000000000000000000000000000000000000" - - - it: cluster.yaml renders and wires dataStoreName when tenant has etcd - template: templates/cluster.yaml - documentSelector: - path: kind - value: KamajiControlPlane - asserts: - - equal: - path: spec.dataStoreName - value: tenant-root - - - it: cluster.yaml skips Cluster resources when tenant has no etcd DataStore - # Must NOT fail rendering - the parent Tenant chart populates - # _namespace.etcd asynchronously, so rendering failures here would cause - # flux install remediation on every cold bootstrap. Instead, emit only a - # ConfigMap status beacon so the HelmRelease reports Ready while flux - # retries on its interval until the DataStore appears. - template: templates/cluster.yaml - set: - _namespace: - etcd: "" - monitoring: "" - ingress: "" - seaweedfs: "" - host: "" - asserts: - - hasDocuments: - count: 1 - - isKind: - of: ConfigMap - - equal: - path: metadata.name - value: test-awaiting-etcd - - equal: - path: data.status - value: awaiting-etcd diff --git a/packages/apps/kubernetes/tests/gpu_operator_hami_test.yaml b/packages/apps/kubernetes/tests/gpu_operator_hami_test.yaml deleted file mode 100644 index 44528470..00000000 --- a/packages/apps/kubernetes/tests/gpu_operator_hami_test.yaml +++ /dev/null @@ -1,99 +0,0 @@ -suite: GPU Operator HelmRelease HAMi integration tests -templates: - - templates/helmreleases/gpu-operator.yaml -values: - - values-ci.yaml -tests: - - it: should disable devicePlugin when hami is enabled - set: - addons: - gpuOperator: - enabled: true - valuesOverride: {} - hami: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: false - - - it: should not have values when hami is disabled and no overrides - set: - addons: - gpuOperator: - enabled: true - valuesOverride: {} - hami: - enabled: false - valuesOverride: {} - asserts: - - notExists: - path: spec.values - - - it: should apply hami defaults when valuesOverride key is omitted - set: - addons: - gpuOperator: - enabled: true - hami: - enabled: true - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: false - - - it: should allow user overrides to merge with hami defaults - set: - addons: - gpuOperator: - enabled: true - valuesOverride: - gpu-operator: - driver: - enabled: false - hami: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: false - - equal: - path: spec.values.gpu-operator.driver.enabled - value: false - - - it: should let user explicitly override devicePlugin.enabled to true with hami enabled - set: - addons: - gpuOperator: - enabled: true - valuesOverride: - gpu-operator: - devicePlugin: - enabled: true - driver: - enabled: false - hami: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.gpu-operator.devicePlugin.enabled - value: true - - equal: - path: spec.values.gpu-operator.driver.enabled - value: false - - - it: should not render when gpuOperator is disabled - set: - addons: - gpuOperator: - enabled: false - valuesOverride: {} - hami: - enabled: false - valuesOverride: {} - asserts: - - hasDocuments: - count: 0 diff --git a/packages/apps/kubernetes/tests/hami_test.yaml b/packages/apps/kubernetes/tests/hami_test.yaml deleted file mode 100644 index 27f7c75b..00000000 --- a/packages/apps/kubernetes/tests/hami_test.yaml +++ /dev/null @@ -1,153 +0,0 @@ -suite: HAMi HelmRelease tests -templates: - - templates/helmreleases/hami.yaml -values: - - values-ci.yaml -tests: - - it: should not render when hami is disabled - set: - addons: - hami: - enabled: false - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - hasDocuments: - count: 0 - - - it: should render HelmRelease when hami is enabled - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - hasDocuments: - count: 1 - - isKind: - of: HelmRelease - - - it: should fail when gpuOperator is not enabled - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: false - valuesOverride: {} - asserts: - - failedTemplate: - errorMessage: "addons.hami requires addons.gpuOperator to be enabled" - - - it: should have correct metadata labels - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: metadata.labels["cozystack.io/repository"] - value: system - - equal: - path: metadata.labels["sharding.fluxcd.io/key"] - value: tenants - - - it: should use ExternalArtifact chartRef - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.chartRef.kind - value: ExternalArtifact - - equal: - path: spec.chartRef.namespace - value: cozy-system - - - it: should target cozy-hami namespace - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.targetNamespace - value: cozy-hami - - equal: - path: spec.storageNamespace - value: cozy-hami - - - it: should depend on gpu-operator and cilium - release: - name: test - namespace: test-ns - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - contains: - path: spec.dependsOn - content: - name: test-cilium - namespace: test-ns - - contains: - path: spec.dependsOn - content: - name: test-gpu-operator - namespace: test-ns - - - it: should not render spec.values when valuesOverride is empty - set: - addons: - hami: - enabled: true - valuesOverride: {} - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - hasDocuments: - count: 1 - - notExists: - path: spec.values - - - it: should pass through valuesOverride - set: - addons: - hami: - enabled: true - valuesOverride: - hami: - devicePlugin: - deviceSplitCount: 5 - gpuOperator: - enabled: true - valuesOverride: {} - asserts: - - equal: - path: spec.values.hami.devicePlugin.deviceSplitCount - value: 5 diff --git a/packages/apps/kubernetes/tests/values-ci-no-etcd.yaml b/packages/apps/kubernetes/tests/values-ci-no-etcd.yaml deleted file mode 100644 index c7c8196f..00000000 --- a/packages/apps/kubernetes/tests/values-ci-no-etcd.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_namespace: - etcd: "" - monitoring: "" - ingress: "" - seaweedfs: "" - host: "" -_cluster: - cluster-domain: cozy.local -nodeGroups: null diff --git a/packages/apps/kubernetes/tests/values-ci.yaml b/packages/apps/kubernetes/tests/values-ci.yaml deleted file mode 100644 index 13365e8c..00000000 --- a/packages/apps/kubernetes/tests/values-ci.yaml +++ /dev/null @@ -1,9 +0,0 @@ -_namespace: - etcd: tenant-root - monitoring: "" - ingress: "" - seaweedfs: "" - host: "" -_cluster: - cluster-domain: cozy.local -nodeGroups: null diff --git a/packages/apps/kubernetes/values.schema.json b/packages/apps/kubernetes/values.schema.json index a43deaec..1f6c9361 100644 --- a/packages/apps/kubernetes/values.schema.json +++ b/packages/apps/kubernetes/values.schema.json @@ -2,142 +2,6 @@ "title": "Chart Values", "type": "object", "properties": { - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "replicated" - }, - "nodeGroups": { - "description": "Worker nodes configuration map.", - "type": "object", - "default": { - "md0": { - "ephemeralStorage": "20Gi", - "gpus": [], - "instanceType": "u1.medium", - "maxReplicas": 10, - "minReplicas": 0, - "resources": {}, - "roles": [ - "ingress-nginx" - ] - } - }, - "additionalProperties": { - "type": "object", - "required": [ - "ephemeralStorage", - "instanceType", - "maxReplicas", - "minReplicas", - "resources" - ], - "properties": { - "ephemeralStorage": { - "description": "Ephemeral storage size.", - "default": "20Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "gpus": { - "description": "List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).", - "type": "array", - "items": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "description": "Name of GPU, such as \"nvidia.com/AD102GL_L40S\".", - "type": "string" - } - } - } - }, - "instanceType": { - "description": "Virtual machine instance type.", - "type": "string", - "default": "u1.medium" - }, - "maxReplicas": { - "description": "Maximum number of replicas.", - "type": "integer", - "default": 10 - }, - "minReplicas": { - "description": "Minimum number of replicas.", - "type": "integer", - "default": 0 - }, - "resources": { - "description": "CPU and memory resources for each worker node.", - "type": "object", - "properties": { - "cpu": { - "description": "CPU available.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "roles": { - "description": "List of node roles.", - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "version": { - "description": "Kubernetes major.minor version to deploy", - "type": "string", - "default": "v1.35", - "enum": [ - "v1.35", - "v1.34", - "v1.33", - "v1.32", - "v1.31", - "v1.30" - ] - }, - "host": { - "description": "External hostname for Kubernetes cluster. Defaults to `\u003ccluster-name\u003e.\u003ctenant-host\u003e` if empty.", - "type": "string", - "default": "" - }, "addons": { "description": "Cluster addons configuration.", "type": "object", @@ -149,7 +13,6 @@ "fluxcd", "gatewayAPI", "gpuOperator", - "hami", "ingressNginx", "monitoringAgents", "velero", @@ -269,28 +132,6 @@ } } }, - "hami": { - "description": "HAMi GPU virtualization middleware.", - "type": "object", - "default": {}, - "required": [ - "enabled", - "valuesOverride" - ], - "properties": { - "enabled": { - "description": "Enable HAMi (requires GPU Operator).", - "type": "boolean", - "default": false - }, - "valuesOverride": { - "description": "Custom Helm values overrides.", - "type": "object", - "default": {}, - "x-kubernetes-preserve-unknown-fields": true - } - } - }, "ingressNginx": { "description": "Ingress-NGINX controller.", "type": "object", @@ -654,17 +495,141 @@ } } }, - "images": { - "description": "Optional image overrides for air-gapped or rate-limited registries.", + "host": { + "description": "External hostname for Kubernetes cluster. Defaults to `\u003ccluster-name\u003e.\u003ctenant-host\u003e` if empty.", + "type": "string", + "default": "" + }, + "nodeGroups": { + "description": "Worker nodes configuration map.", "type": "object", - "default": {}, - "properties": { - "waitForKubeconfig": { - "description": "Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag.", - "type": "string", - "default": "" + "default": { + "md0": { + "ephemeralStorage": "20Gi", + "gpus": [], + "instanceType": "u1.medium", + "maxReplicas": 10, + "minReplicas": 0, + "resources": {}, + "roles": [ + "ingress-nginx" + ] + } + }, + "additionalProperties": { + "type": "object", + "required": [ + "ephemeralStorage", + "instanceType", + "maxReplicas", + "minReplicas", + "resources" + ], + "properties": { + "ephemeralStorage": { + "description": "Ephemeral storage size.", + "default": "20Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "gpus": { + "description": "List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).", + "type": "array", + "items": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "Name of GPU, such as \"nvidia.com/AD102GL_L40S\".", + "type": "string" + } + } + } + }, + "instanceType": { + "description": "Virtual machine instance type.", + "type": "string", + "default": "u1.medium" + }, + "maxReplicas": { + "description": "Maximum number of replicas.", + "type": "integer", + "default": 10 + }, + "minReplicas": { + "description": "Minimum number of replicas.", + "type": "integer", + "default": 0 + }, + "resources": { + "description": "CPU and memory resources for each worker node.", + "type": "object", + "properties": { + "cpu": { + "description": "CPU available.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory (RAM) available.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "roles": { + "description": "List of node roles.", + "type": "array", + "items": { + "type": "string" + } + } } } + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "replicated" + }, + "version": { + "description": "Kubernetes major.minor version to deploy", + "type": "string", + "default": "v1.33", + "enum": [ + "v1.33", + "v1.32", + "v1.31", + "v1.30", + "v1.29", + "v1.28" + ] } } -} +} \ No newline at end of file diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index d609476c..7f15752f 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -48,15 +48,15 @@ nodeGroups: ## ## @enum {string} Version -## @value v1.35 -## @value v1.34 ## @value v1.33 ## @value v1.32 ## @value v1.31 ## @value v1.30 +## @value v1.29 +## @value v1.28 ## @param {Version} version - Kubernetes major.minor version to deploy -version: "v1.35" +version: "v1.33" ## @param {string} host - External hostname for Kubernetes cluster. Defaults to `.` if empty. @@ -94,10 +94,6 @@ host: "" ## @field {bool} enabled - Enable FluxCD. ## @field {object} valuesOverride - Custom Helm values overrides. -## @typedef {struct} HAMiAddon - HAMi GPU virtualization middleware. -## @field {bool} enabled - Enable HAMi (requires GPU Operator). -## @field {object} valuesOverride - Custom Helm values overrides. - ## @typedef {struct} MonitoringAgentsAddon - Monitoring agents (Fluent Bit, VMAgents). ## @field {bool} enabled - Enable monitoring agents. ## @field {object} valuesOverride - Custom Helm values overrides. @@ -118,7 +114,6 @@ host: "" ## @field {GatewayAPIAddon} gatewayAPI - Gateway API addon. ## @field {IngressNginxAddon} ingressNginx - Ingress-NGINX controller. ## @field {GPUOperatorAddon} gpuOperator - NVIDIA GPU Operator. -## @field {HAMiAddon} hami - HAMi GPU virtualization middleware. ## @field {FluxCDAddon} fluxcd - FluxCD GitOps operator. ## @field {MonitoringAgentsAddon} monitoringAgents - Monitoring agents. ## @field {VerticalPodAutoscalerAddon} verticalPodAutoscaler - Vertical Pod Autoscaler. @@ -142,9 +137,6 @@ addons: gpuOperator: enabled: false valuesOverride: {} - hami: - enabled: false - valuesOverride: {} fluxcd: enabled: false valuesOverride: {} @@ -205,10 +197,3 @@ controlPlane: server: resources: {} resourcesPreset: "micro" - -## @typedef {struct} Images - Optional image overrides for chart-internal helpers. -## @field {string} [waitForKubeconfig] - Image used by the wait-for-kubeconfig init container. Empty falls back to images/busybox.tag. - -## @param {Images} images - Optional image overrides for air-gapped or rate-limited registries. -images: - waitForKubeconfig: "" diff --git a/packages/apps/mariadb/images/mariadb-backup.tag b/packages/apps/mariadb/images/mariadb-backup.tag deleted file mode 100644 index 6c830892..00000000 --- a/packages/apps/mariadb/images/mariadb-backup.tag +++ /dev/null @@ -1 +0,0 @@ -ghcr.io/cozystack/cozystack/mariadb-backup:0.0.0@sha256:3841eb171416711977dea0cf8cd45d32344caac9727af760c37d5e1dd41ee4bb diff --git a/packages/apps/mongodb/Makefile b/packages/apps/mongodb/Makefile index 37f30ccc..9440c3fd 100644 --- a/packages/apps/mongodb/Makefile +++ b/packages/apps/mongodb/Makefile @@ -3,7 +3,7 @@ include ../../../hack/package.mk .PHONY: generate update generate: - cozyvalues-gen -m 'mongodb' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/mongodb/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh update: diff --git a/packages/apps/mongodb/logos/mongodb.svg b/packages/apps/mongodb/logos/mongodb.svg index 86bb6d40..3c76d2d6 100644 --- a/packages/apps/mongodb/logos/mongodb.svg +++ b/packages/apps/mongodb/logos/mongodb.svg @@ -1,10 +1,13 @@ - - + + + + + - - - - + + + + diff --git a/packages/apps/mongodb/templates/mongodb.yaml b/packages/apps/mongodb/templates/mongodb.yaml index 9273e506..67969758 100644 --- a/packages/apps/mongodb/templates/mongodb.yaml +++ b/packages/apps/mongodb/templates/mongodb.yaml @@ -169,8 +169,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ .Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: {{- if .Values.sharding }} {{- $totalReplicas := 0 }} diff --git a/packages/apps/mongodb/values.schema.json b/packages/apps/mongodb/values.schema.json index 2d077cfc..3a66d60d 100644 --- a/packages/apps/mongodb/values.schema.json +++ b/packages/apps/mongodb/values.schema.json @@ -2,6 +2,112 @@ "title": "Chart Values", "type": "object", "properties": { + "backup": { + "description": "Backup configuration.", + "type": "object", + "default": {}, + "required": [ + "enabled" + ], + "properties": { + "destinationPath": { + "description": "Destination path for backups (e.g. s3://bucket/path/).", + "type": "string", + "default": "s3://bucket/path/to/folder/" + }, + "enabled": { + "description": "Enable regular backups.", + "type": "boolean", + "default": false + }, + "endpointURL": { + "description": "S3 endpoint URL for uploads.", + "type": "string", + "default": "http://minio-gateway-service:9000" + }, + "retentionPolicy": { + "description": "Retention policy (e.g. \"30d\").", + "type": "string", + "default": "30d" + }, + "s3AccessKey": { + "description": "Access key for S3 authentication.", + "type": "string", + "default": "" + }, + "s3SecretKey": { + "description": "Secret key for S3 authentication.", + "type": "string", + "default": "" + }, + "schedule": { + "description": "Cron schedule for automated backups.", + "type": "string", + "default": "0 2 * * *" + } + } + }, + "bootstrap": { + "description": "Bootstrap configuration.", + "type": "object", + "default": {}, + "required": [ + "backupName", + "enabled" + ], + "properties": { + "backupName": { + "description": "Name of backup to restore from.", + "type": "string", + "default": "" + }, + "enabled": { + "description": "Whether to restore from a backup.", + "type": "boolean", + "default": false + }, + "recoveryTime": { + "description": "Timestamp for point-in-time recovery; empty means latest.", + "type": "string", + "default": "" + } + } + }, + "databases": { + "description": "Databases configuration map.", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "roles": { + "description": "Roles assigned to users.", + "type": "object", + "properties": { + "admin": { + "description": "List of users with admin privileges (readWrite + dbAdmin).", + "type": "array", + "items": { + "type": "string" + } + }, + "readonly": { + "description": "List of users with read-only privileges.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, "replicas": { "description": "Number of MongoDB replicas in replica set.", "type": "integer", @@ -54,40 +160,6 @@ "2xlarge" ] }, - "size": { - "description": "Persistent Volume Claim size available for application data.", - "default": "10Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, - "version": { - "description": "MongoDB major version to deploy.", - "type": "string", - "default": "v8", - "enum": [ - "v8", - "v7", - "v6" - ] - }, "sharding": { "description": "Enable sharded cluster mode. When disabled, deploys a replica set.", "type": "boolean", @@ -171,6 +243,25 @@ } } }, + "size": { + "description": "Persistent Volume Claim size available for application data.", + "default": "10Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "" + }, "users": { "description": "Users configuration map.", "type": "object", @@ -185,106 +276,15 @@ } } }, - "databases": { - "description": "Databases configuration map.", - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "properties": { - "roles": { - "description": "Roles assigned to users.", - "type": "object", - "properties": { - "admin": { - "description": "List of users with admin privileges (readWrite + dbAdmin).", - "type": "array", - "items": { - "type": "string" - } - }, - "readonly": { - "description": "List of users with read-only privileges.", - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } - }, - "backup": { - "description": "Backup configuration.", - "type": "object", - "default": {}, - "required": [ - "enabled" - ], - "properties": { - "destinationPath": { - "description": "Destination path for backups (e.g. s3://bucket/path/).", - "type": "string", - "default": "s3://bucket/path/to/folder/" - }, - "enabled": { - "description": "Enable regular backups.", - "type": "boolean", - "default": false - }, - "endpointURL": { - "description": "S3 endpoint URL for uploads.", - "type": "string", - "default": "http://minio-gateway-service:9000" - }, - "retentionPolicy": { - "description": "Retention policy (e.g. \"30d\").", - "type": "string", - "default": "30d" - }, - "s3AccessKey": { - "description": "Access key for S3 authentication.", - "type": "string", - "default": "" - }, - "s3SecretKey": { - "description": "Secret key for S3 authentication.", - "type": "string", - "default": "" - }, - "schedule": { - "description": "Cron schedule for automated backups.", - "type": "string", - "default": "0 2 * * *" - } - } - }, - "bootstrap": { - "description": "Bootstrap configuration.", - "type": "object", - "default": {}, - "required": [ - "backupName", - "enabled" - ], - "properties": { - "backupName": { - "description": "Name of backup to restore from.", - "type": "string", - "default": "" - }, - "enabled": { - "description": "Whether to restore from a backup.", - "type": "boolean", - "default": false - }, - "recoveryTime": { - "description": "Timestamp for point-in-time recovery; empty means latest.", - "type": "string", - "default": "" - } - } + "version": { + "description": "MongoDB major version to deploy.", + "type": "string", + "default": "v8", + "enum": [ + "v8", + "v7", + "v6" + ] } } -} +} \ No newline at end of file diff --git a/packages/apps/mariadb/.helmignore b/packages/apps/mysql/.helmignore similarity index 100% rename from packages/apps/mariadb/.helmignore rename to packages/apps/mysql/.helmignore diff --git a/packages/apps/mariadb/Chart.yaml b/packages/apps/mysql/Chart.yaml similarity index 93% rename from packages/apps/mariadb/Chart.yaml rename to packages/apps/mysql/Chart.yaml index 6acc5082..f9cedb1b 100644 --- a/packages/apps/mariadb/Chart.yaml +++ b/packages/apps/mysql/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -name: mariadb +name: mysql description: Managed MariaDB service icon: /logos/mariadb.svg type: application diff --git a/packages/apps/mariadb/Makefile b/packages/apps/mysql/Makefile similarity index 85% rename from packages/apps/mariadb/Makefile rename to packages/apps/mysql/Makefile index 9833f302..e8f02703 100644 --- a/packages/apps/mariadb/Makefile +++ b/packages/apps/mysql/Makefile @@ -4,7 +4,7 @@ include ../../../hack/common-envs.mk include ../../../hack/package.mk generate: - cozyvalues-gen -m 'mariadb' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/mariadb/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh update: diff --git a/packages/apps/mariadb/README.md b/packages/apps/mysql/README.md similarity index 95% rename from packages/apps/mariadb/README.md rename to packages/apps/mysql/README.md index 9d97dc5f..6d47a6d5 100644 --- a/packages/apps/mariadb/README.md +++ b/packages/apps/mysql/README.md @@ -15,7 +15,7 @@ This managed service is controlled by mariadb-operator, ensuring efficient manag ### How to switch master/slave replica ```bash -kubectl edit mariadb +kubectl edit mariadb ``` update: @@ -54,11 +54,11 @@ more details: - **Replication can't be finished with various errors** - **Replication can't be finished in case if `binlog` purged** - Until `mariadbbackup` is not used to bootstrap a node by mariadb-operator (this feature is not implemented yet), follow these manual steps to fix it: + Until `mariadbbackup` is not used to bootstrap a node by mariadb-operator (this feature is not inmplemented yet), follow these manual steps to fix it: https://github.com/mariadb-operator/mariadb-operator/issues/141#issuecomment-1804760231 -- **Corrupted indices** - Sometimes some indices can be corrupted on master replica, you can recover them from slave: +- **Corrupted indicies** + Sometimes some indecies can be corrupted on master replica, you can recover them from slave: ```bash mysqldump -h -P 3306 -u -p --column-statistics=0 ~/tmp/fix-table.sql @@ -102,7 +102,7 @@ more details: | `backup` | Backup configuration. | `object` | `{}` | | `backup.enabled` | Enable regular backups (default: false). | `bool` | `false` | | `backup.s3Region` | AWS S3 region where backups are stored. | `string` | `us-east-1` | -| `backup.s3Bucket` | S3 bucket used for storing backups. | `string` | `s3.example.org/mariadb-backups` | +| `backup.s3Bucket` | S3 bucket used for storing backups. | `string` | `s3.example.org/mysql-backups` | | `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * *` | | `backup.cleanupStrategy` | Retention strategy for cleaning up old backups. | `string` | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` | | `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `` | diff --git a/packages/apps/mariadb/charts/cozy-lib b/packages/apps/mysql/charts/cozy-lib similarity index 100% rename from packages/apps/mariadb/charts/cozy-lib rename to packages/apps/mysql/charts/cozy-lib diff --git a/packages/apps/mariadb/files/versions.yaml b/packages/apps/mysql/files/versions.yaml similarity index 100% rename from packages/apps/mariadb/files/versions.yaml rename to packages/apps/mysql/files/versions.yaml diff --git a/packages/apps/mariadb/hack/update-versions.sh b/packages/apps/mysql/hack/update-versions.sh similarity index 97% rename from packages/apps/mariadb/hack/update-versions.sh rename to packages/apps/mysql/hack/update-versions.sh index 775c0327..1b58591a 100755 --- a/packages/apps/mariadb/hack/update-versions.sh +++ b/packages/apps/mysql/hack/update-versions.sh @@ -5,9 +5,9 @@ set -o nounset set -o pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -MARIADB_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -VALUES_FILE="${MARIADB_DIR}/values.yaml" -VERSIONS_FILE="${MARIADB_DIR}/files/versions.yaml" +MYSQL_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" +VALUES_FILE="${MYSQL_DIR}/values.yaml" +VERSIONS_FILE="${MYSQL_DIR}/files/versions.yaml" MARIADB_API_URL="https://downloads.mariadb.org/rest-api/mariadb/" # Check if jq is installed diff --git a/packages/apps/mysql/images/mariadb-backup.tag b/packages/apps/mysql/images/mariadb-backup.tag new file mode 100644 index 00000000..1e381661 --- /dev/null +++ b/packages/apps/mysql/images/mariadb-backup.tag @@ -0,0 +1 @@ +ghcr.io/cozystack/cozystack/mariadb-backup:0.0.0@sha256:0ddbbec0568dcb9fbc317cd9cc654e826dbe88ba3f184fa9b6b58aacb93b4570 diff --git a/packages/apps/mariadb/images/mariadb-backup/Dockerfile b/packages/apps/mysql/images/mariadb-backup/Dockerfile similarity index 100% rename from packages/apps/mariadb/images/mariadb-backup/Dockerfile rename to packages/apps/mysql/images/mariadb-backup/Dockerfile diff --git a/packages/apps/mariadb/logos/mariadb.svg b/packages/apps/mysql/logos/mariadb.svg similarity index 100% rename from packages/apps/mariadb/logos/mariadb.svg rename to packages/apps/mysql/logos/mariadb.svg diff --git a/packages/apps/opensearch/templates/.gitkeep b/packages/apps/mysql/templates/.gitkeep similarity index 100% rename from packages/apps/opensearch/templates/.gitkeep rename to packages/apps/mysql/templates/.gitkeep diff --git a/packages/apps/openbao/templates/_resources.tpl b/packages/apps/mysql/templates/_resources.tpl similarity index 91% rename from packages/apps/openbao/templates/_resources.tpl rename to packages/apps/mysql/templates/_resources.tpl index 7aeb976e..6539c99a 100644 --- a/packages/apps/openbao/templates/_resources.tpl +++ b/packages/apps/mysql/templates/_resources.tpl @@ -11,32 +11,32 @@ These presets are for basic testing and not meant to be used in production {{ include "resources.preset" (dict "type" "nano") -}} */}} {{- define "resources.preset" -}} -{{- $presets := dict - "nano" (dict +{{- $presets := dict + "nano" (dict "requests" (dict "cpu" "100m" "memory" "128Mi" "ephemeral-storage" "50Mi") "limits" (dict "memory" "128Mi" "ephemeral-storage" "2Gi") ) - "micro" (dict + "micro" (dict "requests" (dict "cpu" "250m" "memory" "256Mi" "ephemeral-storage" "50Mi") "limits" (dict "memory" "256Mi" "ephemeral-storage" "2Gi") ) - "small" (dict + "small" (dict "requests" (dict "cpu" "500m" "memory" "512Mi" "ephemeral-storage" "50Mi") "limits" (dict "memory" "512Mi" "ephemeral-storage" "2Gi") ) - "medium" (dict + "medium" (dict "requests" (dict "cpu" "500m" "memory" "1Gi" "ephemeral-storage" "50Mi") "limits" (dict "memory" "1Gi" "ephemeral-storage" "2Gi") ) - "large" (dict + "large" (dict "requests" (dict "cpu" "1" "memory" "2Gi" "ephemeral-storage" "50Mi") "limits" (dict "memory" "2Gi" "ephemeral-storage" "2Gi") ) - "xlarge" (dict + "xlarge" (dict "requests" (dict "cpu" "2" "memory" "4Gi" "ephemeral-storage" "50Mi") "limits" (dict "memory" "4Gi" "ephemeral-storage" "2Gi") ) - "2xlarge" (dict + "2xlarge" (dict "requests" (dict "cpu" "4" "memory" "8Gi" "ephemeral-storage" "50Mi") "limits" (dict "memory" "8Gi" "ephemeral-storage" "2Gi") ) diff --git a/packages/apps/mariadb/templates/_versions.tpl b/packages/apps/mysql/templates/_versions.tpl similarity index 89% rename from packages/apps/mariadb/templates/_versions.tpl rename to packages/apps/mysql/templates/_versions.tpl index a896ea5f..cd4ee0e1 100644 --- a/packages/apps/mariadb/templates/_versions.tpl +++ b/packages/apps/mysql/templates/_versions.tpl @@ -1,4 +1,4 @@ -{{- define "mariadb.versionMap" }} +{{- define "mysql.versionMap" }} {{- $versionMap := .Files.Get "files/versions.yaml" | fromYaml }} {{- if not (hasKey $versionMap .Values.version) }} {{- printf `MariaDB version %s is not supported, allowed versions are %s` $.Values.version (keys $versionMap) | fail }} diff --git a/packages/apps/mariadb/templates/backup-cronjob.yaml b/packages/apps/mysql/templates/backup-cronjob.yaml similarity index 96% rename from packages/apps/mariadb/templates/backup-cronjob.yaml rename to packages/apps/mysql/templates/backup-cronjob.yaml index ddb237cd..97b52208 100644 --- a/packages/apps/mariadb/templates/backup-cronjob.yaml +++ b/packages/apps/mysql/templates/backup-cronjob.yaml @@ -13,6 +13,9 @@ spec: jobTemplate: spec: backoffLimit: 2 + template: + spec: + restartPolicy: OnFailure template: metadata: annotations: @@ -41,7 +44,7 @@ spec: name: {{ .Release.Name }} key: root-password - name: MYSQL_HOST - value: "{{ .Release.Name }}-{{ if eq (int .Values.replicas) 1 }}primary{{ else }}secondary{{ end }}" + value: {{ .Release.Name }}-secondary - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: diff --git a/packages/apps/mariadb/templates/backup-script.yaml b/packages/apps/mysql/templates/backup-script.yaml similarity index 100% rename from packages/apps/mariadb/templates/backup-script.yaml rename to packages/apps/mysql/templates/backup-script.yaml diff --git a/packages/apps/mariadb/templates/backup-secret.yaml b/packages/apps/mysql/templates/backup-secret.yaml similarity index 100% rename from packages/apps/mariadb/templates/backup-secret.yaml rename to packages/apps/mysql/templates/backup-secret.yaml diff --git a/packages/apps/mariadb/templates/config.yaml b/packages/apps/mysql/templates/config.yaml similarity index 100% rename from packages/apps/mariadb/templates/config.yaml rename to packages/apps/mysql/templates/config.yaml diff --git a/packages/apps/mariadb/templates/dashboard-resourcemap.yaml b/packages/apps/mysql/templates/dashboard-resourcemap.yaml similarity index 100% rename from packages/apps/mariadb/templates/dashboard-resourcemap.yaml rename to packages/apps/mysql/templates/dashboard-resourcemap.yaml diff --git a/packages/apps/mariadb/templates/db.yaml b/packages/apps/mysql/templates/db.yaml similarity index 100% rename from packages/apps/mariadb/templates/db.yaml rename to packages/apps/mysql/templates/db.yaml diff --git a/packages/apps/mariadb/templates/hooks/cleanup-pvc.yaml b/packages/apps/mysql/templates/hooks/cleanup-pvc.yaml similarity index 100% rename from packages/apps/mariadb/templates/hooks/cleanup-pvc.yaml rename to packages/apps/mysql/templates/hooks/cleanup-pvc.yaml diff --git a/packages/apps/mariadb/templates/mariadb.yaml b/packages/apps/mysql/templates/mariadb.yaml similarity index 86% rename from packages/apps/mariadb/templates/mariadb.yaml rename to packages/apps/mysql/templates/mariadb.yaml index d3d5e636..b4a888d8 100644 --- a/packages/apps/mariadb/templates/mariadb.yaml +++ b/packages/apps/mysql/templates/mariadb.yaml @@ -8,7 +8,7 @@ spec: name: {{ .Release.Name }}-credentials key: root - image: "mariadb:{{ include "mariadb.versionMap" $ }}" + image: "mariadb:{{ include "mysql.versionMap" $ }}" port: 3306 @@ -29,11 +29,13 @@ spec: - {{ .Release.Name }} topologyKey: "kubernetes.io/hostname" + {{- if gt (int .Values.replicas) 1 }} replication: enabled: true #primary: # podIndex: 0 # automaticFailover: true + {{- end }} podMetadata: labels: @@ -63,6 +65,9 @@ spec: metadata: labels: app.kubernetes.io/instance: {{ $.Release.Name }} + {{- if and .Values.external (eq (int .Values.replicas) 1) }} + type: LoadBalancer + {{- end }} storage: size: {{ .Values.size }} resizeInUseVolumes: true @@ -71,7 +76,7 @@ spec: storageClassName: {{ . }} {{- end }} - {{- if .Values.external }} + {{- if and .Values.external (gt (int .Values.replicas) 1) }} primaryService: type: LoadBalancer {{- end }} diff --git a/packages/apps/mariadb/templates/regsecret.yaml b/packages/apps/mysql/templates/regsecret.yaml similarity index 100% rename from packages/apps/mariadb/templates/regsecret.yaml rename to packages/apps/mysql/templates/regsecret.yaml diff --git a/packages/apps/mariadb/templates/secret.yaml b/packages/apps/mysql/templates/secret.yaml similarity index 100% rename from packages/apps/mariadb/templates/secret.yaml rename to packages/apps/mysql/templates/secret.yaml diff --git a/packages/apps/mariadb/templates/user.yaml b/packages/apps/mysql/templates/user.yaml similarity index 100% rename from packages/apps/mariadb/templates/user.yaml rename to packages/apps/mysql/templates/user.yaml diff --git a/packages/apps/bucket/templates/workloadmonitor.yaml b/packages/apps/mysql/templates/workloadmonitor.yaml similarity index 71% rename from packages/apps/bucket/templates/workloadmonitor.yaml rename to packages/apps/mysql/templates/workloadmonitor.yaml index a23f3147..9fc6d144 100644 --- a/packages/apps/bucket/templates/workloadmonitor.yaml +++ b/packages/apps/mysql/templates/workloadmonitor.yaml @@ -4,10 +4,10 @@ kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} spec: - replicas: 0 - minReplicas: 0 - kind: bucket - type: s3 + replicas: {{ .Values.replicas }} + minReplicas: 1 + kind: mysql + type: mysql selector: app.kubernetes.io/instance: {{ $.Release.Name }} version: {{ $.Chart.Version }} diff --git a/packages/apps/mariadb/values.schema.json b/packages/apps/mysql/values.schema.json similarity index 99% rename from packages/apps/mariadb/values.schema.json rename to packages/apps/mysql/values.schema.json index 49df40f0..a36754b2 100644 --- a/packages/apps/mariadb/values.schema.json +++ b/packages/apps/mysql/values.schema.json @@ -2,6 +2,98 @@ "title": "Chart Values", "type": "object", "properties": { + "backup": { + "description": "Backup configuration.", + "type": "object", + "default": {}, + "required": [ + "cleanupStrategy", + "enabled", + "resticPassword", + "s3AccessKey", + "s3Bucket", + "s3Region", + "s3SecretKey", + "schedule" + ], + "properties": { + "cleanupStrategy": { + "description": "Retention strategy for cleaning up old backups.", + "type": "string", + "default": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m" + }, + "enabled": { + "description": "Enable regular backups (default: false).", + "type": "boolean", + "default": false + }, + "resticPassword": { + "description": "Password for Restic backup encryption.", + "type": "string", + "default": "\u003cpassword\u003e" + }, + "s3AccessKey": { + "description": "Access key for S3 authentication.", + "type": "string", + "default": "\u003cyour-access-key\u003e" + }, + "s3Bucket": { + "description": "S3 bucket used for storing backups.", + "type": "string", + "default": "s3.example.org/mysql-backups" + }, + "s3Region": { + "description": "AWS S3 region where backups are stored.", + "type": "string", + "default": "us-east-1" + }, + "s3SecretKey": { + "description": "Secret key for S3 authentication.", + "type": "string", + "default": "\u003cyour-secret-key\u003e" + }, + "schedule": { + "description": "Cron schedule for automated backups.", + "type": "string", + "default": "0 2 * * *" + } + } + }, + "databases": { + "description": "Databases configuration map.", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "roles": { + "description": "Roles assigned to users.", + "type": "object", + "properties": { + "admin": { + "description": "List of users with admin privileges.", + "type": "array", + "items": { + "type": "string" + } + }, + "readonly": { + "description": "List of users with read-only privileges.", + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, "replicas": { "description": "Number of MariaDB replicas.", "type": "integer", @@ -73,22 +165,6 @@ "type": "string", "default": "" }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, - "version": { - "description": "MariaDB major.minor version to deploy", - "type": "string", - "default": "v11.8", - "enum": [ - "v11.8", - "v11.4", - "v10.11", - "v10.6" - ] - }, "users": { "description": "Users configuration map.", "type": "object", @@ -111,92 +187,16 @@ } } }, - "databases": { - "description": "Databases configuration map.", - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "properties": { - "roles": { - "description": "Roles assigned to users.", - "type": "object", - "properties": { - "admin": { - "description": "List of users with admin privileges.", - "type": "array", - "items": { - "type": "string" - } - }, - "readonly": { - "description": "List of users with read-only privileges.", - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } - }, - "backup": { - "description": "Backup configuration.", - "type": "object", - "default": {}, - "required": [ - "cleanupStrategy", - "enabled", - "resticPassword", - "s3AccessKey", - "s3Bucket", - "s3Region", - "s3SecretKey", - "schedule" - ], - "properties": { - "cleanupStrategy": { - "description": "Retention strategy for cleaning up old backups.", - "type": "string", - "default": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m" - }, - "enabled": { - "description": "Enable regular backups (default: false).", - "type": "boolean", - "default": false - }, - "resticPassword": { - "description": "Password for Restic backup encryption.", - "type": "string", - "default": "\u003cpassword\u003e" - }, - "s3AccessKey": { - "description": "Access key for S3 authentication.", - "type": "string", - "default": "\u003cyour-access-key\u003e" - }, - "s3Bucket": { - "description": "S3 bucket used for storing backups.", - "type": "string", - "default": "s3.example.org/mariadb-backups" - }, - "s3Region": { - "description": "AWS S3 region where backups are stored.", - "type": "string", - "default": "us-east-1" - }, - "s3SecretKey": { - "description": "Secret key for S3 authentication.", - "type": "string", - "default": "\u003cyour-secret-key\u003e" - }, - "schedule": { - "description": "Cron schedule for automated backups.", - "type": "string", - "default": "0 2 * * *" - } - } + "version": { + "description": "MariaDB major.minor version to deploy", + "type": "string", + "default": "v11.8", + "enum": [ + "v11.8", + "v11.4", + "v10.11", + "v10.6" + ] } } -} +} \ No newline at end of file diff --git a/packages/apps/mariadb/values.yaml b/packages/apps/mysql/values.yaml similarity index 98% rename from packages/apps/mariadb/values.yaml rename to packages/apps/mysql/values.yaml index 6d629a83..c7726b7a 100644 --- a/packages/apps/mariadb/values.yaml +++ b/packages/apps/mysql/values.yaml @@ -98,7 +98,7 @@ databases: {} backup: enabled: false s3Region: us-east-1 - s3Bucket: "s3.example.org/mariadb-backups" + s3Bucket: "s3.example.org/mysql-backups" schedule: "0 2 * * *" cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m" s3AccessKey: "" diff --git a/packages/apps/nats/Makefile b/packages/apps/nats/Makefile index 29f6f9bc..d1cfda8e 100644 --- a/packages/apps/nats/Makefile +++ b/packages/apps/nats/Makefile @@ -1,5 +1,5 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'nats' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/nats/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh diff --git a/packages/apps/nats/templates/nats.yaml b/packages/apps/nats/templates/nats.yaml index e5f5cf5d..4f52ff11 100644 --- a/packages/apps/nats/templates/nats.yaml +++ b/packages/apps/nats/templates/nats.yaml @@ -95,6 +95,10 @@ spec: {{- with .Values.storageClass }} storageClassName: {{ . }} {{- end }} + promExporter: + enabled: true + podMonitor: + enabled: true {{- if .Values.external }} service: merge: diff --git a/packages/apps/nats/templates/workloadmonitor.yaml b/packages/apps/nats/templates/workloadmonitor.yaml index cb20b4a6..43d64a46 100644 --- a/packages/apps/nats/templates/workloadmonitor.yaml +++ b/packages/apps/nats/templates/workloadmonitor.yaml @@ -3,8 +3,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 diff --git a/packages/apps/nats/values.schema.json b/packages/apps/nats/values.schema.json index 605c8752..3ef5fef7 100644 --- a/packages/apps/nats/values.schema.json +++ b/packages/apps/nats/values.schema.json @@ -2,6 +2,60 @@ "title": "Chart Values", "type": "object", "properties": { + "config": { + "description": "NATS configuration.", + "type": "object", + "default": {}, + "properties": { + "merge": { + "description": "Additional configuration to merge into NATS config.", + "type": "object", + "default": {}, + "x-kubernetes-preserve-unknown-fields": true + }, + "resolver": { + "description": "Additional resolver configuration to merge into NATS config.", + "type": "object", + "default": {}, + "x-kubernetes-preserve-unknown-fields": true + } + } + }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, + "jetstream": { + "description": "Jetstream configuration.", + "type": "object", + "default": {}, + "required": [ + "enabled", + "size" + ], + "properties": { + "enabled": { + "description": "Enable or disable Jetstream for persistent messaging in NATS.", + "type": "boolean", + "default": true + }, + "size": { + "description": "Jetstream persistent storage size.", + "default": "10Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, "replicas": { "description": "Number of replicas.", "type": "integer", @@ -59,11 +113,6 @@ "type": "string", "default": "" }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, "users": { "description": "Users configuration map.", "type": "object", @@ -77,55 +126,6 @@ } } } - }, - "jetstream": { - "description": "Jetstream configuration.", - "type": "object", - "default": {}, - "required": [ - "enabled", - "size" - ], - "properties": { - "enabled": { - "description": "Enable or disable Jetstream for persistent messaging in NATS.", - "type": "boolean", - "default": true - }, - "size": { - "description": "Jetstream persistent storage size.", - "default": "10Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "config": { - "description": "NATS configuration.", - "type": "object", - "default": {}, - "properties": { - "merge": { - "description": "Additional configuration to merge into NATS config.", - "type": "object", - "default": {}, - "x-kubernetes-preserve-unknown-fields": true - }, - "resolver": { - "description": "Additional resolver configuration to merge into NATS config.", - "type": "object", - "default": {}, - "x-kubernetes-preserve-unknown-fields": true - } - } } } -} +} \ No newline at end of file diff --git a/packages/apps/openbao/Chart.yaml b/packages/apps/openbao/Chart.yaml deleted file mode 100644 index f33fc756..00000000 --- a/packages/apps/openbao/Chart.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v2 -name: openbao -description: Managed OpenBAO secrets management service -icon: /logos/openbao.svg -type: application -version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process -appVersion: "2.5.0" diff --git a/packages/apps/openbao/Makefile b/packages/apps/openbao/Makefile deleted file mode 100644 index b9530139..00000000 --- a/packages/apps/openbao/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../../../hack/package.mk - -generate: - cozyvalues-gen -m 'openbao' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/openbao/types.go - ../../../hack/update-crd.sh diff --git a/packages/apps/openbao/README.md b/packages/apps/openbao/README.md deleted file mode 100644 index c53c9d28..00000000 --- a/packages/apps/openbao/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Managed OpenBAO Service - -OpenBAO is an open-source secrets management solution forked from HashiCorp Vault. -It provides identity-based secrets and encryption management for cloud infrastructure. - -## Parameters - -### Common parameters - -| Name | Description | Type | Value | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- | -| `replicas` | Number of OpenBAO replicas. HA with Raft is automatically enabled when replicas > 1. Switching between standalone (file storage) and HA (Raft storage) modes requires data migration. | `int` | `1` | -| `resources` | Explicit CPU and memory configuration for each OpenBAO replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `resources.cpu` | CPU available to each replica. | `quantity` | `""` | -| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` | -| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `size` | Persistent Volume Claim size for data storage. | `quantity` | `10Gi` | -| `storageClass` | StorageClass used to store the data. | `string` | `""` | -| `external` | Enable external access from outside the cluster. | `bool` | `false` | - - -### Application-specific parameters - -| Name | Description | Type | Value | -| ---- | -------------------------- | ------ | ------ | -| `ui` | Enable the OpenBAO web UI. | `bool` | `true` | - diff --git a/packages/apps/openbao/logos/openbao.svg b/packages/apps/openbao/logos/openbao.svg deleted file mode 100644 index 5ce73b79..00000000 --- a/packages/apps/openbao/logos/openbao.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/packages/apps/openbao/templates/openbao.yaml b/packages/apps/openbao/templates/openbao.yaml deleted file mode 100644 index daa6f9c4..00000000 --- a/packages/apps/openbao/templates/openbao.yaml +++ /dev/null @@ -1,99 +0,0 @@ -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ .Release.Name }}-system - labels: - sharding.fluxcd.io/key: tenants -spec: - chartRef: - kind: ExternalArtifact - name: cozystack-openbao-application-default-openbao-system - namespace: cozy-system - interval: 5m - timeout: 10m - install: - remediation: - retries: -1 - upgrade: - force: true - remediation: - retries: -1 - valuesFrom: - - kind: Secret - name: cozystack-values - values: - openbao: - fullnameOverride: {{ .Release.Name }} - global: - tlsDisable: true - server: - podManagementPolicy: Parallel - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 10 }} - dataStorage: - enabled: true - size: {{ .Values.size }} - {{- with .Values.storageClass }} - storageClass: {{ . }} - {{- end }} - {{- if gt (int .Values.replicas) 1 }} - standalone: - enabled: false - ha: - enabled: true - replicas: {{ .Values.replicas }} - raft: - enabled: true - setNodeId: true - config: | - ui = {{ .Values.ui }} - - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_disable = true - } - - storage "raft" { - path = "/openbao/data" - {{- range $i := until (int $.Values.replicas) }} - retry_join { - leader_api_addr = "http://{{ $.Release.Name }}-{{ $i }}.{{ $.Release.Name }}-internal:8200" - } - {{- end }} - } - - service_registration "kubernetes" {} - {{- else }} - standalone: - enabled: true - config: | - ui = {{ .Values.ui }} - - listener "tcp" { - address = "[::]:8200" - cluster_address = "[::]:8201" - tls_disable = true - } - - storage "file" { - path = "/openbao/data" - } - # Note: service_registration "kubernetes" {} is intentionally omitted - # in standalone mode — it requires an HA-capable storage backend and - # causes a fatal error with storage "file". - ha: - enabled: false - {{- end }} - {{- if .Values.external }} - service: - type: LoadBalancer - {{- end }} - ui: - enabled: {{ .Values.ui }} - {{- if .Values.external }} - serviceType: LoadBalancer - {{- end }} - injector: - enabled: false - csi: - enabled: false diff --git a/packages/apps/openbao/templates/workloadmonitor.yaml b/packages/apps/openbao/templates/workloadmonitor.yaml deleted file mode 100644 index 56f9ec8e..00000000 --- a/packages/apps/openbao/templates/workloadmonitor.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} -spec: - replicas: {{ .Values.replicas }} - minReplicas: 1 - kind: openbao - type: openbao - selector: - app.kubernetes.io/instance: {{ $.Release.Name }}-system - version: {{ $.Chart.Version }} diff --git a/packages/apps/openbao/values.schema.json b/packages/apps/openbao/values.schema.json deleted file mode 100644 index 9b32ddd6..00000000 --- a/packages/apps/openbao/values.schema.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "title": "Chart Values", - "type": "object", - "properties": { - "replicas": { - "description": "Number of OpenBAO replicas. HA with Raft is automatically enabled when replicas \u003e 1. Switching between standalone (file storage) and HA (Raft storage) modes requires data migration.", - "type": "integer", - "default": 1 - }, - "resources": { - "description": "Explicit CPU and memory configuration for each OpenBAO replica. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "small", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, - "size": { - "description": "Persistent Volume Claim size for data storage.", - "default": "10Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, - "ui": { - "description": "Enable the OpenBAO web UI.", - "type": "boolean", - "default": true - } - } -} diff --git a/packages/apps/openbao/values.yaml b/packages/apps/openbao/values.yaml deleted file mode 100644 index fc8b75cc..00000000 --- a/packages/apps/openbao/values.yaml +++ /dev/null @@ -1,41 +0,0 @@ -## -## @section Common parameters -## - -## @typedef {struct} Resources - Explicit CPU and memory configuration for each OpenBAO replica. -## @field {quantity} [cpu] - CPU available to each replica. -## @field {quantity} [memory] - Memory (RAM) available to each replica. - -## @enum {string} ResourcesPreset - Default sizing preset. -## @value nano -## @value micro -## @value small -## @value medium -## @value large -## @value xlarge -## @value 2xlarge - -## @param {int} replicas - Number of OpenBAO replicas. HA with Raft is automatically enabled when replicas > 1. Switching between standalone (file storage) and HA (Raft storage) modes requires data migration. -replicas: 1 - -## @param {Resources} [resources] - Explicit CPU and memory configuration for each OpenBAO replica. When omitted, the preset defined in `resourcesPreset` is applied. -resources: {} - -## @param {ResourcesPreset} resourcesPreset="small" - Default sizing preset used when `resources` is omitted. -resourcesPreset: "small" - -## @param {quantity} size - Persistent Volume Claim size for data storage. -size: 10Gi - -## @param {string} storageClass - StorageClass used to store the data. -storageClass: "" - -## @param {bool} external - Enable external access from outside the cluster. -external: false - -## -## @section Application-specific parameters -## - -## @param {bool} ui - Enable the OpenBAO web UI. -ui: true diff --git a/packages/apps/opensearch/.helmignore b/packages/apps/opensearch/.helmignore deleted file mode 100644 index 0e8a0eb3..00000000 --- a/packages/apps/opensearch/.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/packages/apps/opensearch/Chart.yaml b/packages/apps/opensearch/Chart.yaml deleted file mode 100644 index 8abefadf..00000000 --- a/packages/apps/opensearch/Chart.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v2 -name: opensearch -description: Managed OpenSearch service -icon: /logos/opensearch.svg -type: application -version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process -appVersion: "2.11.1" diff --git a/packages/apps/opensearch/Makefile b/packages/apps/opensearch/Makefile deleted file mode 100644 index 1781661f..00000000 --- a/packages/apps/opensearch/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -include ../../../hack/package.mk - -.PHONY: generate update - -generate: - cozyvalues-gen -m 'opensearch' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/opensearch/types.go - ../../../hack/update-crd.sh - -update: - hack/update-versions.sh - $(MAKE) generate diff --git a/packages/apps/opensearch/README.md b/packages/apps/opensearch/README.md deleted file mode 100644 index d968c665..00000000 --- a/packages/apps/opensearch/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Managed OpenSearch Service - -## Parameters - -### Common parameters - -| Name | Description | Type | Value | -| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- | -| `replicas` | Number of OpenSearch nodes in the cluster. | `int` | `3` | -| `resources` | Explicit CPU and memory configuration for each OpenSearch node. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `resources.cpu` | CPU available to each node. | `quantity` | `""` | -| `resources.memory` | Memory (RAM) available to each node. | `quantity` | `""` | -| `resourcesPreset` | Default sizing preset used when `resources` is omitted. OpenSearch requires minimum 2Gi memory. | `string` | `large` | -| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` | -| `storageClass` | StorageClass used to store the data. | `string` | `""` | -| `external` | Enable external access from outside the cluster. | `bool` | `false` | -| `topologySpreadPolicy` | How strictly to enforce pod distribution across nodes and zones. | `string` | `soft` | -| `version` | OpenSearch major version to deploy. | `string` | `v2` | - - -### Image configuration - -| Name | Description | Type | Value | -| ------------------- | -------------------------------------- | -------- | ----- | -| `images` | Container images used by the operator. | `object` | `{}` | -| `images.opensearch` | OpenSearch image. | `string` | `""` | - - -### Node roles configuration - -| Name | Description | Type | Value | -| ------------------ | ----------------------------- | -------- | ------- | -| `nodeRoles` | Node roles configuration. | `object` | `{}` | -| `nodeRoles.master` | Enable cluster_manager role. | `bool` | `true` | -| `nodeRoles.data` | Enable data role. | `bool` | `true` | -| `nodeRoles.ingest` | Enable ingest role. | `bool` | `true` | -| `nodeRoles.ml` | Enable machine learning role. | `bool` | `false` | - - -### Users configuration - -| Name | Description | Type | Value | -| ---------------------- | -------------------------------------------------- | ------------------- | ----- | -| `users` | Custom OpenSearch users configuration map. | `map[string]object` | `{}` | -| `users[name].password` | Password for the user (auto-generated if omitted). | `string` | `""` | -| `users[name].roles` | List of OpenSearch roles. | `[]string` | `[]` | - - -### OpenSearch Dashboards configuration - -| Name | Description | Type | Value | -| ----------------------------- | ----------------------------------------------------- | ---------- | -------- | -| `dashboards` | OpenSearch Dashboards configuration. | `object` | `{}` | -| `dashboards.enabled` | Enable OpenSearch Dashboards deployment. | `bool` | `false` | -| `dashboards.replicas` | Number of Dashboards replicas. | `int` | `1` | -| `dashboards.resources` | Explicit CPU and memory configuration for Dashboards. | `object` | `{}` | -| `dashboards.resources.cpu` | CPU available to each node. | `quantity` | `""` | -| `dashboards.resources.memory` | Memory (RAM) available to each node. | `quantity` | `""` | -| `dashboards.resourcesPreset` | Default sizing preset for Dashboards. | `string` | `medium` | - diff --git a/packages/apps/opensearch/charts/cozy-lib b/packages/apps/opensearch/charts/cozy-lib deleted file mode 120000 index e1813509..00000000 --- a/packages/apps/opensearch/charts/cozy-lib +++ /dev/null @@ -1 +0,0 @@ -../../../library/cozy-lib \ No newline at end of file diff --git a/packages/apps/opensearch/files/versions.yaml b/packages/apps/opensearch/files/versions.yaml deleted file mode 100644 index be39fc80..00000000 --- a/packages/apps/opensearch/files/versions.yaml +++ /dev/null @@ -1,5 +0,0 @@ -# OpenSearch version mapping (major version -> image tag) -# Auto-generated by hack/update-versions.sh - do not edit manually -v3: "3.0.0" -v2: "2.11.1" -v1: "1.3.20" diff --git a/packages/apps/opensearch/hack/update-versions.sh b/packages/apps/opensearch/hack/update-versions.sh deleted file mode 100755 index b2c4c946..00000000 --- a/packages/apps/opensearch/hack/update-versions.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -OPENSEARCH_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -VERSIONS_FILE="${OPENSEARCH_DIR}/files/versions.yaml" - -# Supported major versions (newest first) -SUPPORTED_MAJOR_VERSIONS="3 2 1" - -echo "Supported major versions: $SUPPORTED_MAJOR_VERSIONS" - -# Check if skopeo is installed -if ! command -v skopeo &> /dev/null; then - echo "Error: skopeo is not installed. Please install skopeo and try again." >&2 - exit 1 -fi - -# Check if jq is installed -if ! command -v jq &> /dev/null; then - echo "Error: jq is not installed. Please install jq and try again." >&2 - exit 1 -fi - -# Get available image tags from Docker Hub -IMAGE="docker.io/opensearchproject/opensearch" -echo "Fetching available image tags from registry..." -TAGS=$(skopeo list-tags "docker://${IMAGE}" | jq -r '.Tags[]') - -echo "# OpenSearch version mapping (major version -> image tag)" > "${VERSIONS_FILE}" -echo "# Auto-generated by hack/update-versions.sh - do not edit manually" >> "${VERSIONS_FILE}" - -for MAJOR in $SUPPORTED_MAJOR_VERSIONS; do - # Find the latest stable release for this major version - LATEST=$(echo "$TAGS" \ - | grep -E "^${MAJOR}\.[0-9]+\.[0-9]+$" \ - | sort -t. -k1,1n -k2,2n -k3,3n \ - | tail -1) - - if [ -n "$LATEST" ]; then - echo "v${MAJOR}: latest tag is ${LATEST}" - echo "v${MAJOR}: \"${LATEST}\"" >> "${VERSIONS_FILE}" - else - echo "WARNING: No stable release found for major version ${MAJOR}" >&2 - fi -done - -echo "" -echo "Updated ${VERSIONS_FILE}:" -cat "${VERSIONS_FILE}" diff --git a/packages/apps/opensearch/logos/opensearch.svg b/packages/apps/opensearch/logos/opensearch.svg deleted file mode 100644 index 345fdd0a..00000000 --- a/packages/apps/opensearch/logos/opensearch.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/packages/apps/opensearch/templates/_versions.tpl b/packages/apps/opensearch/templates/_versions.tpl deleted file mode 100644 index 4eae4163..00000000 --- a/packages/apps/opensearch/templates/_versions.tpl +++ /dev/null @@ -1,13 +0,0 @@ -{{/* -Version mapping helper -Loads version mapping from files/versions.yaml and returns the full version for a given major version -*/}} -{{- define "opensearch.versionMap" -}} -{{- $versions := .Files.Get "files/versions.yaml" | fromYaml -}} -{{- $version := .Values.version | default "v2" -}} -{{- if hasKey $versions $version -}} -{{- index $versions $version -}} -{{- else -}} -{{- fail (printf "Invalid version '%s'. Available versions: %s" $version (keys $versions | join ", ")) -}} -{{- end -}} -{{- end -}} diff --git a/packages/apps/opensearch/templates/external-svc.yaml b/packages/apps/opensearch/templates/external-svc.yaml deleted file mode 100644 index f28626ab..00000000 --- a/packages/apps/opensearch/templates/external-svc.yaml +++ /dev/null @@ -1,39 +0,0 @@ -{{- if .Values.external }} -{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ .Release.Name }}-external - annotations: - external-dns.alpha.kubernetes.io/hostname: {{ .Release.Name }}.{{ .Release.Namespace }}.{{ $clusterDomain }} -spec: - type: LoadBalancer - selector: - opster.io/opensearch-cluster: {{ .Release.Name }} - opster.io/opensearch-nodepool: nodes - ports: - - name: https - port: 9200 - targetPort: 9200 - protocol: TCP -{{- if .Values.dashboards.enabled }} ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ .Release.Name }}-dashboards-external - annotations: - external-dns.alpha.kubernetes.io/hostname: {{ .Release.Name }}-dashboards.{{ .Release.Namespace }}.{{ $clusterDomain }} -spec: - type: LoadBalancer - selector: - opster.io/opensearch-cluster: {{ .Release.Name }} - app.kubernetes.io/component: dashboards - ports: - - name: https - port: 5601 - targetPort: 5601 - protocol: TCP -{{- end }} -{{- end }} diff --git a/packages/apps/opensearch/templates/opensearch.yaml b/packages/apps/opensearch/templates/opensearch.yaml deleted file mode 100644 index 836a3d4b..00000000 --- a/packages/apps/opensearch/templates/opensearch.yaml +++ /dev/null @@ -1,105 +0,0 @@ -{{- $topologyMode := .Values.topologySpreadPolicy | default "soft" }} -{{- $whenUnsatisfiable := "ScheduleAnyway" }} -{{- if eq $topologyMode "hard" }} -{{- $whenUnsatisfiable = "DoNotSchedule" }} -{{- end }} ---- -apiVersion: opensearch.opster.io/v1 -kind: OpenSearchCluster -metadata: - name: {{ .Release.Name }} -spec: - general: - serviceName: {{ .Release.Name }} - version: {{ include "opensearch.versionMap" $ }} - httpPort: 9200 - setVMMaxMapCount: true - drainDataNodes: true - {{- if gt (len .Values.images.opensearch) 0 }} - image: {{ .Values.images.opensearch }} - {{- end }} - bootstrap: - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 6 }} - security: - tls: - transport: - generate: true - perNode: true - http: - generate: true - config: - securityConfigSecret: - name: {{ .Release.Name }}-security-config - adminCredentialsSecret: - name: {{ .Release.Name }}-admin-credentials - {{- if .Values.dashboards.enabled }} - dashboards: - enable: true - version: {{ include "opensearch.versionMap" $ }} - replicas: {{ .Values.dashboards.replicas | default 1 }} - tls: - enable: true - generate: true - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list (.Values.dashboards.resourcesPreset | default "medium") .Values.dashboards.resources $) | nindent 6 }} - {{- end }} - nodePools: - - component: nodes - replicas: {{ .Values.replicas }} - diskSize: {{ .Values.size }} - persistence: - pvc: - accessModes: - - ReadWriteOnce - {{- if .Values.storageClass }} - storageClass: {{ .Values.storageClass }} - {{- else if eq (int .Values.replicas) 1 }} - storageClass: replicated - {{- else }} - storageClass: local - {{- end }} - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 8 }} - {{- if not (or .Values.nodeRoles.master .Values.nodeRoles.data .Values.nodeRoles.ingest .Values.nodeRoles.ml) }} - {{- fail "At least one node role must be enabled (master, data, ingest, or ml)" }} - {{- end }} - roles: - {{- if .Values.nodeRoles.master }} - - cluster_manager - {{- end }} - {{- if .Values.nodeRoles.data }} - - data - {{- end }} - {{- if .Values.nodeRoles.ingest }} - - ingest - {{- end }} - {{- if .Values.nodeRoles.ml }} - - ml - {{- end }} - topologySpreadConstraints: - - maxSkew: 1 - topologyKey: kubernetes.io/hostname - whenUnsatisfiable: {{ $whenUnsatisfiable }} - labelSelector: - matchLabels: - opster.io/opensearch-cluster: {{ .Release.Name }} - - maxSkew: 1 - topologyKey: topology.kubernetes.io/zone - whenUnsatisfiable: {{ $whenUnsatisfiable }} - labelSelector: - matchLabels: - opster.io/opensearch-cluster: {{ .Release.Name }} ---- -# WorkloadMonitor tracks OpenSearch pods -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} -spec: - replicas: {{ .Values.replicas }} - minReplicas: 1 - kind: opensearch - type: opensearch - selector: - opster.io/opensearch-cluster: {{ .Release.Name }} - version: {{ .Chart.Version }} diff --git a/packages/apps/opensearch/templates/security.yaml b/packages/apps/opensearch/templates/security.yaml deleted file mode 100644 index d10d353a..00000000 --- a/packages/apps/opensearch/templates/security.yaml +++ /dev/null @@ -1,120 +0,0 @@ -{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }} -{{- $existingAdminCreds := lookup "v1" "Secret" .Release.Namespace (printf "%s-admin-credentials" .Release.Name) }} -{{- $existingSecurityConfig := lookup "v1" "Secret" .Release.Namespace (printf "%s-security-config" .Release.Name) }} -{{- $password := randAlphaNum 32 }} -{{- if and $existingAdminCreds (hasKey $existingAdminCreds.data "password") }} -{{- $password = index $existingAdminCreds.data "password" | b64dec }} -{{- end }} ---- -# Admin credentials for the OpenSearch operator (referenced by adminCredentialsSecret) -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-admin-credentials - labels: - app.kubernetes.io/name: opensearch - app.kubernetes.io/instance: {{ .Release.Name }} -type: Opaque -stringData: - username: admin - password: {{ $password | quote }} ---- -# Security plugin configuration (referenced by securityConfigSecret) -# On upgrades, the existing secret is preserved to avoid bcrypt hash regeneration -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-security-config - labels: - app.kubernetes.io/name: opensearch - app.kubernetes.io/instance: {{ .Release.Name }} -type: Opaque -{{- if and $existingSecurityConfig (hasKey $existingSecurityConfig.data "internal_users.yml") }} -data: - {{- range $key, $val := $existingSecurityConfig.data }} - {{ $key }}: {{ $val }} - {{- end }} -{{- else }} -stringData: - config.yml: | - --- - _meta: - type: "config" - config_version: 2 - config: - dynamic: - http: - anonymous_auth_enabled: false - authc: - basic_internal_auth_domain: - description: "Authenticate via HTTP Basic against internal users database" - http_enabled: true - transport_enabled: true - order: 0 - http_authenticator: - type: basic - challenge: true - authentication_backend: - type: internal - - internal_users.yml: | - --- - _meta: - type: "internalusers" - config_version: 2 - admin: - hash: {{ htpasswd "admin" $password | trimPrefix "admin:" | quote }} - reserved: true - backend_roles: - - "admin" - description: "Admin user" - - roles.yml: | - --- - _meta: - type: "roles" - config_version: 2 - - roles_mapping.yml: | - --- - _meta: - type: "rolesmapping" - config_version: 2 - all_access: - reserved: false - backend_roles: - - "admin" - - action_groups.yml: | - --- - _meta: - type: "actiongroups" - config_version: 2 - - tenants.yml: | - --- - _meta: - type: "tenants" - config_version: 2 -{{- end }} ---- -# User-facing credentials with connection URI -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-credentials - labels: - app.kubernetes.io/name: opensearch - app.kubernetes.io/instance: {{ .Release.Name }} -type: Opaque -stringData: - username: admin - password: {{ $password | quote }} - host: {{ .Release.Name }}.{{ .Release.Namespace }}.svc.{{ $clusterDomain }} - port: "9200" - uri: https://admin:{{ $password | urlquery }}@{{ .Release.Name }}.{{ .Release.Namespace }}.svc.{{ $clusterDomain }}:9200 - {{- if .Values.dashboards.enabled }} - dashboards-host: {{ .Release.Name }}-dashboards.{{ .Release.Namespace }}.svc.{{ $clusterDomain }} - dashboards-port: "5601" - dashboards-uri: https://admin:{{ $password | urlquery }}@{{ .Release.Name }}-dashboards.{{ .Release.Namespace }}.svc.{{ $clusterDomain }}:5601 - {{- end }} diff --git a/packages/apps/opensearch/templates/users.yaml b/packages/apps/opensearch/templates/users.yaml deleted file mode 100644 index 1d326206..00000000 --- a/packages/apps/opensearch/templates/users.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- range $username, $user := .Values.users }} -{{- $existingSecret := lookup "v1" "Secret" $.Release.Namespace (printf "%s-user-%s" $.Release.Name $username) }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ $.Release.Name }}-user-{{ $username }} - labels: - opensearch.opster.io/credentials: "true" -type: kubernetes.io/basic-auth -stringData: - username: {{ $username | quote }} - {{- if $user.password }} - password: {{ $user.password | quote }} - {{- else if and $existingSecret (hasKey $existingSecret.data "password") }} - password: {{ index $existingSecret.data "password" | b64dec | quote }} - {{- else }} - password: {{ randAlphaNum 16 | quote }} - {{- end }} - roles: {{ $user.roles | default (list "readall") | join "," | quote }} -{{- end }} diff --git a/packages/apps/opensearch/tests/opensearch_test.yaml b/packages/apps/opensearch/tests/opensearch_test.yaml deleted file mode 100644 index 2959ec18..00000000 --- a/packages/apps/opensearch/tests/opensearch_test.yaml +++ /dev/null @@ -1,532 +0,0 @@ -suite: opensearch CR tests - -templates: - - templates/opensearch.yaml - -tests: - ################### - # Basic rendering # - ################### - - - it: renders OpenSearchCluster and WorkloadMonitor - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - hasDocuments: - count: 2 - - isKind: - of: OpenSearchCluster - documentIndex: 0 - - isKind: - of: WorkloadMonitor - documentIndex: 1 - - - it: sets correct CR name - release: - name: my-opensearch - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: metadata.name - value: my-opensearch - documentIndex: 0 - - ################## - # Version # - ################## - - - it: defaults to version 2.11.1 - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.general.version - value: "2.11.1" - documentIndex: 0 - - - it: sets version 3.0.0 when v3 selected - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - version: v3 - asserts: - - equal: - path: spec.general.version - value: "3.0.0" - documentIndex: 0 - - - it: sets version 1.3.20 when v1 selected - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - version: v1 - asserts: - - equal: - path: spec.general.version - value: "1.3.20" - documentIndex: 0 - - ##################### - # General # - ##################### - - - it: sets drainDataNodes to true - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.general.drainDataNodes - value: true - documentIndex: 0 - - - it: sets httpPort to 9200 - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.general.httpPort - value: 9200 - documentIndex: 0 - - ##################### - # Security # - ##################### - - - it: always includes security section with TLS - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.security.tls.transport.generate - value: true - documentIndex: 0 - - equal: - path: spec.security.tls.transport.perNode - value: true - documentIndex: 0 - - equal: - path: spec.security.tls.http.generate - value: true - documentIndex: 0 - - - it: references security config secret - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.security.config.securityConfigSecret.name - value: test-os-security-config - documentIndex: 0 - - - it: references admin credentials secret - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.security.config.adminCredentialsSecret.name - value: test-os-admin-credentials - documentIndex: 0 - - - it: does not disable security plugin - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - notExists: - path: spec.general.additionalConfig - documentIndex: 0 - - ##################### - # Node Pools # - ##################### - - - it: sets default replica count to 3 - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.nodePools[0].replicas - value: 3 - documentIndex: 0 - - - it: sets replica count from values - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - replicas: 5 - asserts: - - equal: - path: spec.nodePools[0].replicas - value: 5 - documentIndex: 0 - - ##################### - # Node Roles # - ##################### - - - it: enables default node roles - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - contains: - path: spec.nodePools[0].roles - content: cluster_manager - documentIndex: 0 - - contains: - path: spec.nodePools[0].roles - content: data - documentIndex: 0 - - contains: - path: spec.nodePools[0].roles - content: ingest - documentIndex: 0 - - - it: disables master role when configured - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - nodeRoles: - master: false - data: true - ingest: true - ml: false - asserts: - - notContains: - path: spec.nodePools[0].roles - content: cluster_manager - documentIndex: 0 - - - it: fails when all node roles are disabled - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - nodeRoles: - master: false - data: false - ingest: false - ml: false - asserts: - - failedTemplate: - errorMessage: "At least one node role must be enabled (master, data, ingest, or ml)" - - - it: enables ml role when configured - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - nodeRoles: - master: true - data: true - ingest: true - ml: true - asserts: - - contains: - path: spec.nodePools[0].roles - content: ml - documentIndex: 0 - - ########################### - # Topology Spread Policy # - ########################### - - - it: uses soft topology spread by default (ScheduleAnyway) - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.nodePools[0].topologySpreadConstraints[0].whenUnsatisfiable - value: ScheduleAnyway - documentIndex: 0 - - equal: - path: spec.nodePools[0].topologySpreadConstraints[1].whenUnsatisfiable - value: ScheduleAnyway - documentIndex: 0 - - - it: uses hard topology spread when configured (DoNotSchedule) - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - topologySpreadPolicy: hard - asserts: - - equal: - path: spec.nodePools[0].topologySpreadConstraints[0].whenUnsatisfiable - value: DoNotSchedule - documentIndex: 0 - - equal: - path: spec.nodePools[0].topologySpreadConstraints[1].whenUnsatisfiable - value: DoNotSchedule - documentIndex: 0 - - - it: sets correct topology keys - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.nodePools[0].topologySpreadConstraints[0].topologyKey - value: kubernetes.io/hostname - documentIndex: 0 - - equal: - path: spec.nodePools[0].topologySpreadConstraints[1].topologyKey - value: topology.kubernetes.io/zone - documentIndex: 0 - - ##################### - # Storage # - ##################### - - - it: sets accessModes to ReadWriteOnce - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - contains: - path: spec.nodePools[0].persistence.pvc.accessModes - content: ReadWriteOnce - documentIndex: 0 - - - it: sets storage size from values - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - size: 50Gi - asserts: - - equal: - path: spec.nodePools[0].diskSize - value: 50Gi - documentIndex: 0 - - - it: uses local storageClass when replicas > 1 and no storageClass - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - storageClass: "" - replicas: 3 - asserts: - - equal: - path: spec.nodePools[0].persistence.pvc.storageClass - value: local - documentIndex: 0 - - - it: uses replicated storageClass when single replica and no storageClass - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - storageClass: "" - replicas: 1 - asserts: - - equal: - path: spec.nodePools[0].persistence.pvc.storageClass - value: replicated - documentIndex: 0 - - - it: uses custom storageClass when provided - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - storageClass: fast-ssd - asserts: - - equal: - path: spec.nodePools[0].persistence.pvc.storageClass - value: fast-ssd - documentIndex: 0 - - ##################### - # Dashboards # - ##################### - - - it: does not render dashboards when disabled - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - dashboards: - enabled: false - replicas: 1 - resourcesPreset: "medium" - resources: {} - asserts: - - notExists: - path: spec.dashboards - documentIndex: 0 - - - it: renders dashboards when enabled - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - dashboards: - enabled: true - replicas: 1 - resourcesPreset: "medium" - resources: {} - asserts: - - equal: - path: spec.dashboards.enable - value: true - documentIndex: 0 - - equal: - path: spec.dashboards.replicas - value: 1 - documentIndex: 0 - - equal: - path: spec.dashboards.tls.enable - value: true - documentIndex: 0 - - equal: - path: spec.dashboards.tls.generate - value: true - documentIndex: 0 - - ########################### - # WorkloadMonitor # - ########################### - - - it: creates WorkloadMonitor with correct metadata - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: metadata.name - value: test-os - documentIndex: 1 - - equal: - path: spec.kind - value: opensearch - documentIndex: 1 - - equal: - path: spec.type - value: opensearch - documentIndex: 1 - - - it: sets replicas in WorkloadMonitor - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - replicas: 5 - asserts: - - equal: - path: spec.replicas - value: 5 - documentIndex: 1 - - - it: sets minReplicas to 1 - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.minReplicas - value: 1 - documentIndex: 1 - - - it: sets correct selector labels - release: - name: mydb - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: spec.selector["opster.io/opensearch-cluster"] - value: mydb - documentIndex: 1 diff --git a/packages/apps/opensearch/tests/security_test.yaml b/packages/apps/opensearch/tests/security_test.yaml deleted file mode 100644 index cd8740d9..00000000 --- a/packages/apps/opensearch/tests/security_test.yaml +++ /dev/null @@ -1,207 +0,0 @@ -suite: security secrets tests - -templates: - - templates/security.yaml - -tests: - ################### - # Basic rendering # - ################### - - - it: renders three secrets (admin-credentials, security-config, credentials) - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - hasDocuments: - count: 3 - - ########################### - # Admin credentials # - ########################### - - - it: sets admin-credentials secret name - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: metadata.name - value: test-os-admin-credentials - documentIndex: 0 - - - it: sets admin username - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: stringData.username - value: admin - documentIndex: 0 - - - it: generates a 32-char alphanumeric password - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - matchRegex: - path: stringData.password - pattern: "^[a-zA-Z0-9]{32}$" - documentIndex: 0 - - ########################### - # Security config # - ########################### - - - it: sets security-config secret name - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: metadata.name - value: test-os-security-config - documentIndex: 1 - - - it: includes config.yml with basic auth - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - exists: - path: stringData["config.yml"] - documentIndex: 1 - - - it: includes internal_users.yml with bcrypt hash - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - matchRegex: - path: stringData["internal_users.yml"] - pattern: "hash:.*\\$2a\\$" - documentIndex: 1 - - - it: includes roles_mapping.yml - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - exists: - path: stringData["roles_mapping.yml"] - documentIndex: 1 - - ########################### - # User-facing credentials # - ########################### - - - it: sets credentials secret name - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: metadata.name - value: test-os-credentials - documentIndex: 2 - - - it: sets correct host and port - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - equal: - path: stringData.host - value: test-os.tenant-test.svc.cozy.local - documentIndex: 2 - - equal: - path: stringData.port - value: "9200" - documentIndex: 2 - - - it: sets https URI with credentials - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - asserts: - - matchRegex: - path: stringData.uri - pattern: "^https://admin:[a-zA-Z0-9]{32}@test-os\\.tenant-test\\.svc\\.cozy\\.local:9200$" - documentIndex: 2 - - - it: does not include dashboards fields when dashboards disabled - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - dashboards: - enabled: false - replicas: 1 - resourcesPreset: "medium" - resources: {} - asserts: - - notExists: - path: stringData.dashboards-host - documentIndex: 2 - - - it: includes dashboards fields when dashboards enabled - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - dashboards: - enabled: true - replicas: 1 - resourcesPreset: "medium" - resources: {} - asserts: - - equal: - path: stringData.dashboards-host - value: test-os-dashboards.tenant-test.svc.cozy.local - documentIndex: 2 - - equal: - path: stringData.dashboards-port - value: "5601" - documentIndex: 2 - - matchRegex: - path: stringData.dashboards-uri - pattern: "^https://admin:[a-zA-Z0-9]{32}@test-os-dashboards\\.tenant-test\\.svc\\.cozy\\.local:5601$" - documentIndex: 2 diff --git a/packages/apps/opensearch/tests/users_test.yaml b/packages/apps/opensearch/tests/users_test.yaml deleted file mode 100644 index f6b4990e..00000000 --- a/packages/apps/opensearch/tests/users_test.yaml +++ /dev/null @@ -1,176 +0,0 @@ -suite: users secrets tests - -templates: - - templates/users.yaml - -tests: - ################### - # Basic rendering # - ################### - - - it: does not render secrets when no users defined - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: {} - asserts: - - hasDocuments: - count: 0 - - - it: renders one secret per user - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - user1: - roles: - - readall - user2: - roles: - - all_access - asserts: - - hasDocuments: - count: 2 - - ##################### - # Secret metadata # - ##################### - - - it: sets correct secret name - release: - name: my-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - myuser: - roles: - - readall - asserts: - - equal: - path: metadata.name - value: my-os-user-myuser - - - it: sets opensearch credentials label - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - myuser: - roles: - - readall - asserts: - - equal: - path: metadata.labels["opensearch.opster.io/credentials"] - value: "true" - - - it: uses basic-auth secret type - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - myuser: - roles: - - readall - asserts: - - equal: - path: type - value: kubernetes.io/basic-auth - - ##################### - # Secret data # - ##################### - - - it: sets username in secret - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - testuser: - roles: - - readall - asserts: - - equal: - path: stringData.username - value: testuser - - - it: uses provided password - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - myuser: - password: mysecretpassword - roles: - - readall - asserts: - - equal: - path: stringData.password - value: mysecretpassword - - - it: generates password when not provided - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - myuser: - roles: - - readall - asserts: - - matchRegex: - path: stringData.password - pattern: "^[a-zA-Z0-9]{16}$" - - - it: sets roles as comma-separated string - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - myuser: - roles: - - readall - - reporting_user - - monitoring_user - asserts: - - equal: - path: stringData.roles - value: "readall,reporting_user,monitoring_user" - - - it: defaults to readall role when no roles specified - release: - name: test-os - namespace: tenant-test - set: - _cluster: - cluster-domain: cozy.local - users: - myuser: {} - asserts: - - equal: - path: stringData.roles - value: "readall" diff --git a/packages/apps/opensearch/values.schema.json b/packages/apps/opensearch/values.schema.json deleted file mode 100644 index 04b530ba..00000000 --- a/packages/apps/opensearch/values.schema.json +++ /dev/null @@ -1,239 +0,0 @@ -{ - "title": "Chart Values", - "type": "object", - "properties": { - "replicas": { - "description": "Number of OpenSearch nodes in the cluster.", - "type": "integer", - "default": 3 - }, - "resources": { - "description": "Explicit CPU and memory configuration for each OpenSearch node. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU available to each node.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available to each node.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted. OpenSearch requires minimum 2Gi memory.", - "type": "string", - "default": "large", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, - "size": { - "description": "Persistent Volume Claim size available for application data.", - "default": "10Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, - "topologySpreadPolicy": { - "description": "How strictly to enforce pod distribution across nodes and zones.", - "type": "string", - "default": "soft", - "enum": [ - "soft", - "hard" - ] - }, - "version": { - "description": "OpenSearch major version to deploy.", - "type": "string", - "default": "v2", - "enum": [ - "v3", - "v2", - "v1" - ] - }, - "images": { - "description": "Container images used by the operator.", - "type": "object", - "default": {}, - "required": [ - "opensearch" - ], - "properties": { - "opensearch": { - "description": "OpenSearch image.", - "type": "string", - "default": "" - } - } - }, - "nodeRoles": { - "description": "Node roles configuration.", - "type": "object", - "default": {}, - "required": [ - "data", - "ingest", - "master", - "ml" - ], - "properties": { - "data": { - "description": "Enable data role.", - "type": "boolean", - "default": true - }, - "ingest": { - "description": "Enable ingest role.", - "type": "boolean", - "default": true - }, - "master": { - "description": "Enable cluster_manager role.", - "type": "boolean", - "default": true - }, - "ml": { - "description": "Enable machine learning role.", - "type": "boolean", - "default": false - } - } - }, - "users": { - "description": "Custom OpenSearch users configuration map.", - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "properties": { - "password": { - "description": "Password for the user (auto-generated if omitted).", - "type": "string" - }, - "roles": { - "description": "List of OpenSearch roles.", - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "dashboards": { - "description": "OpenSearch Dashboards configuration.", - "type": "object", - "default": {}, - "required": [ - "enabled", - "replicas", - "resourcesPreset" - ], - "properties": { - "enabled": { - "description": "Enable OpenSearch Dashboards deployment.", - "type": "boolean", - "default": false - }, - "replicas": { - "description": "Number of Dashboards replicas.", - "type": "integer", - "default": 1 - }, - "resources": { - "description": "Explicit CPU and memory configuration for Dashboards.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU available to each node.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available to each node.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset for Dashboards.", - "type": "string", - "default": "medium", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - } - } - } - } -} diff --git a/packages/apps/opensearch/values.yaml b/packages/apps/opensearch/values.yaml deleted file mode 100644 index 8de805e3..00000000 --- a/packages/apps/opensearch/values.yaml +++ /dev/null @@ -1,111 +0,0 @@ -## -## @section Common parameters -## - -## @typedef {struct} Resources - Explicit CPU and memory configuration for each OpenSearch node. -## @field {quantity} [cpu] - CPU available to each node. -## @field {quantity} [memory] - Memory (RAM) available to each node. - -## @enum {string} ResourcesPreset - Default sizing preset. -## @value nano -## @value micro -## @value small -## @value medium -## @value large -## @value xlarge -## @value 2xlarge - -## @param {int} replicas - Number of OpenSearch nodes in the cluster. -replicas: 3 - -## @param {Resources} [resources] - Explicit CPU and memory configuration for each OpenSearch node. When omitted, the preset defined in `resourcesPreset` is applied. -resources: {} - -## @param {ResourcesPreset} resourcesPreset="large" - Default sizing preset used when `resources` is omitted. OpenSearch requires minimum 2Gi memory. -resourcesPreset: "large" - -## @param {quantity} size - Persistent Volume Claim size available for application data. -size: 10Gi - -## @param {string} storageClass - StorageClass used to store the data. -storageClass: "" - -## @param {bool} external - Enable external access from outside the cluster. -external: false - -## @enum {string} TopologySpreadPolicy - Pod distribution policy across nodes/zones. -## @value soft - Best-effort distribution (ScheduleAnyway) - pods may be scheduled on same node if needed -## @value hard - Strict distribution (DoNotSchedule) - pods will not schedule if spread cannot be achieved - -## @param {TopologySpreadPolicy} topologySpreadPolicy="soft" - How strictly to enforce pod distribution across nodes and zones. -topologySpreadPolicy: "soft" - -## -## @enum {string} Version -## @value v3 -## @value v2 -## @value v1 - -## @param {Version} version - OpenSearch major version to deploy. -version: v2 - -## -## @section Image configuration -## - -## @typedef {struct} Images - Container image configuration. -## @field {string} opensearch - OpenSearch image. - -## @param {Images} images - Container images used by the operator. -images: - opensearch: "" - -## -## @section Node roles configuration -## - -## @typedef {struct} NodeRoles - OpenSearch node roles. -## @field {bool} master - Enable cluster_manager role. -## @field {bool} data - Enable data role. -## @field {bool} ingest - Enable ingest role. -## @field {bool} ml - Enable machine learning role. - -## @param {NodeRoles} nodeRoles - Node roles configuration. -nodeRoles: - master: true - data: true - ingest: true - ml: false - -## -## @section Users configuration -## - -## @typedef {struct} User - User configuration. -## @field {string} [password] - Password for the user (auto-generated if omitted). -## @field {[]string} roles - List of OpenSearch roles. - -## @param {map[string]User} users - Custom OpenSearch users configuration map. -users: {} -## Example: -## users: -## myuser: -## roles: -## - all_access - -## -## @section OpenSearch Dashboards configuration -## - -## @typedef {struct} Dashboards - OpenSearch Dashboards deployment configuration. -## @field {bool} enabled - Enable OpenSearch Dashboards deployment. -## @field {int} replicas - Number of Dashboards replicas. -## @field {Resources} [resources] - Explicit CPU and memory configuration for Dashboards. -## @field {ResourcesPreset} resourcesPreset - Default sizing preset for Dashboards. - -## @param {Dashboards} dashboards - OpenSearch Dashboards configuration. -dashboards: - enabled: false - replicas: 1 - resources: {} - resourcesPreset: "medium" diff --git a/packages/apps/postgres/Makefile b/packages/apps/postgres/Makefile index dff0b9c6..aa9b0ccc 100644 --- a/packages/apps/postgres/Makefile +++ b/packages/apps/postgres/Makefile @@ -1,7 +1,7 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'postgresql' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/postgresql/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh update: diff --git a/packages/apps/postgres/README.md b/packages/apps/postgres/README.md index 4cda7284..5a550f7a 100644 --- a/packages/apps/postgres/README.md +++ b/packages/apps/postgres/README.md @@ -133,13 +133,12 @@ See: ### Bootstrap (recovery) parameters -| Name | Description | Type | Value | -| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | -| `bootstrap` | Bootstrap configuration. | `object` | `{}` | -| `bootstrap.enabled` | Whether to restore from a backup. | `bool` | `false` | -| `bootstrap.recoveryTime` | Timestamp (RFC3339) for point-in-time recovery; empty means latest. | `string` | `""` | -| `bootstrap.oldName` | Previous cluster name before deletion. | `string` | `""` | -| `bootstrap.serverName` | Barman server name (S3 path prefix) used by the original cluster when writing backups. Set this only when the original cluster had an explicit barmanObjectStore.serverName that differed from its Kubernetes resource name. | `string` | `""` | +| Name | Description | Type | Value | +| ------------------------ | ------------------------------------------------------------------- | -------- | ------- | +| `bootstrap` | Bootstrap configuration. | `object` | `{}` | +| `bootstrap.enabled` | Whether to restore from a backup. | `bool` | `false` | +| `bootstrap.recoveryTime` | Timestamp (RFC3339) for point-in-time recovery; empty means latest. | `string` | `""` | +| `bootstrap.oldName` | Previous cluster name before deletion. | `string` | `""` | ## Parameter examples and reference diff --git a/packages/apps/postgres/templates/db.yaml b/packages/apps/postgres/templates/db.yaml index 2cdaec1d..7557c436 100644 --- a/packages/apps/postgres/templates/db.yaml +++ b/packages/apps/postgres/templates/db.yaml @@ -32,9 +32,6 @@ spec: - name: {{ .Values.bootstrap.oldName }} barmanObjectStore: destinationPath: {{ .Values.backup.destinationPath }} - {{- if .Values.bootstrap.serverName }} - serverName: {{ .Values.bootstrap.serverName }} - {{- end }} endpointURL: {{ .Values.backup.endpointURL }} s3Credentials: accessKeyId: @@ -87,8 +84,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 diff --git a/packages/apps/postgres/templates/init-script.yaml b/packages/apps/postgres/templates/init-script.yaml index 500d54d4..80f7c4c7 100644 --- a/packages/apps/postgres/templates/init-script.yaml +++ b/packages/apps/postgres/templates/init-script.yaml @@ -66,38 +66,6 @@ stringData: EOT done - echo "== delete databases" - MANAGED_DBS=$(psql -v ON_ERROR_STOP=1 -t -A -c "SELECT datname FROM pg_database d JOIN pg_shdescription s ON d.oid = s.objoid WHERE s.description = 'database managed by helm'") - DEFINED_DBS="{{ join " " (keys .Values.databases) }}" - DELETE_DBS=$(for db in $MANAGED_DBS; do case " $DEFINED_DBS " in *" $db "*) :;; *) echo $db;; esac; done) - - echo "databases to delete: $DELETE_DBS" - for db in $DELETE_DBS; do - psql -v ON_ERROR_STOP=1 --echo-all -c "DROP DATABASE IF EXISTS \"$db\" WITH (FORCE);" - done - - echo "== delete orphaned managed roles" - MANAGED_ROLES=$(psql -v ON_ERROR_STOP=1 -t -A -c "SELECT rolname FROM pg_roles r JOIN pg_shdescription s ON r.oid = s.objoid WHERE s.description = 'role managed by helm'") - DEFINED_ROLES="{{ range $database, $d := .Values.databases }}{{ $database }}_admin {{ $database }}_readonly {{ end }}" - DELETE_ROLES=$(for role in $MANAGED_ROLES; do case " $DEFINED_ROLES " in *" $role "*) :;; *) echo $role;; esac; done) - - echo "roles to delete: $DELETE_ROLES" - for role in $DELETE_ROLES; do - psql -v ON_ERROR_STOP=1 --echo-all < 1. | `int` | `1` | -| `resources` | Explicit CPU and memory configuration for each Qdrant replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `resources.cpu` | CPU available to each replica. | `quantity` | `""` | -| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` | -| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `size` | Persistent Volume Claim size available for vector data storage. | `quantity` | `10Gi` | -| `storageClass` | StorageClass used to store the data. | `string` | `""` | -| `external` | Enable external access from outside the cluster. | `bool` | `false` | - - -## Parameter examples and reference - -### resources and resourcesPreset - -`resources` sets explicit CPU and memory configurations for each replica. -When left empty, the preset defined in `resourcesPreset` is applied. - -```yaml -resources: - cpu: 4000m - memory: 4Gi -``` - -`resourcesPreset` sets named CPU and memory configurations for each replica. -This setting is ignored if the corresponding `resources` value is set. - -| Preset name | CPU | memory | -|-------------|--------|---------| -| `nano` | `250m` | `128Mi` | -| `micro` | `500m` | `256Mi` | -| `small` | `1` | `512Mi` | -| `medium` | `1` | `1Gi` | -| `large` | `2` | `2Gi` | -| `xlarge` | `4` | `4Gi` | -| `2xlarge` | `8` | `8Gi` | diff --git a/packages/apps/qdrant/charts/cozy-lib b/packages/apps/qdrant/charts/cozy-lib deleted file mode 120000 index e1813509..00000000 --- a/packages/apps/qdrant/charts/cozy-lib +++ /dev/null @@ -1 +0,0 @@ -../../../library/cozy-lib \ No newline at end of file diff --git a/packages/apps/qdrant/logos/qdrant.svg b/packages/apps/qdrant/logos/qdrant.svg deleted file mode 100644 index 3c940b5e..00000000 --- a/packages/apps/qdrant/logos/qdrant.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/packages/apps/qdrant/templates/dashboard-resourcemap.yaml b/packages/apps/qdrant/templates/dashboard-resourcemap.yaml deleted file mode 100644 index 0986951f..00000000 --- a/packages/apps/qdrant/templates/dashboard-resourcemap.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ .Release.Name }}-dashboard-resources -rules: -- apiGroups: - - "" - resources: - - services - resourceNames: - - {{ .Release.Name }} - - {{ .Release.Name }}-headless - verbs: ["get", "list", "watch"] -- apiGroups: - - "" - resources: - - secrets - resourceNames: - - {{ .Release.Name }}-apikey - verbs: ["get", "list", "watch"] -- apiGroups: - - cozystack.io - resources: - - workloadmonitors - resourceNames: - - {{ .Release.Name }} - verbs: ["get", "list", "watch"] ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ .Release.Name }}-dashboard-resources -subjects: -{{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "use" .Release.Namespace) }} -roleRef: - kind: Role - name: {{ .Release.Name }}-dashboard-resources - apiGroup: rbac.authorization.k8s.io ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} -spec: - minReplicas: 1 - replicas: {{ .Values.replicas }} - kind: qdrant - type: qdrant - selector: - app.kubernetes.io/instance: {{ .Release.Name }}-system - version: {{ .Chart.Version }} diff --git a/packages/apps/qdrant/templates/qdrant.yaml b/packages/apps/qdrant/templates/qdrant.yaml deleted file mode 100644 index 888bd05e..00000000 --- a/packages/apps/qdrant/templates/qdrant.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ .Release.Name }}-system - labels: - sharding.fluxcd.io/key: tenants -spec: - chartRef: - kind: ExternalArtifact - name: cozystack-qdrant-application-default-qdrant-system - namespace: cozy-system - interval: 5m - timeout: 10m - install: - remediation: - retries: -1 - upgrade: - force: true - remediation: - retries: -1 - valuesFrom: - - kind: Secret - name: cozystack-values - values: - qdrant: - fullnameOverride: {{ .Release.Name }} - replicaCount: {{ .Values.replicas }} - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 8 }} - apiKey: true - livenessProbe: - enabled: true - persistence: - size: {{ .Values.size }} - {{- with .Values.storageClass }} - storageClassName: {{ . }} - {{- end }} - metrics: - serviceMonitor: - enabled: true - {{- if .Values.external }} - service: - type: LoadBalancer - {{- end }} diff --git a/packages/apps/qdrant/values.schema.json b/packages/apps/qdrant/values.schema.json deleted file mode 100644 index 90af7c3d..00000000 --- a/packages/apps/qdrant/values.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "title": "Chart Values", - "type": "object", - "properties": { - "replicas": { - "description": "Number of Qdrant replicas. Cluster mode is automatically enabled when replicas \u003e 1.", - "type": "integer", - "default": 1 - }, - "resources": { - "description": "Explicit CPU and memory configuration for each Qdrant replica. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "small", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, - "size": { - "description": "Persistent Volume Claim size available for vector data storage.", - "default": "10Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - } - } -} diff --git a/packages/apps/qdrant/values.yaml b/packages/apps/qdrant/values.yaml deleted file mode 100644 index 7abd25ff..00000000 --- a/packages/apps/qdrant/values.yaml +++ /dev/null @@ -1,34 +0,0 @@ -## -## @section Common parameters -## - -## @typedef {struct} Resources - Explicit CPU and memory configuration for each Qdrant replica. -## @field {quantity} [cpu] - CPU available to each replica. -## @field {quantity} [memory] - Memory (RAM) available to each replica. - -## @enum {string} ResourcesPreset - Default sizing preset. -## @value nano -## @value micro -## @value small -## @value medium -## @value large -## @value xlarge -## @value 2xlarge - -## @param {int} replicas - Number of Qdrant replicas. Cluster mode is automatically enabled when replicas > 1. -replicas: 1 - -## @param {Resources} [resources] - Explicit CPU and memory configuration for each Qdrant replica. When omitted, the preset defined in `resourcesPreset` is applied. -resources: {} - -## @param {ResourcesPreset} resourcesPreset="small" - Default sizing preset used when `resources` is omitted. -resourcesPreset: "small" - -## @param {quantity} size - Persistent Volume Claim size available for vector data storage. -size: 10Gi - -## @param {string} storageClass - StorageClass used to store the data. -storageClass: "" - -## @param {bool} external - Enable external access from outside the cluster. -external: false diff --git a/packages/apps/rabbitmq/Chart.yaml b/packages/apps/rabbitmq/Chart.yaml index e764e7dd..13500669 100644 --- a/packages/apps/rabbitmq/Chart.yaml +++ b/packages/apps/rabbitmq/Chart.yaml @@ -4,4 +4,4 @@ description: Managed RabbitMQ service icon: /logos/rabbitmq.svg type: application version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process -appVersion: "4.2.4" +appVersion: "3.13.2" diff --git a/packages/apps/rabbitmq/Makefile b/packages/apps/rabbitmq/Makefile index 9b045b66..d1cfda8e 100644 --- a/packages/apps/rabbitmq/Makefile +++ b/packages/apps/rabbitmq/Makefile @@ -1,9 +1,5 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'rabbitmq' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/rabbitmq/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh - -update: - hack/update-versions.sh - make generate diff --git a/packages/apps/rabbitmq/README.md b/packages/apps/rabbitmq/README.md index b1f01f21..4b19c7b3 100644 --- a/packages/apps/rabbitmq/README.md +++ b/packages/apps/rabbitmq/README.md @@ -23,7 +23,6 @@ The service utilizes official RabbitMQ operator. This ensures the reliability an | `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` | | `storageClass` | StorageClass used to store the data. | `string` | `""` | | `external` | Enable external access from outside the cluster. | `bool` | `false` | -| `version` | RabbitMQ major.minor version to deploy | `string` | `v4.2` | ### Application-specific parameters diff --git a/packages/apps/rabbitmq/files/versions.yaml b/packages/apps/rabbitmq/files/versions.yaml deleted file mode 100644 index 0cf87dd0..00000000 --- a/packages/apps/rabbitmq/files/versions.yaml +++ /dev/null @@ -1,4 +0,0 @@ -"v4.2": "4.2.4" -"v4.1": "4.1.8" -"v4.0": "4.0.9" -"v3.13": "3.13.7" diff --git a/packages/apps/rabbitmq/hack/update-versions.sh b/packages/apps/rabbitmq/hack/update-versions.sh deleted file mode 100755 index 7dec5a84..00000000 --- a/packages/apps/rabbitmq/hack/update-versions.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -RABBITMQ_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -VALUES_FILE="${RABBITMQ_DIR}/values.yaml" -VERSIONS_FILE="${RABBITMQ_DIR}/files/versions.yaml" -GITHUB_API_URL="https://api.github.com/repos/rabbitmq/rabbitmq-server/releases" - -# Check if jq is installed -if ! command -v jq &> /dev/null; then - echo "Error: jq is not installed. Please install jq and try again." >&2 - exit 1 -fi - -# Fetch releases from GitHub API -echo "Fetching releases from GitHub API..." -RELEASES_JSON=$(curl -sSL "${GITHUB_API_URL}?per_page=100") - -if [ -z "$RELEASES_JSON" ]; then - echo "Error: Could not fetch releases from GitHub API" >&2 - exit 1 -fi - -# Extract stable release tags (format: v3.13.7, v4.0.3, etc.) -# Filter out pre-releases and draft releases -RELEASE_TAGS=$(echo "$RELEASES_JSON" | jq -r '.[] | select(.prerelease == false) | select(.draft == false) | .tag_name' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V) - -if [ -z "$RELEASE_TAGS" ]; then - echo "Error: Could not find any stable release tags" >&2 - exit 1 -fi - -echo "Found release tags: $(echo "$RELEASE_TAGS" | tr '\n' ' ')" - -# Supported major.minor versions (newest first) -# We support the last few minor releases of each active major -SUPPORTED_MAJORS=("4.2" "4.1" "4.0" "3.13") - -# Build versions map: major.minor -> latest patch version -declare -A VERSION_MAP -MAJOR_VERSIONS=() - -for major_minor in "${SUPPORTED_MAJORS[@]}"; do - # Find the latest patch version for this major.minor - MATCHING=$(echo "$RELEASE_TAGS" | grep -E "^v${major_minor//./\\.}\.[0-9]+$" | tail -n1) - - if [ -n "$MATCHING" ]; then - # Strip the 'v' prefix for the value (Docker tag format is e.g. 3.13.7) - TAG_VERSION="${MATCHING#v}" - VERSION_MAP["v${major_minor}"]="${TAG_VERSION}" - MAJOR_VERSIONS+=("v${major_minor}") - echo "Found version: v${major_minor} -> ${TAG_VERSION}" - else - echo "Warning: No stable releases found for ${major_minor}, skipping..." >&2 - fi -done - -if [ ${#MAJOR_VERSIONS[@]} -eq 0 ]; then - echo "Error: No matching versions found" >&2 - exit 1 -fi - -echo "Major versions to add: ${MAJOR_VERSIONS[*]}" - -# Create/update versions.yaml file -echo "Updating $VERSIONS_FILE..." -{ - for major_ver in "${MAJOR_VERSIONS[@]}"; do - echo "\"${major_ver}\": \"${VERSION_MAP[$major_ver]}\"" - done -} > "$VERSIONS_FILE" - -echo "Successfully updated $VERSIONS_FILE" - -# Update values.yaml - enum with major.minor versions only -TEMP_FILE=$(mktemp) -trap "rm -f $TEMP_FILE" EXIT - -# Build new version section -NEW_VERSION_SECTION="## @enum {string} Version" -for major_ver in "${MAJOR_VERSIONS[@]}"; do - NEW_VERSION_SECTION="${NEW_VERSION_SECTION} -## @value $major_ver" -done -NEW_VERSION_SECTION="${NEW_VERSION_SECTION} - -## @param {Version} version - RabbitMQ major.minor version to deploy -version: ${MAJOR_VERSIONS[0]}" - -# Check if version section already exists -if grep -q "^## @enum {string} Version" "$VALUES_FILE"; then - # Version section exists, update it using awk - echo "Updating existing version section in $VALUES_FILE..." - - awk -v new_section="$NEW_VERSION_SECTION" ' - /^## @enum {string} Version/ { - in_section = 1 - print new_section - next - } - in_section && /^version: / { - in_section = 0 - next - } - in_section { - next - } - { print } - ' "$VALUES_FILE" > "$TEMP_FILE.tmp" - mv "$TEMP_FILE.tmp" "$VALUES_FILE" -else - # Version section doesn't exist, insert it before Application-specific parameters section - echo "Inserting new version section in $VALUES_FILE..." - - awk -v new_section="$NEW_VERSION_SECTION" ' - /^## @section Application-specific parameters/ { - print new_section - print "" - } - { print } - ' "$VALUES_FILE" > "$TEMP_FILE.tmp" - mv "$TEMP_FILE.tmp" "$VALUES_FILE" -fi - -echo "Successfully updated $VALUES_FILE with major.minor versions: ${MAJOR_VERSIONS[*]}" diff --git a/packages/apps/rabbitmq/templates/_versions.tpl b/packages/apps/rabbitmq/templates/_versions.tpl deleted file mode 100644 index 76955b33..00000000 --- a/packages/apps/rabbitmq/templates/_versions.tpl +++ /dev/null @@ -1,8 +0,0 @@ -{{- define "rabbitmq.versionMap" }} -{{- $versionMap := .Files.Get "files/versions.yaml" | fromYaml }} -{{- if not (hasKey $versionMap .Values.version) }} - {{- printf `RabbitMQ version %s is not supported, allowed versions are %s` $.Values.version (keys $versionMap) | fail }} -{{- end }} -{{- index $versionMap .Values.version }} -{{- end }} - diff --git a/packages/apps/rabbitmq/templates/rabbitmq.yaml b/packages/apps/rabbitmq/templates/rabbitmq.yaml index bbf2efbe..b111285e 100644 --- a/packages/apps/rabbitmq/templates/rabbitmq.yaml +++ b/packages/apps/rabbitmq/templates/rabbitmq.yaml @@ -7,7 +7,6 @@ metadata: app.kubernetes.io/managed-by: {{ .Release.Service }} spec: replicas: {{ .Values.replicas }} - image: 'rabbitmq:{{ include "rabbitmq.versionMap" $ }}-management' {{- if .Values.external }} service: type: LoadBalancer diff --git a/packages/apps/rabbitmq/templates/workloadmonitor.yaml b/packages/apps/rabbitmq/templates/workloadmonitor.yaml index 66941153..0f7462c7 100644 --- a/packages/apps/rabbitmq/templates/workloadmonitor.yaml +++ b/packages/apps/rabbitmq/templates/workloadmonitor.yaml @@ -3,8 +3,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 diff --git a/packages/apps/rabbitmq/values.schema.json b/packages/apps/rabbitmq/values.schema.json index 43eaa206..04b8fa11 100644 --- a/packages/apps/rabbitmq/values.schema.json +++ b/packages/apps/rabbitmq/values.schema.json @@ -2,6 +2,11 @@ "title": "Chart Values", "type": "object", "properties": { + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, "replicas": { "description": "Number of RabbitMQ replicas.", "type": "integer", @@ -73,22 +78,6 @@ "type": "string", "default": "" }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, - "version": { - "description": "RabbitMQ major.minor version to deploy", - "type": "string", - "default": "v4.2", - "enum": [ - "v4.2", - "v4.1", - "v4.0", - "v3.13" - ] - }, "users": { "description": "Users configuration map.", "type": "object", @@ -137,4 +126,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/apps/rabbitmq/values.yaml b/packages/apps/rabbitmq/values.yaml index 08b6f5e6..65d5de44 100644 --- a/packages/apps/rabbitmq/values.yaml +++ b/packages/apps/rabbitmq/values.yaml @@ -34,15 +34,6 @@ storageClass: "" external: false ## -## @enum {string} Version -## @value v4.2 -## @value v4.1 -## @value v4.0 -## @value v3.13 - -## @param {Version} version - RabbitMQ major.minor version to deploy -version: v4.2 - ## @section Application-specific parameters ## diff --git a/packages/apps/redis/Makefile b/packages/apps/redis/Makefile index 939b75ee..aa9b0ccc 100644 --- a/packages/apps/redis/Makefile +++ b/packages/apps/redis/Makefile @@ -1,7 +1,7 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'redis' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/redis/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh update: diff --git a/packages/apps/redis/templates/redisfailover.yaml b/packages/apps/redis/templates/redisfailover.yaml index 160e030d..936217a3 100644 --- a/packages/apps/redis/templates/redisfailover.yaml +++ b/packages/apps/redis/templates/redisfailover.yaml @@ -75,8 +75,6 @@ kind: WorkloadMonitor metadata: name: {{ $.Release.Name }}-redis namespace: {{ $.Release.Namespace }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: minReplicas: 1 replicas: {{ .Values.replicas }} @@ -92,8 +90,6 @@ kind: WorkloadMonitor metadata: name: {{ $.Release.Name }}-sentinel namespace: {{ $.Release.Namespace }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: minReplicas: 2 replicas: 3 diff --git a/packages/apps/redis/values.schema.json b/packages/apps/redis/values.schema.json index a93d92ac..5c01cc31 100644 --- a/packages/apps/redis/values.schema.json +++ b/packages/apps/redis/values.schema.json @@ -2,6 +2,16 @@ "title": "Chart Values", "type": "object", "properties": { + "authEnabled": { + "description": "Enable password generation.", + "type": "boolean", + "default": true + }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, "replicas": { "description": "Number of Redis replicas.", "type": "integer", @@ -73,11 +83,6 @@ "type": "string", "default": "" }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, "version": { "description": "Redis major version to deploy", "type": "string", @@ -86,11 +91,6 @@ "v8", "v7" ] - }, - "authEnabled": { - "description": "Enable password generation.", - "type": "boolean", - "default": true } } -} +} \ No newline at end of file diff --git a/packages/apps/tcp-balancer/Makefile b/packages/apps/tcp-balancer/Makefile index e3bf78fe..d1cfda8e 100644 --- a/packages/apps/tcp-balancer/Makefile +++ b/packages/apps/tcp-balancer/Makefile @@ -1,5 +1,5 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'tcpbalancer' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/tcpbalancer/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh diff --git a/packages/apps/tcp-balancer/templates/workloadmonitor.yaml b/packages/apps/tcp-balancer/templates/workloadmonitor.yaml index 3478826b..41dce2ab 100644 --- a/packages/apps/tcp-balancer/templates/workloadmonitor.yaml +++ b/packages/apps/tcp-balancer/templates/workloadmonitor.yaml @@ -3,8 +3,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 diff --git a/packages/apps/tcp-balancer/values.schema.json b/packages/apps/tcp-balancer/values.schema.json index 20d04d80..ea30664a 100644 --- a/packages/apps/tcp-balancer/values.schema.json +++ b/packages/apps/tcp-balancer/values.schema.json @@ -2,58 +2,6 @@ "title": "Chart Values", "type": "object", "properties": { - "replicas": { - "description": "Number of HAProxy replicas.", - "type": "integer", - "default": 2 - }, - "resources": { - "description": "Explicit CPU and memory configuration for each TCP Balancer replica. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "nano", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, "external": { "description": "Enable external access from outside the cluster.", "type": "boolean", @@ -108,10 +56,57 @@ } } }, - "whitelistHTTP": { - "description": "Secure HTTP by whitelisting client networks (default: false).", - "type": "boolean", - "default": false + "replicas": { + "description": "Number of HAProxy replicas.", + "type": "integer", + "default": 2 + }, + "resources": { + "description": "Explicit CPU and memory configuration for each TCP Balancer replica. When omitted, the preset defined in `resourcesPreset` is applied.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory (RAM) available to each replica.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "resourcesPreset": { + "description": "Default sizing preset used when `resources` is omitted.", + "type": "string", + "default": "nano", + "enum": [ + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] }, "whitelist": { "description": "List of allowed client networks.", @@ -120,6 +115,11 @@ "items": { "type": "string" } + }, + "whitelistHTTP": { + "description": "Secure HTTP by whitelisting client networks (default: false).", + "type": "boolean", + "default": false } } -} +} \ No newline at end of file diff --git a/packages/apps/tenant/Makefile b/packages/apps/tenant/Makefile index 2f51d836..d1cfda8e 100644 --- a/packages/apps/tenant/Makefile +++ b/packages/apps/tenant/Makefile @@ -1,8 +1,5 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'tenant' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/tenant/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh - -test: - helm unittest . diff --git a/packages/apps/tenant/README.md b/packages/apps/tenant/README.md index 96cf5c6e..99a973c7 100644 --- a/packages/apps/tenant/README.md +++ b/packages/apps/tenant/README.md @@ -6,20 +6,15 @@ Tenants can be created recursively and are subject to the following rules: ### Tenant naming -Tenant names must be alphanumeric: - -- Lowercase letters (`a-z`) and digits (`0-9`) only -- Must start with a lowercase letter -- Dashes (`-`) are **not allowed**, unlike with other services -- Maximum length depends on the cluster configuration (Helm release prefix and root domain) - -This restriction exists to keep consistent naming in tenants, nested tenants, and services deployed in them. -A tenant cannot be named `foo-bar` because parsing internal resource names like `tenant-foo-bar` would be ambiguous. +Tenant names must be alphanumeric. +Using dashes (`-`) in tenant names is not allowed, unlike with other services. +This limitation exists to keep consistent naming in tenants, nested tenants, and services deployed in them. For example: - The root tenant is named `root`, but internally it's referenced as `tenant-root`. - A nested tenant could be named `foo`, which would result in `tenant-foo` in service names and URLs. +- However, a tenant can not be named `foo-bar`, because parsing names such as `tenant-foo-bar` would be ambiguous. ### Unique domains @@ -74,15 +69,14 @@ tenant-u1 ### Common parameters -| Name | Description | Type | Value | -| ----------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------- | ------- | -| `host` | The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host). | `string` | `""` | -| `etcd` | Deploy own Etcd cluster. | `bool` | `false` | -| `monitoring` | Deploy own Monitoring Stack. | `bool` | `false` | -| `ingress` | Deploy own Ingress Controller. | `bool` | `false` | -| `seaweedfs` | Deploy own SeaweedFS. | `bool` | `false` | -| `schedulingClass` | The name of a SchedulingClass CR to apply scheduling constraints for this tenant's workloads. | `string` | `""` | -| `resourceQuotas` | Define resource quotas for the tenant. | `map[string]quantity` | `{}` | +| Name | Description | Type | Value | +| ---------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------- | ------- | +| `host` | The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host). | `string` | `""` | +| `etcd` | Deploy own Etcd cluster. | `bool` | `false` | +| `monitoring` | Deploy own Monitoring Stack. | `bool` | `false` | +| `ingress` | Deploy own Ingress Controller. | `bool` | `false` | +| `seaweedfs` | Deploy own SeaweedFS. | `bool` | `false` | +| `resourceQuotas` | Define resource quotas for the tenant. | `map[string]quantity` | `{}` | ## Configuration diff --git a/packages/apps/tenant/templates/cilium-lb-pool.yaml b/packages/apps/tenant/templates/cilium-lb-pool.yaml deleted file mode 100644 index 63dbcaca..00000000 --- a/packages/apps/tenant/templates/cilium-lb-pool.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- $exposeMode := (index .Values._cluster "expose-mode") | default "externalIPs" }} -{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} -{{- $exposeIPs := (index .Values._cluster "expose-external-ips") | default "" | nospace }} -{{- $ipsList := list }} -{{- range splitList "," $exposeIPs }} - {{- $ip := . | trim }} - {{- if $ip }} - {{- $ipsList = append $ipsList $ip }} - {{- end }} -{{- end }} -{{- $isPublishingIngressLB := and - (eq $exposeMode "loadBalancer") - (eq $exposeIngress .Release.Namespace) - .Values.ingress }} -{{- if and $isPublishingIngressLB $ipsList }} -apiVersion: cilium.io/v2 -kind: CiliumLoadBalancerIPPool -metadata: - name: {{ trimPrefix "tenant-" .Release.Namespace }}-exposure -spec: - blocks: - {{- range $ipsList }} - - cidr: {{ . }}{{ if not (contains "/" .) }}/{{ if contains ":" . }}128{{ else }}32{{ end }}{{ end }} - {{- end }} - serviceSelector: - matchLabels: - "io.kubernetes.service.namespace": {{ .Release.Namespace | quote }} -{{- end }} diff --git a/packages/apps/tenant/templates/etcd.yaml b/packages/apps/tenant/templates/etcd.yaml index 9a122da2..97b39205 100644 --- a/packages/apps/tenant/templates/etcd.yaml +++ b/packages/apps/tenant/templates/etcd.yaml @@ -18,7 +18,7 @@ spec: name: cozystack-etcd-application-default-etcd namespace: cozy-system interval: 5m - timeout: 30m + timeout: 10m install: remediation: retries: -1 diff --git a/packages/apps/tenant/templates/namespace.yaml b/packages/apps/tenant/templates/namespace.yaml index dfb83730..5942cba3 100644 --- a/packages/apps/tenant/templates/namespace.yaml +++ b/packages/apps/tenant/templates/namespace.yaml @@ -38,12 +38,6 @@ {{- if .Values.seaweedfs }} {{- $seaweedfs = $tenantName }} {{- end }} - -{{/* SchedulingClass: inherited from parent, can be set if parent has none */}} -{{- $schedulingClass := $parentNamespace.schedulingClass | default "" }} -{{- if and (not $schedulingClass) .Values.schedulingClass }} -{{- $schedulingClass = .Values.schedulingClass }} -{{- end }} --- apiVersion: v1 kind: Namespace @@ -64,9 +58,6 @@ metadata: namespace.cozystack.io/monitoring: {{ $monitoring | quote }} namespace.cozystack.io/seaweedfs: {{ $seaweedfs | quote }} namespace.cozystack.io/host: {{ $computedHost | quote }} - {{- with $schedulingClass }} - scheduler.cozystack.io/scheduling-class: {{ . | quote }} - {{- end }} alpha.kubevirt.io/auto-memory-limits-ratio: "1.0" ownerReferences: - apiVersion: v1 @@ -95,7 +86,4 @@ stringData: monitoring: {{ $monitoring | quote }} seaweedfs: {{ $seaweedfs | quote }} host: {{ $computedHost | quote }} - {{- with $schedulingClass }} - schedulingClass: {{ . | quote }} - {{- end }} {{- end }} diff --git a/packages/apps/tenant/templates/networkpolicy.yaml b/packages/apps/tenant/templates/networkpolicy.yaml index 4bd3ba02..d9f87856 100644 --- a/packages/apps/tenant/templates/networkpolicy.yaml +++ b/packages/apps/tenant/templates/networkpolicy.yaml @@ -186,23 +186,6 @@ spec: --- apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy -metadata: - # Allow the tenant's ingress-nginx to reach both the linstor-gui - # gatekeeper pods (for /oauth2/* and app traffic) AND the transient - # ACME http-01 solver pods that cert-manager spins up in the same - # namespace during certificate issuance/renewal. Matching the whole - # namespace mirrors allow-to-dashboard / allow-to-keycloak. - name: allow-to-linstor-gui - namespace: {{ include "tenant.name" . }} -spec: - endpointSelector: {} - egress: - - toEndpoints: - - matchLabels: - "k8s:io.kubernetes.pod.namespace": cozy-linstor ---- -apiVersion: cilium.io/v2 -kind: CiliumNetworkPolicy metadata: name: allow-to-keycloak namespace: {{ include "tenant.name" . }} @@ -224,27 +207,6 @@ spec: - toEndpoints: - matchLabels: "k8s:io.kubernetes.pod.namespace": cozy-kubevirt-cdi -{{- if .Values.monitoring }} ---- -apiVersion: cilium.io/v2 -kind: CiliumClusterwideNetworkPolicy -metadata: - name: {{ include "tenant.name" . }}-egress-virt-handler -spec: - endpointSelector: - matchLabels: - "k8s:io.kubernetes.pod.namespace": "{{ include "tenant.name" . }}" - "k8s:app.kubernetes.io/name": "vmagent" - egress: - - toEndpoints: - - matchLabels: - "k8s:kubevirt.io": "virt-handler" - "k8s:io.kubernetes.pod.namespace": "cozy-kubevirt" - toPorts: - - ports: - - port: "8443" - protocol: TCP -{{- end }} --- apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy diff --git a/packages/apps/tenant/templates/tenant.yaml b/packages/apps/tenant/templates/tenant.yaml index 79eba4ca..6d325a07 100644 --- a/packages/apps/tenant/templates/tenant.yaml +++ b/packages/apps/tenant/templates/tenant.yaml @@ -5,10 +5,42 @@ metadata: name: {{ include "tenant.name" . }} namespace: {{ include "tenant.name" . }} --- +# == default role == +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "tenant.name" . }} + namespace: {{ include "tenant.name" . }} +rules: +- apiGroups: [""] + resources: ["pods", "services", "persistentvolumes", "endpoints", "events", "resourcequotas"] + verbs: ["get", "list", "watch"] +- apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["roles"] + verbs: ["get"] +- apiGroups: ["apps.cozystack.io"] + resources: ['*'] + verbs: ['*'] +- apiGroups: + - cozystack.io + resources: + - workloadmonitors + - workloads + verbs: ["get", "list", "watch"] +- apiGroups: + - core.cozystack.io + resources: + - tenantmodules + - tenantsecrets + verbs: ["get", "list", "watch"] +--- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: cozy:tenant + name: {{ include "tenant.name" . }} namespace: {{ include "tenant.name" . }} subjects: {{- if ne .Release.Namespace "tenant-root" }} @@ -30,67 +62,342 @@ subjects: name: {{ include "tenant.name" . }} namespace: {{ include "tenant.name" . }} roleRef: - kind: ClusterRole - name: cozy:tenant + kind: Role + name: {{ include "tenant.name" . }} apiGroup: rbac.authorization.k8s.io --- -# == view role binding == +# == view role == +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "tenant.name" . }}-view + namespace: {{ include "tenant.name" . }} +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + verbs: + - get + - apiGroups: + - apps.cozystack.io + resources: + - "*" + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - pods + - services + - persistentvolumes + - endpoints + - events + - resourcequotas + verbs: + - get + - list + - watch + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - cozystack.io + resources: + - workloadmonitors + - workloads + verbs: ["get", "list", "watch"] +--- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: cozy:tenant:view + name: {{ include "tenant.name" . }}-view namespace: {{ include "tenant.name" . }} subjects: {{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "view" (include "tenant.name" .)) | nindent 2 }} roleRef: - kind: ClusterRole - name: cozy:tenant:view + kind: Role + name: {{ include "tenant.name" . }}-view apiGroup: rbac.authorization.k8s.io + +--- +# == use role == +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "tenant.name" . }}-use + namespace: {{ include "tenant.name" . }} +rules: + - apiGroups: [rbac.authorization.k8s.io] + resources: + - roles + verbs: + - get + - apiGroups: ["apps.cozystack.io"] + resources: + - "*" + verbs: + - get + - list + - watch + - apiGroups: [""] + resources: + - pods + - services + - persistentvolumes + - endpoints + - events + - resourcequotas + verbs: + - get + - list + - watch + - apiGroups: ["networking.k8s.io"] + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: ["subresources.kubevirt.io"] + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + verbs: + - get + - list + - apiGroups: ["subresources.kubevirt.io"] + resources: + - virtualmachineinstances/portforward + verbs: + - get + - update + - apiGroups: + - cozystack.io + resources: + - workloadmonitors + - workloads + verbs: ["get", "list", "watch"] + - apiGroups: + - core.cozystack.io + resources: + - tenantmodules + - tenantsecrets + verbs: ["get", "list", "watch"] --- -# == use role binding == kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: cozy:tenant:use + name: {{ include "tenant.name" . }}-use namespace: {{ include "tenant.name" . }} subjects: {{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "use" (include "tenant.name" .)) | nindent 2 }} roleRef: - kind: ClusterRole - name: cozy:tenant:use + kind: Role + name: {{ include "tenant.name" . }}-use apiGroup: rbac.authorization.k8s.io --- -# == admin role binding == +# == admin role == +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "tenant.name" . }}-admin + namespace: {{ include "tenant.name" . }} +rules: + - apiGroups: [rbac.authorization.k8s.io] + resources: + - roles + verbs: + - get + - apiGroups: [""] + resources: + - pods + - services + - persistentvolumes + - endpoints + - events + - resourcequotas + verbs: + - get + - list + - watch + - delete + - apiGroups: ["kubevirt.io"] + resources: + - virtualmachines + verbs: + - get + - list + - apiGroups: ["subresources.kubevirt.io"] + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + verbs: + - get + - list + - apiGroups: ["subresources.kubevirt.io"] + resources: + - virtualmachineinstances/portforward + verbs: + - get + - update + - apiGroups: ["apps.cozystack.io"] + resources: + - buckets + - clickhouses + - ferretdb + - foos + - httpcaches + - kafkas + - kuberneteses + - mysqls + - natses + - postgreses + - rabbitmqs + - redises + - seaweedfses + - tcpbalancers + - virtualmachines + - vmdisks + - vminstances + - infos + - virtualprivateclouds + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - cozystack.io + resources: + - workloadmonitors + - workloads + verbs: ["get", "list", "watch"] + - apiGroups: + - core.cozystack.io + resources: + - tenantmodules + - tenantsecrets + verbs: ["get", "list", "watch"] +--- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: cozy:tenant:admin + name: {{ include "tenant.name" . }}-admin namespace: {{ include "tenant.name" . }} subjects: {{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "admin" (include "tenant.name" .)) | nindent 2 }} roleRef: - kind: ClusterRole - name: cozy:tenant:admin + kind: Role + name: {{ include "tenant.name" . }}-admin apiGroup: rbac.authorization.k8s.io --- -# == super admin role binding == +# == super admin role == +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "tenant.name" . }}-super-admin + namespace: {{ include "tenant.name" . }} +rules: + - apiGroups: [rbac.authorization.k8s.io] + resources: + - roles + verbs: + - get + - apiGroups: [""] + resources: + - pods + - services + - persistentvolumes + - endpoints + - events + - resourcequotas + verbs: + - get + - list + - watch + - delete + - apiGroups: ["kubevirt.io"] + resources: + - virtualmachines + verbs: + - '*' + - apiGroups: ["subresources.kubevirt.io"] + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + verbs: + - get + - list + - apiGroups: ["subresources.kubevirt.io"] + resources: + - virtualmachineinstances/portforward + verbs: + - get + - update + - apiGroups: ["apps.cozystack.io"] + resources: + - '*' + verbs: + - '*' + - apiGroups: + - cozystack.io + resources: + - workloadmonitors + - workloads + verbs: ["get", "list", "watch"] + - apiGroups: + - core.cozystack.io + resources: + - tenantmodules + - tenantsecrets + verbs: ["get", "list", "watch"] +--- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: cozy:tenant:super-admin + name: {{ include "tenant.name" . }}-super-admin namespace: {{ include "tenant.name" . }} subjects: {{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "super-admin" (include "tenant.name" .) ) | nindent 2 }} roleRef: - kind: ClusterRole - name: cozy:tenant:super-admin + kind: Role + name: {{ include "tenant.name" . }}-super-admin apiGroup: rbac.authorization.k8s.io --- -# == dashboard role binding == +# == dashboard role == +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "tenant.name" . }} + namespace: cozy-public +rules: +- apiGroups: ["source.toolkit.fluxcd.io"] + resources: ["helmrepositories"] + verbs: ["get", "list"] +- apiGroups: ["source.toolkit.fluxcd.io"] + resources: ["helmcharts"] + verbs: ["get", "list"] +--- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: cozy:{{ include "tenant.name" . }}:dashboard + name: {{ include "tenant.name" . }} namespace: cozy-public subjects: - kind: Group @@ -110,5 +417,5 @@ subjects: namespace: {{ include "tenant.name" . }} roleRef: kind: Role - name: cozy:tenant:dashboard + name: {{ include "tenant.name" . }} apiGroup: rbac.authorization.k8s.io diff --git a/packages/apps/tenant/tests/exposure_test.yaml b/packages/apps/tenant/tests/exposure_test.yaml deleted file mode 100644 index e86fab5b..00000000 --- a/packages/apps/tenant/tests/exposure_test.yaml +++ /dev/null @@ -1,141 +0,0 @@ -suite: tenant CiliumLoadBalancerIPPool rendering for publishing.exposure=loadBalancer -templates: - - templates/cilium-lb-pool.yaml - -release: - name: tenant-root - namespace: tenant-root - -tests: - - it: default exposure (externalIPs) renders no pool - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - asserts: - - hasDocuments: - count: 0 - - - it: loadBalancer mode in publishing tenant with ingress=true renders v2 pool with namespace-only selector - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 1 - - equal: - path: apiVersion - value: cilium.io/v2 - - equal: - path: kind - value: CiliumLoadBalancerIPPool - - equal: - path: metadata.name - value: root-exposure - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 192.0.2.11/32 - - equal: - path: spec.serviceSelector.matchLabels["io.kubernetes.service.namespace"] - value: tenant-root - - notExists: - path: spec.serviceSelector.matchLabels["app.kubernetes.io/name"] - - - it: loadBalancer mode with IPv6 emits /128 CIDR - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "2001:db8::1" - expose-mode: loadBalancer - asserts: - - equal: - path: spec.blocks - value: - - cidr: 2001:db8::1/128 - - - it: loadBalancer mode with mixed IPv4 and IPv6 emits correct CIDR per family - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,2001:db8::1" - expose-mode: loadBalancer - asserts: - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 2001:db8::1/128 - - - it: loadBalancer mode accepts pre-CIDR input without double-suffixing - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10/32,2001:db8::1/128" - expose-mode: loadBalancer - asserts: - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 2001:db8::1/128 - - - it: loadBalancer mode filters out empty entries from externalIPs (trailing, leading, repeated commas) - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,,192.0.2.11," - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 1 - - equal: - path: spec.blocks - value: - - cidr: 192.0.2.10/32 - - cidr: 192.0.2.11/32 - - - it: loadBalancer mode with ingress=false in publishing tenant renders no pool - set: - ingress: false - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 0 - - - it: loadBalancer mode in a non-publishing tenant renders no pool - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadBalancer - release: - name: tenant-u1 - namespace: tenant-u1 - asserts: - - hasDocuments: - count: 0 - - - it: loadBalancer mode in publishing tenant with empty externalIPs renders no pool - set: - ingress: true - _cluster: - expose-ingress: tenant-root - expose-external-ips: "" - expose-mode: loadBalancer - asserts: - - hasDocuments: - count: 0 diff --git a/packages/apps/tenant/values.schema.json b/packages/apps/tenant/values.schema.json index 28d9ac1e..2c3d5f89 100644 --- a/packages/apps/tenant/values.schema.json +++ b/packages/apps/tenant/values.schema.json @@ -2,13 +2,18 @@ "title": "Chart Values", "type": "object", "properties": { + "etcd": { + "description": "Deploy own Etcd cluster.", + "type": "boolean", + "default": false + }, "host": { "description": "The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host).", "type": "string", "default": "" }, - "etcd": { - "description": "Deploy own Etcd cluster.", + "ingress": { + "description": "Deploy own Ingress Controller.", "type": "boolean", "default": false }, @@ -17,21 +22,6 @@ "type": "boolean", "default": false }, - "ingress": { - "description": "Deploy own Ingress Controller.", - "type": "boolean", - "default": false - }, - "seaweedfs": { - "description": "Deploy own SeaweedFS.", - "type": "boolean", - "default": false - }, - "schedulingClass": { - "description": "The name of a SchedulingClass CR to apply scheduling constraints for this tenant's workloads.", - "type": "string", - "default": "" - }, "resourceQuotas": { "description": "Define resource quotas for the tenant.", "type": "object", @@ -48,6 +38,11 @@ ], "x-kubernetes-int-or-string": true } + }, + "seaweedfs": { + "description": "Deploy own SeaweedFS.", + "type": "boolean", + "default": false } } -} +} \ No newline at end of file diff --git a/packages/apps/tenant/values.yaml b/packages/apps/tenant/values.yaml index f9f8a999..58bb451f 100644 --- a/packages/apps/tenant/values.yaml +++ b/packages/apps/tenant/values.yaml @@ -17,8 +17,5 @@ ingress: false ## @param {bool} seaweedfs - Deploy own SeaweedFS. seaweedfs: false -## @param {string} [schedulingClass] - The name of a SchedulingClass CR to apply scheduling constraints for this tenant's workloads. -schedulingClass: "" - ## @param {map[string]quantity} resourceQuotas - Define resource quotas for the tenant. resourceQuotas: {} diff --git a/packages/system/monitoring/.helmignore b/packages/apps/virtual-machine/.helmignore similarity index 100% rename from packages/system/monitoring/.helmignore rename to packages/apps/virtual-machine/.helmignore diff --git a/packages/apps/harbor/Chart.yaml b/packages/apps/virtual-machine/Chart.yaml similarity index 55% rename from packages/apps/harbor/Chart.yaml rename to packages/apps/virtual-machine/Chart.yaml index 8b6f59da..7067744b 100644 --- a/packages/apps/harbor/Chart.yaml +++ b/packages/apps/virtual-machine/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 -name: harbor -description: Managed Harbor container registry -icon: /logos/harbor.svg +name: virtual-machine +description: Virtual Machine (simple) +icon: /logos/vm.svg type: application version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process -appVersion: "2.14.2" +appVersion: 0.14.0 diff --git a/packages/apps/virtual-machine/Makefile b/packages/apps/virtual-machine/Makefile new file mode 100644 index 00000000..7c482228 --- /dev/null +++ b/packages/apps/virtual-machine/Makefile @@ -0,0 +1,10 @@ +include ../../../hack/package.mk + +generate: + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md + yq -o json -i '.properties.gpus.items.type = "object" | .properties.gpus.default = []' values.schema.json + # INSTANCE_TYPES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/instancetypes.yaml | yq 'split(" ") | . + [""]' -o json) \ + # && yq -i -o json ".properties.instanceType.enum = $${INSTANCE_TYPES}" values.schema.json + PREFERENCES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/preferences.yaml | yq 'split(" ") | . + [""]' -o json) \ + && yq -i -o json ".properties.instanceProfile.enum = $${PREFERENCES}" values.schema.json + ../../../hack/update-crd.sh diff --git a/packages/apps/virtual-machine/README.md b/packages/apps/virtual-machine/README.md new file mode 100644 index 00000000..dc6633f2 --- /dev/null +++ b/packages/apps/virtual-machine/README.md @@ -0,0 +1,277 @@ +# Virtual Machine (simple) + +A Virtual Machine (VM) simulates computer hardware, enabling various operating systems and applications to run in an isolated environment. + +## Deployment Details + +The virtual machine is managed and hosted through KubeVirt, allowing you to harness the benefits of virtualization within your Kubernetes ecosystem. + +- Docs: [KubeVirt User Guide](https://kubevirt.io/user-guide/) +- GitHub: [KubeVirt Repository](https://github.com/kubevirt/kubevirt) + +## Accessing virtual machine + +You can access the virtual machine using the virtctl tool: +- [KubeVirt User Guide - Virtctl Client Tool](https://kubevirt.io/user-guide/user_workloads/virtctl_client_tool/) + +To access the serial console: + +``` +virtctl console +``` + +To access the VM using VNC: + +``` +virtctl vnc +``` + +To SSH into the VM: + +``` +virtctl ssh @ +``` + +## Parameters + +### Common parameters + +| Name | Description | Type | Value | +| ------------------------- | ------------------------------------------------------- | ---------- | ------------ | +| `external` | Enable external access from outside the cluster. | `bool` | `false` | +| `externalMethod` | Method to pass through traffic to the VM. | `string` | `PortList` | +| `externalPorts` | Ports to forward from outside the cluster. | `[]int` | `[22]` | +| `running` | Whether the virtual machine should be running. | `bool` | `true` | +| `instanceType` | Virtual Machine instance type. | `string` | `u1.medium` | +| `instanceProfile` | Virtual Machine preferences profile. | `string` | `ubuntu` | +| `systemDisk` | System disk configuration. | `object` | `{}` | +| `systemDisk.image` | The base image for the virtual machine. | `string` | `ubuntu` | +| `systemDisk.storage` | The size of the disk allocated for the virtual machine. | `string` | `5Gi` | +| `systemDisk.storageClass` | StorageClass used to store the data. | `string` | `replicated` | +| `subnets` | Additional subnets | `[]object` | `[]` | +| `subnets[i].name` | Subnet name | `string` | `""` | +| `gpus` | List of GPUs to attach. | `[]object` | `[]` | +| `gpus[i].name` | The name of the GPU resource to attach. | `string` | `""` | +| `resources` | Resource configuration for the virtual machine. | `object` | `{}` | +| `resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `resources.sockets` | Number of CPU sockets (vCPU topology). | `quantity` | `""` | +| `resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `sshKeys` | List of SSH public keys for authentication. | `[]string` | `[]` | +| `cloudInit` | Cloud-init user data. | `string` | `""` | +| `cloudInitSeed` | Seed string to generate SMBIOS UUID for the VM. | `string` | `""` | + + +## U Series + +The U Series is quite neutral and provides resources for +general purpose applications. + +*U* is the abbreviation for "Universal", hinting at the universal +attitude towards workloads. + +VMs of instance types will share physical CPU cores on a +time-slice basis with other VMs. + +### U Series Characteristics + +Specific characteristics of this series are: +- *Burstable CPU performance* - The workload has a baseline compute + performance but is permitted to burst beyond this baseline, if + excess compute resources are available. +- *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less + noise per node. + +## O Series + +The O Series is based on the U Series, with the only difference +being that memory is overcommitted. + +*O* is the abbreviation for "Overcommitted". + +### UO Series Characteristics + +Specific characteristics of this series are: +- *Burstable CPU performance* - The workload has a baseline compute + performance but is permitted to burst beyond this baseline, if + excess compute resources are available. +- *Overcommitted Memory* - Memory is over-committed in order to achieve + a higher workload density. +- *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4, for less + noise per node. + +## CX Series + +The CX Series provides exclusive compute resources for compute +intensive applications. + +*CX* is the abbreviation of "Compute Exclusive". + +The exclusive resources are given to the compute threads of the +VM. In order to ensure this, some additional cores (depending +on the number of disks and NICs) will be requested to offload +the IO threading from cores dedicated to the workload. +In addition, in this series, the NUMA topology of the used +cores is provided to the VM. + +### CX Series Characteristics + +Specific characteristics of this series are: +- *Hugepages* - Hugepages are used in order to improve memory + performance. +- *Dedicated CPU* - Physical cores are exclusively assigned to every + vCPU in order to provide fixed and high compute guarantees to the + workload. +- *Isolated emulator threads* - Hypervisor emulator threads are isolated + from the vCPUs in order to reduce emaulation related impact on the + workload. +- *vNUMA* - Physical NUMA topology is reflected in the guest in order to + optimize guest sided cache utilization. +- *vCPU-To-Memory Ratio (1:2)* - A vCPU-to-Memory ratio of 1:2. + +## M Series + +The M Series provides resources for memory intensive +applications. + +*M* is the abbreviation of "Memory". + +### M Series Characteristics + +Specific characteristics of this series are: +- *Hugepages* - Hugepages are used in order to improve memory + performance. +- *Burstable CPU performance* - The workload has a baseline compute + performance but is permitted to burst beyond this baseline, if + excess compute resources are available. +- *vCPU-To-Memory Ratio (1:8)* - A vCPU-to-Memory ratio of 1:8, for much + less noise per node. + +## RT Series + +The RT Series provides resources for realtime applications, like Oslat. + +*RT* is the abbreviation for "realtime". + +This series of instance types requires nodes capable of running +realtime applications. + +### RT Series Characteristics + +Specific characteristics of this series are: +- *Hugepages* - Hugepages are used in order to improve memory + performance. +- *Dedicated CPU* - Physical cores are exclusively assigned to every + vCPU in order to provide fixed and high compute guarantees to the + workload. +- *Isolated emulator threads* - Hypervisor emulator threads are isolated + from the vCPUs in order to reduce emaulation related impact on the + workload. +- *vCPU-To-Memory Ratio (1:4)* - A vCPU-to-Memory ratio of 1:4 starting from + the medium size. + +## Development + +To get started with customizing or creating your own instancetypes and preferences +see [DEVELOPMENT.md](./DEVELOPMENT.md). + +## Resources + +The following instancetype resources are provided by Cozystack: + +Name | vCPUs | Memory +-----|-------|------- +cx1.2xlarge | 8 | 16Gi +cx1.4xlarge | 16 | 32Gi +cx1.8xlarge | 32 | 64Gi +cx1.large | 2 | 4Gi +cx1.medium | 1 | 2Gi +cx1.xlarge | 4 | 8Gi +gn1.2xlarge | 8 | 32Gi +gn1.4xlarge | 16 | 64Gi +gn1.8xlarge | 32 | 128Gi +gn1.xlarge | 4 | 16Gi +m1.2xlarge | 8 | 64Gi +m1.4xlarge | 16 | 128Gi +m1.8xlarge | 32 | 256Gi +m1.large | 2 | 16Gi +m1.xlarge | 4 | 32Gi +n1.2xlarge | 16 | 32Gi +n1.4xlarge | 32 | 64Gi +n1.8xlarge | 64 | 128Gi +n1.large | 4 | 8Gi +n1.medium | 4 | 4Gi +n1.xlarge | 8 | 16Gi +o1.2xlarge | 8 | 32Gi +o1.4xlarge | 16 | 64Gi +o1.8xlarge | 32 | 128Gi +o1.large | 2 | 8Gi +o1.medium | 1 | 4Gi +o1.micro | 1 | 1Gi +o1.nano | 1 | 512Mi +o1.small | 1 | 2Gi +o1.xlarge | 4 | 16Gi +rt1.2xlarge | 8 | 32Gi +rt1.4xlarge | 16 | 64Gi +rt1.8xlarge | 32 | 128Gi +rt1.large | 2 | 8Gi +rt1.medium | 1 | 4Gi +rt1.micro | 1 | 1Gi +rt1.small | 1 | 2Gi +rt1.xlarge | 4 | 16Gi +u1.2xlarge | 8 | 32Gi +u1.2xmedium | 2 | 4Gi +u1.4xlarge | 16 | 64Gi +u1.8xlarge | 32 | 128Gi +u1.large | 2 | 8Gi +u1.medium | 1 | 4Gi +u1.micro | 1 | 1Gi +u1.nano | 1 | 512Mi +u1.small | 1 | 2Gi +u1.xlarge | 4 | 16Gi + +The following preference resources are provided by Cozystack: + +Name | Guest OS +-----|--------- +alpine | Alpine +centos.7 | CentOS 7 +centos.7.desktop | CentOS 7 +centos.stream10 | CentOS Stream 10 +centos.stream10.desktop | CentOS Stream 10 +centos.stream8 | CentOS Stream 8 +centos.stream8.desktop | CentOS Stream 8 +centos.stream8.dpdk | CentOS Stream 8 +centos.stream9 | CentOS Stream 9 +centos.stream9.desktop | CentOS Stream 9 +centos.stream9.dpdk | CentOS Stream 9 +cirros | Cirros +fedora | Fedora (amd64) +fedora.arm64 | Fedora (arm64) +opensuse.leap | OpenSUSE Leap +opensuse.tumbleweed | OpenSUSE Tumbleweed +rhel.10 | Red Hat Enterprise Linux 10 Beta (amd64) +rhel.10.arm64 | Red Hat Enterprise Linux 10 Beta (arm64) +rhel.7 | Red Hat Enterprise Linux 7 +rhel.7.desktop | Red Hat Enterprise Linux 7 +rhel.8 | Red Hat Enterprise Linux 8 +rhel.8.desktop | Red Hat Enterprise Linux 8 +rhel.8.dpdk | Red Hat Enterprise Linux 8 +rhel.9 | Red Hat Enterprise Linux 9 (amd64) +rhel.9.arm64 | Red Hat Enterprise Linux 9 (arm64) +rhel.9.desktop | Red Hat Enterprise Linux 9 Desktop (amd64) +rhel.9.dpdk | Red Hat Enterprise Linux 9 DPDK (amd64) +rhel.9.realtime | Red Hat Enterprise Linux 9 Realtime (amd64) +sles | SUSE Linux Enterprise Server +ubuntu | Ubuntu +windows.10 | Microsoft Windows 10 +windows.10.virtio | Microsoft Windows 10 (virtio) +windows.11 | Microsoft Windows 11 +windows.11.virtio | Microsoft Windows 11 (virtio) +windows.2k16 | Microsoft Windows Server 2016 +windows.2k16.virtio | Microsoft Windows Server 2016 (virtio) +windows.2k19 | Microsoft Windows Server 2019 +windows.2k19.virtio | Microsoft Windows Server 2019 (virtio) +windows.2k22 | Microsoft Windows Server 2022 +windows.2k22.virtio | Microsoft Windows Server 2022 (virtio) +windows.2k25 | Microsoft Windows Server 2025 +windows.2k25.virtio | Microsoft Windows Server 2025 (virtio) diff --git a/packages/apps/openbao/charts/cozy-lib b/packages/apps/virtual-machine/charts/cozy-lib similarity index 100% rename from packages/apps/openbao/charts/cozy-lib rename to packages/apps/virtual-machine/charts/cozy-lib diff --git a/packages/apps/virtual-machine/hack/update-instance-types.sh b/packages/apps/virtual-machine/hack/update-instance-types.sh new file mode 100755 index 00000000..1a248525 --- /dev/null +++ b/packages/apps/virtual-machine/hack/update-instance-types.sh @@ -0,0 +1 @@ +#!/bin/sh diff --git a/packages/apps/virtual-machine/logos/vm.svg b/packages/apps/virtual-machine/logos/vm.svg new file mode 100644 index 00000000..9c3e34d9 --- /dev/null +++ b/packages/apps/virtual-machine/logos/vm.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/apps/virtual-machine/templates/_helpers.tpl b/packages/apps/virtual-machine/templates/_helpers.tpl new file mode 100644 index 00000000..e65cad9d --- /dev/null +++ b/packages/apps/virtual-machine/templates/_helpers.tpl @@ -0,0 +1,103 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "virtual-machine.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 "virtual-machine.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 "virtual-machine.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "virtual-machine.labels" -}} +helm.sh/chart: {{ include "virtual-machine.chart" . }} +{{ include "virtual-machine.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "virtual-machine.selectorLabels" -}} +app.kubernetes.io/name: {{ include "virtual-machine.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Generate a stable UUID for cloud-init re-initialization upon upgrade. +*/}} +{{- define "virtual-machine.stableUuid" -}} +{{- $source := printf "%s-%s-%s" .Release.Namespace (include "virtual-machine.fullname" .) .Values.cloudInitSeed }} +{{- $hash := sha256sum $source }} +{{- $uuid := printf "%s-%s-4%s-9%s-%s" (substr 0 8 $hash) (substr 8 12 $hash) (substr 13 16 $hash) (substr 17 20 $hash) (substr 20 32 $hash) }} +{{- if eq .Values.cloudInitSeed "" }} + {{- /* Try to save previous uuid to not trigger full cloud-init again if user decided to remove the seed. */}} + {{- $vmResource := lookup "kubevirt.io/v1" "VirtualMachine" .Release.Namespace (include "virtual-machine.fullname" .) -}} + {{- if $vmResource }} + {{- $existingUuid := $vmResource | dig "spec" "template" "spec" "domain" "firmware" "uuid" "" }} + {{- if $existingUuid }} + {{- $uuid = $existingUuid }} + {{- end }} + {{- end }} +{{- end }} +{{- $uuid }} +{{- end }} + +{{/* +Node Affinity for Windows VMs +*/}} +{{- define "virtual-machine.nodeAffinity" -}} +{{- if .Values._cluster.scheduling -}} +{{- $dedicatedNodesForWindowsVMs := get .Values._cluster.scheduling "dedicatedNodesForWindowsVMs" -}} +{{- if eq $dedicatedNodesForWindowsVMs "true" -}} +{{- $isWindows := hasPrefix "windows" (toString .Values.instanceProfile) -}} +affinity: + nodeAffinity: + {{- if $isWindows }} + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: scheduling.cozystack.io/vm-windows + operator: In + values: + - "true" + {{- else }} + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + preference: + matchExpressions: + - key: scheduling.cozystack.io/vm-windows + operator: NotIn + values: + - "true" + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/packages/apps/opensearch/templates/dashboard-resourcemap.yaml b/packages/apps/virtual-machine/templates/dashboard-resourcemap.yaml similarity index 67% rename from packages/apps/opensearch/templates/dashboard-resourcemap.yaml rename to packages/apps/virtual-machine/templates/dashboard-resourcemap.yaml index 91dbf8cb..4beac5dc 100644 --- a/packages/apps/opensearch/templates/dashboard-resourcemap.yaml +++ b/packages/apps/virtual-machine/templates/dashboard-resourcemap.yaml @@ -8,19 +8,7 @@ rules: resources: - services resourceNames: - - {{ .Release.Name }} - - {{ .Release.Name }}-external - {{- if .Values.dashboards.enabled }} - - {{ .Release.Name }}-dashboards - - {{ .Release.Name }}-dashboards-external - {{- end }} - verbs: ["get", "list", "watch"] -- apiGroups: - - "" - resources: - - secrets - resourceNames: - - {{ .Release.Name }}-credentials + - {{ include "virtual-machine.fullname" . }} verbs: ["get", "list", "watch"] - apiGroups: - cozystack.io @@ -40,3 +28,16 @@ roleRef: kind: Role name: {{ .Release.Name }}-dashboard-resources apiGroup: rbac.authorization.k8s.io +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: {{ $.Release.Name }} +spec: + replicas: 1 + minReplicas: 1 + kind: virtual-machine + type: virtual-machine + selector: + app.kubernetes.io/instance: {{ .Release.Name }} + version: {{ $.Chart.Version }} diff --git a/packages/apps/virtual-machine/templates/secret-network-config.yaml b/packages/apps/virtual-machine/templates/secret-network-config.yaml new file mode 100644 index 00000000..9800ceac --- /dev/null +++ b/packages/apps/virtual-machine/templates/secret-network-config.yaml @@ -0,0 +1,40 @@ +# if subnets are specified and image is either ubunu or alpine +{{- if and .Values.subnets (or (eq .Values.systemDisk.image "ubuntu") (eq .Values.systemDisk.image "alpine")) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "virtual-machine.fullname" $ }}-network-config +stringData: + networkData: | + network: + version: 1 + config: + {{- if eq .Values.systemDisk.image "ubuntu" }} + # main iface + - type: physical + name: enp1s0 + subnets: + - type: dhcp + # additional ifaces attached to subnets + {{- range $i, $subnet := .Values.subnets }} + - type: physical + name: enp{{ add 2 $i }}s0 + subnets: + - type: dhcp + {{- end }} + {{- else if eq .Values.systemDisk.image "alpine" }} + #main iface + - type: physical + name: eth0 + subnets: + - type: dhcp + # additional ifaces attached to subnets + {{- range $i, $subnet := .Values.subnets }} + - type: physical + name: eth{{ add1 $i }} + subnets: + - type: dhcp + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/apps/virtual-machine/templates/secret.yaml b/packages/apps/virtual-machine/templates/secret.yaml new file mode 100644 index 00000000..73cd92bf --- /dev/null +++ b/packages/apps/virtual-machine/templates/secret.yaml @@ -0,0 +1,33 @@ +{{- if .Values.sshKeys }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "virtual-machine.fullname" $ }}-ssh-keys +stringData: + {{- range $k, $v := .Values.sshKeys }} + key{{ $k }}: {{ quote $v }} + {{- end }} +{{- end }} +{{- if or .Values.cloudInit .Values.sshKeys }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "virtual-machine.fullname" . }}-cloud-init +stringData: + userdata: | + {{- if .Values.cloudInit }} + {{- .Values.cloudInit | nindent 4 }} + {{- else if and (.Values.sshKeys) (not .Values.cloudInit) }} + {{- /* + We usually provide ssh keys in cloud-init metadata, because userdata it not typed and can be used for any purpose. + However, if user provides ssh keys but not cloud-init, we still need to provide a minimal cloud-init config to avoid errors. + */}} + #cloud-config + ssh_authorized_keys: + {{- range .Values.sshKeys }} + - {{ quote . }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packages/apps/virtual-machine/templates/service.yaml b/packages/apps/virtual-machine/templates/service.yaml new file mode 100644 index 00000000..b12f7612 --- /dev/null +++ b/packages/apps/virtual-machine/templates/service.yaml @@ -0,0 +1,38 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "virtual-machine.fullname" . }} + labels: + apps.cozystack.io/user-service: "true" + {{- include "virtual-machine.labels" . | nindent 4 }} +{{- if .Values.external }} + annotations: + networking.cozystack.io/wholeIP: "true" +{{- end }} +spec: + type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }} +{{- if .Values.external }} + externalTrafficPolicy: Local + {{- if ((include "cozy-lib.network.disableLoadBalancerNodePorts" $) | fromYaml) }} + allocateLoadBalancerNodePorts: false + {{- end }} +{{- else }} + clusterIP: None +{{- end }} + selector: + {{- include "virtual-machine.selectorLabels" . | nindent 4 }} + ports: +{{- if .Values.external }} + {{- if and (eq .Values.externalMethod "WholeIP") (not .Values.externalPorts) }} + - port: 65535 + {{- else }} + {{- range .Values.externalPorts }} + - name: port-{{ . }} + port: {{ . }} + targetPort: {{ . }} + {{- end }} + {{- end }} +{{- else }} + - port: 65535 +{{- end }} diff --git a/packages/apps/virtual-machine/templates/vm-update-hook.yaml b/packages/apps/virtual-machine/templates/vm-update-hook.yaml new file mode 100644 index 00000000..3c7d7d34 --- /dev/null +++ b/packages/apps/virtual-machine/templates/vm-update-hook.yaml @@ -0,0 +1,149 @@ +{{- $vmName := include "virtual-machine.fullname" . -}} +{{- $namespace := .Release.Namespace -}} + +{{- $existingVM := lookup "kubevirt.io/v1" "VirtualMachine" $namespace $vmName -}} +{{- $existingPVC := lookup "v1" "PersistentVolumeClaim" $namespace $vmName -}} +{{- $existingService := lookup "v1" "Service" $namespace $vmName -}} + +{{- $instanceType := .Values.instanceType | default "" -}} +{{- $instanceProfile := .Values.instanceProfile | default "" -}} +{{- $desiredStorage := .Values.systemDisk.storage | default "" -}} +{{- $desiredServiceType := ternary "LoadBalancer" "ClusterIP" .Values.external -}} + +{{- $needUpdateType := false -}} +{{- $needUpdateProfile := false -}} +{{- $needResizePVC := false -}} +{{- $needRecreateService := false -}} + +{{- if and $existingVM $instanceType -}} + {{- if not (eq $existingVM.spec.instancetype.name $instanceType) -}} + {{- $needUpdateType = true -}} + {{- end -}} +{{- end -}} + +{{- if and $existingVM $instanceProfile -}} + {{- if not (eq $existingVM.spec.preference.name $instanceProfile) -}} + {{- $needUpdateProfile = true -}} + {{- end -}} +{{- end -}} + +{{- if and $existingPVC $desiredStorage -}} + {{- $currentStorage := $existingPVC.spec.resources.requests.storage | toString -}} + {{- if not (eq $currentStorage $desiredStorage) -}} + {{- $oldSize := (include "cozy-lib.resources.toFloat" $currentStorage) | float64 -}} + {{- $newSize := (include "cozy-lib.resources.toFloat" $desiredStorage) | float64 -}} + {{- if gt $newSize $oldSize -}} + {{- $needResizePVC = true -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{- if $existingService -}} + {{- $currentServiceType := $existingService.spec.type -}} + {{- if ne $currentServiceType $desiredServiceType -}} + {{- $needRecreateService = true -}} + {{- end -}} +{{- end -}} + +{{- if or $needUpdateType $needUpdateProfile $needResizePVC $needRecreateService }} +apiVersion: batch/v1 +kind: Job +metadata: + name: "{{ $.Release.Name }}-update-hook" + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "0" + helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation +spec: + template: + metadata: + labels: + app: "{{ $.Release.Name }}-update-hook" + policy.cozystack.io/allow-to-apiserver: "true" + spec: + serviceAccountName: {{ $.Release.Name }}-update-hook + restartPolicy: Never + containers: + - name: update-resources + image: docker.io/alpine/k8s:1.33.4 + resources: + requests: + memory: "16Mi" + cpu: "10m" + limits: + memory: "128Mi" + cpu: "100m" + command: ["sh", "-exc"] + args: + - | + {{- if $needUpdateType }} + echo "Patching VirtualMachine for instancetype update..." + kubectl patch virtualmachines.kubevirt.io {{ $vmName }} -n {{ $namespace }} \ + --type merge \ + -p '{"spec":{"instancetype":{"name": "{{ $instanceType }}", "revisionName": null}}}' + {{- end }} + + {{- if $needUpdateProfile }} + echo "Patching VirtualMachine for preference update..." + kubectl patch virtualmachines.kubevirt.io {{ $vmName }} -n {{ $namespace }} \ + --type merge \ + -p '{"spec":{"preference":{"name": "{{ $instanceProfile }}", "revisionName": null}}}' + {{- end }} + + {{- if $needResizePVC }} + echo "Patching PVC for storage resize..." + kubectl patch pvc {{ $vmName }} -n {{ $namespace }} \ + --type merge \ + -p '{"spec":{"resources":{"requests":{"storage":"{{ $desiredStorage }}"}}}}' + {{- end }} + + {{- if $needRecreateService }} + echo "Removing Service..." + kubectl delete service --cascade=orphan -n {{ $namespace }} {{ $vmName }} + {{- end }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $.Release.Name }}-update-hook + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $.Release.Name }}-update-hook + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation +rules: + - apiGroups: ["kubevirt.io"] + resources: ["virtualmachines"] + verbs: ["patch", "get", "list", "watch"] + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["patch", "get", "list", "watch"] + - apiGroups: [""] + resources: ["services"] + resourceNames: ["{{ $vmName }}"] + verbs: ["delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $.Release.Name }}-update-hook + annotations: + helm.sh/hook: pre-install,pre-upgrade + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation +subjects: + - kind: ServiceAccount + name: {{ $.Release.Name }}-update-hook +roleRef: + kind: Role + name: {{ $.Release.Name }}-update-hook + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/packages/apps/virtual-machine/templates/vm.yaml b/packages/apps/virtual-machine/templates/vm.yaml new file mode 100644 index 00000000..efadf3af --- /dev/null +++ b/packages/apps/virtual-machine/templates/vm.yaml @@ -0,0 +1,155 @@ +{{- if and .Values.instanceType (not (lookup "instancetype.kubevirt.io/v1beta1" "VirtualMachineClusterInstancetype" "" .Values.instanceType)) }} +{{- fail (printf "Specified instancetype not exists in cluster: %s" .Values.instanceType) }} +{{- end }} +{{- if and .Values.instanceProfile (not (lookup "instancetype.kubevirt.io/v1beta1" "VirtualMachineClusterPreference" "" .Values.instanceProfile)) }} +{{- fail (printf "Specified profile not exists in cluster: %s" .Values.instanceProfile) }} +{{- end }} + +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + name: {{ include "virtual-machine.fullname" . }} + labels: + {{- include "virtual-machine.labels" . | nindent 4 }} +spec: + running: {{ .Values.running | default "true" }} + + {{- with .Values.instanceType }} + instancetype: + kind: VirtualMachineClusterInstancetype + name: {{ . }} + {{- end }} + {{- with .Values.instanceProfile }} + preference: + kind: VirtualMachineClusterPreference + name: {{ . }} + {{- end }} + + dataVolumeTemplates: + - metadata: + name: {{ include "virtual-machine.fullname" . }} + labels: + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + storage: + resources: + requests: + storage: {{ .Values.systemDisk.storage | quote }} + {{- with .Values.systemDisk.storageClass }} + storageClassName: {{ . }} + {{- end }} + source: + {{- $dv := lookup "cdi.kubevirt.io/v1beta1" "DataVolume" "cozy-public" (printf "vm-image-%s" .Values.systemDisk.image) }} + {{- if $dv }} + pvc: + name: vm-image-{{ .Values.systemDisk.image }} + namespace: cozy-public + {{- else }} + http: + {{- if eq .Values.systemDisk.image "cirros" }} + url: https://download.cirros-cloud.net/0.6.2/cirros-0.6.2-x86_64-disk.img + {{- else if eq .Values.systemDisk.image "ubuntu" }} + url: https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img + {{- else if eq .Values.systemDisk.image "fedora" }} + url: https://download.fedoraproject.org/pub/fedora/linux/releases/42/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-42-1.1.x86_64.qcow2 + {{- else if eq .Values.systemDisk.image "alpine" }} + url: https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/cloud/nocloud_alpine-3.20.8-x86_64-bios-cloudinit-r0.qcow2 + {{- else if eq .Values.systemDisk.image "talos" }} + url: https://github.com/siderolabs/talos/releases/download/v1.7.6/nocloud-amd64.raw.xz + {{- end }} + {{- end }} + + template: + metadata: + annotations: + kubevirt.io/allow-pod-bridge-network-live-migration: "true" + labels: + {{- include "virtual-machine.labels" . | nindent 8 }} + spec: + domain: + {{- if and .Values.resources .Values.resources.cpu .Values.resources.sockets }} + cpu: + cores: {{ .Values.resources.cpu }} + sockets: {{ .Values.resources.sockets }} + {{- end }} + {{- if and .Values.resources .Values.resources.memory }} + resources: + requests: + memory: {{ .Values.resources.memory | quote }} + {{- end }} + firmware: + uuid: {{ include "virtual-machine.stableUuid" . }} + devices: + {{- if .Values.gpus }} + gpus: + {{- range $i, $gpu := .Values.gpus }} + - name: gpu{{ add $i 1 }} + deviceName: {{ $gpu.name }} + {{- end }} + {{- end }} + + disks: + - disk: + bus: scsi + name: systemdisk + {{- if or .Values.cloudInit .Values.sshKeys (and .Values.subnets (or (eq .Values.systemDisk.image "ubuntu") (eq .Values.systemDisk.image "alpine"))) }} + - disk: + bus: virtio + name: cloudinitdisk + {{- end }} + + interfaces: + - name: default + bridge: {} + {{- if .Values.subnets }} + {{- range $i, $subnet := .Values.subnets }} + - name: {{ $subnet.name }} + bridge: {} + {{- end }} + {{- end }} + + machine: + type: "" + + {{- if .Values.sshKeys }} + accessCredentials: + - sshPublicKey: + source: + secret: + secretName: {{ include "virtual-machine.fullname" $ }}-ssh-keys + propagationMethod: + # keys will be injected into metadata part of cloud-init disk + noCloud: {} + {{- end }} + + terminationGracePeriodSeconds: 30 + + {{- include "virtual-machine.nodeAffinity" . | nindent 6 }} + + volumes: + - name: systemdisk + dataVolume: + name: {{ include "virtual-machine.fullname" . }} + {{- if or .Values.cloudInit .Values.sshKeys (and .Values.subnets (or (eq .Values.systemDisk.image "ubuntu") (eq .Values.systemDisk.image "alpine"))) }} + - name: cloudinitdisk + cloudInitNoCloud: + {{- if or .Values.cloudInit .Values.sshKeys }} + secretRef: + name: {{ include "virtual-machine.fullname" . }}-cloud-init + {{- end }} + {{- if and .Values.subnets (or (eq .Values.systemDisk.image "ubuntu") (eq .Values.systemDisk.image "alpine")) }} + networkDataSecretRef: + name: {{ include "virtual-machine.fullname" . }}-network-config + {{- end }} + {{- end }} + + networks: + - name: default + pod: {} + {{- if .Values.subnets }} + {{- range $i, $subnet := .Values.subnets }} + - name: {{ $subnet.name }} + multus: + networkName: {{ $.Release.Namespace }}/{{ $subnet.name }} + {{- end }} + {{- end }} diff --git a/packages/apps/virtual-machine/values.schema.json b/packages/apps/virtual-machine/values.schema.json new file mode 100644 index 00000000..e96d6449 --- /dev/null +++ b/packages/apps/virtual-machine/values.schema.json @@ -0,0 +1,218 @@ +{ + "title": "Chart Values", + "type": "object", + "properties": { + "cloudInit": { + "description": "Cloud-init user data.", + "type": "string", + "default": "" + }, + "cloudInitSeed": { + "description": "Seed string to generate SMBIOS UUID for the VM.", + "type": "string", + "default": "" + }, + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, + "externalMethod": { + "description": "Method to pass through traffic to the VM.", + "type": "string", + "default": "PortList", + "enum": [ + "PortList", + "WholeIP" + ] + }, + "externalPorts": { + "description": "Ports to forward from outside the cluster.", + "type": "array", + "default": [ + 22 + ], + "items": { + "type": "integer" + } + }, + "gpus": { + "description": "List of GPUs to attach.", + "type": "array", + "default": [], + "items": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "The name of the GPU resource to attach.", + "type": "string" + } + } + } + }, + "instanceProfile": { + "description": "Virtual Machine preferences profile.", + "type": "string", + "default": "ubuntu", + "enum": [ + "alpine", + "centos.7", + "centos.7.desktop", + "centos.stream10", + "centos.stream10.desktop", + "centos.stream8", + "centos.stream8.desktop", + "centos.stream8.dpdk", + "centos.stream9", + "centos.stream9.desktop", + "centos.stream9.dpdk", + "cirros", + "fedora", + "fedora.arm64", + "opensuse.leap", + "opensuse.tumbleweed", + "rhel.10", + "rhel.10.arm64", + "rhel.7", + "rhel.7.desktop", + "rhel.8", + "rhel.8.desktop", + "rhel.8.dpdk", + "rhel.9", + "rhel.9.arm64", + "rhel.9.desktop", + "rhel.9.dpdk", + "rhel.9.realtime", + "sles", + "ubuntu", + "windows.10", + "windows.10.virtio", + "windows.11", + "windows.11.virtio", + "windows.2k16", + "windows.2k16.virtio", + "windows.2k19", + "windows.2k19.virtio", + "windows.2k22", + "windows.2k22.virtio", + "windows.2k25", + "windows.2k25.virtio", + "" + ] + }, + "instanceType": { + "description": "Virtual Machine instance type.", + "type": "string", + "default": "u1.medium" + }, + "resources": { + "description": "Resource configuration for the virtual machine.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "Number of CPU cores allocated.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Amount of memory allocated.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "sockets": { + "description": "Number of CPU sockets (vCPU topology).", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "running": { + "description": "Whether the virtual machine should be running.", + "type": "boolean", + "default": true + }, + "sshKeys": { + "description": "List of SSH public keys for authentication.", + "type": "array", + "default": [], + "items": { + "type": "string" + } + }, + "subnets": { + "description": "Additional subnets", + "type": "array", + "default": [], + "items": { + "type": "object", + "properties": { + "name": { + "description": "Subnet name", + "type": "string" + } + } + } + }, + "systemDisk": { + "description": "System disk configuration.", + "type": "object", + "default": {}, + "required": [ + "image", + "storage" + ], + "properties": { + "image": { + "description": "The base image for the virtual machine.", + "type": "string", + "default": "ubuntu", + "enum": [ + "ubuntu", + "cirros", + "alpine", + "fedora", + "talos" + ] + }, + "storage": { + "description": "The size of the disk allocated for the virtual machine.", + "type": "string", + "default": "5Gi" + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "replicated" + } + } + } + } +} diff --git a/packages/apps/virtual-machine/values.yaml b/packages/apps/virtual-machine/values.yaml new file mode 100644 index 00000000..a4bfbb53 --- /dev/null +++ b/packages/apps/virtual-machine/values.yaml @@ -0,0 +1,98 @@ +## +## @section Common parameters +## + +## @enum {string} ExternalMethod - Method to pass through traffic to the VM. +## @value PortList - Forward selected ports only. +## @value WholeIP - Forward all traffic for the IP. + +## @enum {string} SystemImage - The base image for the virtual machine. +## @value ubuntu +## @value cirros +## @value alpine +## @value fedora +## @value talos + +## @typedef {struct} SystemDisk - System disk configuration. +## @field {SystemImage} image - The base image for the virtual machine. +## @field {string} storage - The size of the disk allocated for the virtual machine. +## @field {string} [storageClass] - StorageClass used to store the data. + +## @typedef {struct} Subnet - Additional subnets +## @field {string} [name] - Subnet name + +## @typedef {struct} GPU - GPU device configuration. +## @field {string} name - The name of the GPU resource to attach. + +## @typedef {struct} Resources - Resource configuration for the virtual machine. +## @field {quantity} [cpu] - Number of CPU cores allocated. +## @field {quantity} [sockets] - Number of CPU sockets (vCPU topology). +## @field {quantity} [memory] - Amount of memory allocated. + +## @param {bool} external - Enable external access from outside the cluster. +external: false + +## @param {ExternalMethod} externalMethod - Method to pass through traffic to the VM. +externalMethod: "PortList" + +## @param {[]int} externalPorts - Ports to forward from outside the cluster. +externalPorts: + - 22 + +## @param {bool} running - Whether the virtual machine should be running. +running: true + +## @param {string} instanceType - Virtual Machine instance type. +## @param {string} instanceProfile - Virtual Machine preferences profile. +instanceType: "u1.medium" +instanceProfile: ubuntu + +## @param {SystemDisk} systemDisk - System disk configuration. +systemDisk: + image: ubuntu + storage: 5Gi + storageClass: replicated + +## @param {[]Subnet} subnets - Additional subnets +subnets: [] +## Example: +## subnets: +## - name: subnet-84dbec17 +## - name: subnet-aa8896b5 +## - name: subnet-e9b97196 + +## @param {[]GPU} gpus - List of GPUs to attach. +gpus: [] +## Example: +## gpus: +## - name: nvidia.com/GA102GL_A10 + +## @param {Resources} [resources] - Resource configuration for the virtual machine. +resources: {} +## Example: +## resources: +## cpu: "4" +## sockets: "1" +## memory: "8Gi" + +## @param {[]string} sshKeys - List of SSH public keys for authentication. +sshKeys: [] +## Example: +## sshKeys: +## - ssh-rsa ... +## - ssh-ed25519 ... +## + +## @param {string} cloudInit - Cloud-init user data. +cloudInit: "" +## Example: +## cloudInit: | +## #cloud-config +## password: ubuntu +## chpasswd: { expire: False } +## + +## @param {string} cloudInitSeed - Seed string to generate SMBIOS UUID for the VM. +cloudInitSeed: "" +## Example: +## cloudInitSeed: "upd1" diff --git a/packages/apps/vm-disk/Makefile b/packages/apps/vm-disk/Makefile index 80b1075a..d1cfda8e 100644 --- a/packages/apps/vm-disk/Makefile +++ b/packages/apps/vm-disk/Makefile @@ -1,5 +1,5 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'vmdisk' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/vmdisk/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh diff --git a/packages/apps/vm-disk/README.md b/packages/apps/vm-disk/README.md index 3727d0f5..b8a4cdac 100644 --- a/packages/apps/vm-disk/README.md +++ b/packages/apps/vm-disk/README.md @@ -6,17 +6,15 @@ A Virtual Machine Disk ### Common parameters -| Name | Description | Type | Value | -| ------------------- | ------------------------------------------------------- | ---------- | ------------ | -| `source` | The source image location used to create a disk. | `object` | `{}` | -| `source.image` | Use image by name from default collection. | `*object` | `null` | -| `source.image.name` | Name of the image to use. | `string` | `""` | -| `source.upload` | Upload local image. | `*object` | `null` | -| `source.http` | Download image from an HTTP source. | `*object` | `null` | -| `source.http.url` | URL to download the image. | `string` | `""` | -| `source.disk` | Clone an existing vm-disk. | `*object` | `null` | -| `source.disk.name` | Name of the vm-disk to clone. | `string` | `""` | -| `optical` | Defines if disk should be considered optical. | `bool` | `false` | -| `storage` | The size of the disk allocated for the virtual machine. | `quantity` | `5Gi` | -| `storageClass` | StorageClass used to store the data. | `string` | `replicated` | +| Name | Description | Type | Value | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------- | ------------ | +| `source` | The source image location used to create a disk. | `object` | `{}` | +| `source.image` | Use image by name. | `*object` | `null` | +| `source.image.name` | Name of the image to use (uploaded as "golden image" or from the list: `ubuntu`, `fedora`, `cirros`, `alpine`, `talos`). | `string` | `""` | +| `source.upload` | Upload local image. | `*object` | `null` | +| `source.http` | Download image from an HTTP source. | `*object` | `null` | +| `source.http.url` | URL to download the image. | `string` | `""` | +| `optical` | Defines if disk should be considered optical. | `bool` | `false` | +| `storage` | The size of the disk allocated for the virtual machine. | `quantity` | `5Gi` | +| `storageClass` | StorageClass used to store the data. | `string` | `replicated` | diff --git a/packages/apps/vm-disk/templates/dv.yaml b/packages/apps/vm-disk/templates/dv.yaml index 521a82b8..3d68e639 100644 --- a/packages/apps/vm-disk/templates/dv.yaml +++ b/packages/apps/vm-disk/templates/dv.yaml @@ -21,18 +21,15 @@ spec: {{- end }} source: {{- if hasKey .Values.source "image" }} + {{- $dv := lookup "cdi.kubevirt.io/v1beta1" "DataVolume" "cozy-public" (printf "vm-image-%s" .Values.source.image.name) }} pvc: - name: vm-default-images-{{ required "A valid .Values.source.image.name entry required!" .Values.source.image.name }} + name: vm-image-{{ required "A valid .Values.source.image.name entry required!" .Values.source.image.name }} namespace: cozy-public {{- else if hasKey .Values.source "http" }} http: url: {{ required "A valid .Values.source.http.url entry required!" .Values.source.http.url }} {{- else if hasKey .Values.source "upload" }} upload: {} - {{- else if hasKey .Values.source "disk" }} - pvc: - name: vm-disk-{{ required "A valid .Values.source.disk.name entry required!" .Values.source.disk.name }} - namespace: {{ $.Release.Namespace }} {{- end }} {{- else }} source: diff --git a/packages/apps/vm-disk/values.schema.json b/packages/apps/vm-disk/values.schema.json index d61fc359..cd2215d8 100644 --- a/packages/apps/vm-disk/values.schema.json +++ b/packages/apps/vm-disk/values.schema.json @@ -2,24 +2,16 @@ "title": "Chart Values", "type": "object", "properties": { + "optical": { + "description": "Defines if disk should be considered optical.", + "type": "boolean", + "default": false + }, "source": { "description": "The source image location used to create a disk.", "type": "object", "default": {}, "properties": { - "disk": { - "description": "Clone an existing vm-disk.", - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "description": "Name of the vm-disk to clone.", - "type": "string" - } - } - }, "http": { "description": "Download image from an HTTP source.", "type": "object", @@ -34,29 +26,23 @@ } }, "image": { - "description": "Use image by name from default collection.", + "description": "Use image by name.", "type": "object", "required": [ "name" ], "properties": { "name": { - "description": "Name of the image to use.", + "description": "Name of the image to use (uploaded as \"golden image\" or from the list: `ubuntu`, `fedora`, `cirros`, `alpine`, `talos`).", "type": "string" } } }, "upload": { - "description": "Upload local image.", - "type": "object" + "description": "Upload local image." } } }, - "optical": { - "description": "Defines if disk should be considered optical.", - "type": "boolean", - "default": false - }, "storage": { "description": "The size of the disk allocated for the virtual machine.", "default": "5Gi", @@ -77,4 +63,4 @@ "default": "replicated" } } -} +} \ No newline at end of file diff --git a/packages/apps/vm-disk/values.yaml b/packages/apps/vm-disk/values.yaml index b9a20d68..33bd174f 100644 --- a/packages/apps/vm-disk/values.yaml +++ b/packages/apps/vm-disk/values.yaml @@ -3,21 +3,17 @@ ## ## @typedef {struct} SourceImage - Use image by name. -## @field {string} name - Name of the image to use. +## @field {string} name - Name of the image to use (uploaded as "golden image" or from the list: `ubuntu`, `fedora`, `cirros`, `alpine`, `talos`). ## @typedef {struct} SourceUpload - Upload local image. ## @typedef {struct} SourceHTTP - Download image from an HTTP source. ## @field {string} url - URL to download the image. -## @typedef {struct} SourceDisk - Clone an existing vm-disk. -## @field {string} name - Name of the vm-disk to clone. - ## @typedef {struct} Source - The source image location used to create a disk. -## @field {*SourceImage} [image] - Use image by name from default collection. +## @field {*SourceImage} [image] - Use image by name. ## @field {*SourceUpload} [upload] - Upload local image. ## @field {*SourceHTTP} [http] - Download image from an HTTP source. -## @field {*SourceDisk} [disk] - Clone an existing vm-disk. ## @param {Source} source - The source image location used to create a disk. source: {} diff --git a/packages/apps/vm-instance/Makefile b/packages/apps/vm-instance/Makefile index 92798e4f..3b6d471d 100644 --- a/packages/apps/vm-instance/Makefile +++ b/packages/apps/vm-instance/Makefile @@ -1,7 +1,7 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'vminstance' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/vminstance/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md #INSTANCE_TYPES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/instancetypes.yaml | yq 'split(" ") | . + [""]' -o json) \ # && yq -i -o json ".properties.instanceType.enum = $${INSTANCE_TYPES}" values.schema.json PREFERENCES=$$(yq e '.metadata.name' -o=json -r ../../system/kubevirt-instancetypes/templates/preferences.yaml | yq 'split(" ") | . + [""]' -o json) \ diff --git a/packages/apps/vm-instance/README.md b/packages/apps/vm-instance/README.md index 9d6a52b2..dc63508a 100644 --- a/packages/apps/vm-instance/README.md +++ b/packages/apps/vm-instance/README.md @@ -36,32 +36,28 @@ virtctl ssh @ ### Common parameters -| Name | Description | Type | Value | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ----------- | -| `external` | Enable external access from outside the cluster. | `bool` | `false` | -| `externalMethod` | Method to pass through traffic to the VM. | `string` | `PortList` | -| `externalPorts` | Ports to forward from outside the cluster. | `[]int` | `[22]` | -| `externalAllowICMP` | Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect. | `bool` | `true` | -| `runStrategy` | Requested running state of the VirtualMachineInstance | `string` | `Always` | -| `instanceType` | Virtual Machine instance type. | `string` | `u1.medium` | -| `instanceProfile` | Virtual Machine preferences profile. | `string` | `ubuntu` | -| `disks` | List of disks to attach. | `[]object` | `[]` | -| `disks[i].name` | Disk name. | `string` | `""` | -| `disks[i].bus` | Disk bus type (e.g. "sata"). | `string` | `""` | -| `networks` | Networks to attach the VM to. | `[]object` | `[]` | -| `networks[i].name` | Network attachment name. | `string` | `""` | -| `subnets` | Deprecated: use networks instead. | `[]object` | `[]` | -| `subnets[i].name` | Network attachment name. | `string` | `""` | -| `gpus` | List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | `[]object` | `[]` | -| `gpus[i].name` | The name of the GPU resource to attach. | `string` | `""` | -| `cpuModel` | Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map | `string` | `""` | -| `resources` | Resource configuration for the virtual machine. | `object` | `{}` | -| `resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `resources.sockets` | Number of CPU sockets (vCPU topology). | `quantity` | `""` | -| `sshKeys` | List of SSH public keys for authentication. | `[]string` | `[]` | -| `cloudInit` | Cloud-init user data. | `string` | `""` | -| `cloudInitSeed` | Seed string to generate SMBIOS UUID for the VM. | `string` | `""` | +| Name | Description | Type | Value | +| ------------------- | ------------------------------------------------------------------- | ---------- | ----------- | +| `external` | Enable external access from outside the cluster. | `bool` | `false` | +| `externalMethod` | Method to pass through traffic to the VM. | `string` | `PortList` | +| `externalPorts` | Ports to forward from outside the cluster. | `[]int` | `[22]` | +| `running` | Determines if the virtual machine should be running. | `bool` | `true` | +| `instanceType` | Virtual Machine instance type. | `string` | `u1.medium` | +| `instanceProfile` | Virtual Machine preferences profile. | `string` | `ubuntu` | +| `disks` | List of disks to attach. | `[]object` | `[]` | +| `disks[i].name` | Disk name. | `string` | `""` | +| `disks[i].bus` | Disk bus type (e.g. "sata"). | `string` | `""` | +| `subnets` | Additional subnets | `[]object` | `[]` | +| `subnets[i].name` | Subnet name | `string` | `""` | +| `gpus` | List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | `[]object` | `[]` | +| `gpus[i].name` | The name of the GPU resource to attach. | `string` | `""` | +| `resources` | Resource configuration for the virtual machine. | `object` | `{}` | +| `resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `resources.sockets` | Number of CPU sockets (vCPU topology). | `quantity` | `""` | +| `sshKeys` | List of SSH public keys for authentication. | `[]string` | `[]` | +| `cloudInit` | Cloud-init user data. | `string` | `""` | +| `cloudInitSeed` | Seed string to generate SMBIOS UUID for the VM. | `string` | `""` | ## U Series diff --git a/packages/apps/vm-instance/templates/_helpers.tpl b/packages/apps/vm-instance/templates/_helpers.tpl index ddea90fe..e65cad9d 100644 --- a/packages/apps/vm-instance/templates/_helpers.tpl +++ b/packages/apps/vm-instance/templates/_helpers.tpl @@ -70,29 +70,6 @@ Generate a stable UUID for cloud-init re-initialization upon upgrade. {{- $uuid }} {{- end }} -{{/* -Domain resources (cpu, memory) as a JSON object. -Used in vm.yaml for rendering and in the update hook for merge patches. -*/}} -{{- define "virtual-machine.domainResources" -}} -{{- $result := dict -}} -{{- if or .Values.cpuModel (and .Values.resources .Values.resources.cpu .Values.resources.sockets) -}} - {{- $cpu := dict -}} - {{- if and .Values.resources .Values.resources.cpu .Values.resources.sockets -}} - {{- $_ := set $cpu "cores" (.Values.resources.cpu | int64) -}} - {{- $_ := set $cpu "sockets" (.Values.resources.sockets | int64) -}} - {{- end -}} - {{- if .Values.cpuModel -}} - {{- $_ := set $cpu "model" .Values.cpuModel -}} - {{- end -}} - {{- $_ := set $result "cpu" $cpu -}} -{{- end -}} -{{- if and .Values.resources .Values.resources.memory -}} - {{- $_ := set $result "resources" (dict "requests" (dict "memory" .Values.resources.memory)) -}} -{{- end -}} -{{- $result | toJson -}} -{{- end -}} - {{/* Node Affinity for Windows VMs */}} diff --git a/packages/apps/vm-instance/templates/service.yaml b/packages/apps/vm-instance/templates/service.yaml index cfeffa81..b12f7612 100644 --- a/packages/apps/vm-instance/templates/service.yaml +++ b/packages/apps/vm-instance/templates/service.yaml @@ -7,12 +7,8 @@ metadata: apps.cozystack.io/user-service: "true" {{- include "virtual-machine.labels" . | nindent 4 }} {{- if .Values.external }} - service.kubernetes.io/service-proxy-name: "cozy-proxy" annotations: - networking.cozystack.io/wholeIP: {{ ternary "true" "false" (eq .Values.externalMethod "WholeIP") | quote }} - {{- if eq .Values.externalMethod "PortList" }} - networking.cozystack.io/allowICMP: {{ ternary "true" "false" (ne .Values.externalAllowICMP false) | quote }} - {{- end }} + networking.cozystack.io/wholeIP: "true" {{- end }} spec: type: {{ ternary "LoadBalancer" "ClusterIP" .Values.external }} diff --git a/packages/apps/vm-instance/templates/vm-update-hook.yaml b/packages/apps/vm-instance/templates/vm-update-hook.yaml index 995dafff..a12e8583 100644 --- a/packages/apps/vm-instance/templates/vm-update-hook.yaml +++ b/packages/apps/vm-instance/templates/vm-update-hook.yaml @@ -2,43 +2,26 @@ {{- $namespace := .Release.Namespace -}} {{- $existingVM := lookup "kubevirt.io/v1" "VirtualMachine" $namespace $vmName -}} -{{- $existingService := lookup "v1" "Service" $namespace $vmName -}} {{- $instanceType := .Values.instanceType | default "" -}} {{- $instanceProfile := .Values.instanceProfile | default "" -}} -{{- $desiredServiceType := ternary "LoadBalancer" "ClusterIP" .Values.external -}} {{- $needUpdateType := false -}} {{- $needUpdateProfile := false -}} -{{- $needRecreateService := false -}} -{{- $needRemoveInstanceType := false -}} -{{- $needRemoveCustomResources := false -}} -{{- $existingHasInstanceType := and $existingVM $existingVM.spec.instancetype -}} -{{- if and $existingHasInstanceType (not $instanceType) -}} - {{- $needRemoveInstanceType = true -}} -{{- else if and $existingHasInstanceType $instanceType -}} +{{- if and $existingVM $instanceType -}} {{- if not (eq $existingVM.spec.instancetype.name $instanceType) -}} {{- $needUpdateType = true -}} {{- end -}} -{{- else if and $existingVM (not $existingHasInstanceType) $instanceType -}} - {{- $needRemoveCustomResources = true -}} {{- end -}} -{{- if and $existingVM $existingVM.spec.preference $instanceProfile -}} +{{- if and $existingVM $instanceProfile -}} {{- if not (eq $existingVM.spec.preference.name $instanceProfile) -}} {{- $needUpdateProfile = true -}} {{- end -}} {{- end -}} -{{- if $existingService -}} - {{- $currentServiceType := $existingService.spec.type -}} - {{- if ne $currentServiceType $desiredServiceType -}} - {{- $needRecreateService = true -}} - {{- end -}} -{{- end -}} - -{{- if or $needUpdateType $needUpdateProfile $needRecreateService $needRemoveInstanceType $needRemoveCustomResources }} +{{- if or $needUpdateType $needUpdateProfile }} apiVersion: batch/v1 kind: Job metadata: @@ -75,32 +58,13 @@ spec: --type merge \ -p '{"spec":{"instancetype":{"name": "{{ $instanceType }}", "revisionName": null}}}' {{- end }} - + {{- if $needUpdateProfile }} echo "Patching VirtualMachine for preference update..." kubectl patch virtualmachines.kubevirt.io {{ $vmName }} -n {{ $namespace }} \ --type merge \ -p '{"spec":{"preference":{"name": "{{ $instanceProfile }}", "revisionName": null}}}' {{- end }} - - {{- if $needRemoveInstanceType }} - echo "Removing instancetype from VM (switching to custom resources)..." - kubectl patch virtualmachines.kubevirt.io {{ $vmName }} -n {{ $namespace }} \ - --type merge \ - -p '{"spec":{"instancetype":null{{- if not $instanceProfile }},"preference":null{{- end }},"template":{"spec":{"domain":{{ include "virtual-machine.domainResources" . }}}}}}' - {{- end }} - - {{- if $needRemoveCustomResources }} - echo "Removing custom CPU/memory from domain (switching to instancetype)..." - kubectl patch virtualmachines.kubevirt.io {{ $vmName }} -n {{ $namespace }} \ - --type merge \ - -p '{"spec":{"instancetype":{"name":"{{ $instanceType }}","revisionName":null},"template":{"spec":{"domain":{"cpu":null,"resources":null}}}}}' - {{- end }} - - {{- if $needRecreateService }} - echo "Removing Service..." - kubectl delete service --cascade=orphan -n {{ $namespace }} {{ $vmName }} - {{- end }} --- apiVersion: v1 kind: ServiceAccount @@ -123,10 +87,6 @@ rules: - apiGroups: ["kubevirt.io"] resources: ["virtualmachines"] verbs: ["patch", "get", "list", "watch"] - - apiGroups: [""] - resources: ["services"] - resourceNames: ["{{ $vmName }}"] - verbs: ["delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/packages/apps/vm-instance/templates/vm.yaml b/packages/apps/vm-instance/templates/vm.yaml index 55f278c1..acad3475 100644 --- a/packages/apps/vm-instance/templates/vm.yaml +++ b/packages/apps/vm-instance/templates/vm.yaml @@ -4,10 +4,6 @@ {{- if and .Values.instanceProfile (not (lookup "instancetype.kubevirt.io/v1beta1" "VirtualMachineClusterPreference" "" .Values.instanceProfile)) }} {{- fail (printf "Specified instanceProfile does not exist in the cluster: %s" .Values.instanceProfile) }} {{- end }} -{{- if and (not .Values.instanceType) (not (and .Values.resources .Values.resources.cpu .Values.resources.sockets .Values.resources.memory)) }} -{{- fail "Either instanceType or resources (cpu, sockets, memory) must be specified" }} -{{- end }} -{{- $networks := .Values.networks | default .Values.subnets }} apiVersion: kubevirt.io/v1 kind: VirtualMachine @@ -16,11 +12,7 @@ metadata: labels: {{- include "virtual-machine.labels" . | nindent 4 }} spec: - {{- if hasKey .Values "runStrategy" }} - runStrategy: {{ .Values.runStrategy }} - {{- else }} - runStrategy: {{ ternary "Always" "Halted" (.Values.running | default true) }} - {{- end }} + running: {{ .Values.running }} {{- with .Values.instanceType }} instancetype: kind: VirtualMachineClusterInstancetype @@ -35,22 +27,19 @@ spec: metadata: annotations: kubevirt.io/allow-pod-bridge-network-live-migration: "true" - {{- $ovnIPName := printf "%s.%s" (include "virtual-machine.fullname" .) .Release.Namespace }} - {{- $ovnIP := lookup "kubeovn.io/v1" "IP" "" $ovnIPName }} - {{- if $ovnIP }} - ovn.kubernetes.io/mac_address: {{ $ovnIP.spec.macAddress | quote }} - ovn.kubernetes.io/ip_address: {{ $ovnIP.spec.ipAddress | quote }} - {{- end }} labels: {{- include "virtual-machine.labels" . | nindent 8 }} spec: domain: - {{- $domainRes := include "virtual-machine.domainResources" . | fromJson -}} - {{- with $domainRes.cpu }} - cpu: {{- . | toYaml | nindent 10 }} + {{- if and .Values.resources .Values.resources.cpu .Values.resources.sockets }} + cpu: + cores: {{ .Values.resources.cpu }} + sockets: {{ .Values.resources.sockets }} {{- end }} - {{- with $domainRes.resources }} - resources: {{- . | toYaml | nindent 10 }} + {{- if and .Values.resources .Values.resources.memory }} + resources: + requests: + memory: {{ .Values.resources.memory | quote }} {{- end }} firmware: uuid: {{ include "virtual-machine.stableUuid" . }} @@ -87,10 +76,12 @@ spec: interfaces: - name: default bridge: {} - {{- range $i, $net := $networks }} - - name: {{ $net.name }} + {{- if .Values.subnets }} + {{- range $i, $subnet := .Values.subnets }} + - name: {{ $subnet.name }} bridge: {} {{- end }} + {{- end }} machine: type: "" {{- with .Values.sshKeys }} @@ -122,8 +113,10 @@ spec: networks: - name: default pod: {} - {{- range $i, $net := $networks }} - - name: {{ $net.name }} + {{- if .Values.subnets }} + {{- range $i, $subnet := .Values.subnets }} + - name: {{ $subnet.name }} multus: - networkName: {{ $.Release.Namespace }}/{{ $net.name }} + networkName: {{ $.Release.Namespace }}/{{ $subnet.name }} + {{- end }} {{- end }} diff --git a/packages/apps/vm-instance/values.schema.json b/packages/apps/vm-instance/values.schema.json index 01bd30a9..ca6b34e7 100644 --- a/packages/apps/vm-instance/values.schema.json +++ b/packages/apps/vm-instance/values.schema.json @@ -2,6 +2,37 @@ "title": "Chart Values", "type": "object", "properties": { + "cloudInit": { + "description": "Cloud-init user data.", + "type": "string", + "default": "" + }, + "cloudInitSeed": { + "description": "Seed string to generate SMBIOS UUID for the VM.", + "type": "string", + "default": "" + }, + "disks": { + "description": "List of disks to attach.", + "type": "array", + "default": [], + "items": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "bus": { + "description": "Disk bus type (e.g. \"sata\").", + "type": "string" + }, + "name": { + "description": "Disk name.", + "type": "string" + } + } + } + }, "external": { "description": "Enable external access from outside the cluster.", "type": "boolean", @@ -26,27 +57,22 @@ "type": "integer" } }, - "externalAllowICMP": { - "description": "Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect.", - "type": "boolean", - "default": true - }, - "runStrategy": { - "description": "Requested running state of the VirtualMachineInstance", - "type": "string", - "default": "Always", - "enum": [ - "Always", - "Halted", - "Manual", - "RerunOnFailure", - "Once" - ] - }, - "instanceType": { - "description": "Virtual Machine instance type.", - "type": "string", - "default": "u1.medium" + "gpus": { + "description": "List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).", + "type": "array", + "default": [], + "items": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "description": "The name of the GPU resource to attach.", + "type": "string" + } + } + } }, "instanceProfile": { "description": "Virtual Machine preferences profile.", @@ -98,76 +124,10 @@ "" ] }, - "disks": { - "description": "List of disks to attach.", - "type": "array", - "default": [], - "items": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "bus": { - "description": "Disk bus type (e.g. \"sata\").", - "type": "string" - }, - "name": { - "description": "Disk name.", - "type": "string" - } - } - } - }, - "networks": { - "description": "Networks to attach the VM to.", - "type": "array", - "default": [], - "items": { - "type": "object", - "properties": { - "name": { - "description": "Network attachment name.", - "type": "string" - } - } - } - }, - "subnets": { - "description": "Deprecated: use networks instead.", - "type": "array", - "default": [], - "items": { - "type": "object", - "properties": { - "name": { - "description": "Network attachment name.", - "type": "string" - } - } - } - }, - "gpus": { - "description": "List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).", - "type": "array", - "default": [], - "items": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "description": "The name of the GPU resource to attach.", - "type": "string" - } - } - } - }, - "cpuModel": { - "description": "Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map", + "instanceType": { + "description": "Virtual Machine instance type.", "type": "string", - "default": "" + "default": "u1.medium" }, "resources": { "description": "Resource configuration for the virtual machine.", @@ -215,6 +175,11 @@ } } }, + "running": { + "description": "Determines if the virtual machine should be running.", + "type": "boolean", + "default": true + }, "sshKeys": { "description": "List of SSH public keys for authentication.", "type": "array", @@ -223,15 +188,19 @@ "type": "string" } }, - "cloudInit": { - "description": "Cloud-init user data.", - "type": "string", - "default": "" - }, - "cloudInitSeed": { - "description": "Seed string to generate SMBIOS UUID for the VM.", - "type": "string", - "default": "" + "subnets": { + "description": "Additional subnets", + "type": "array", + "default": [], + "items": { + "type": "object", + "properties": { + "name": { + "description": "Subnet name", + "type": "string" + } + } + } } } } diff --git a/packages/apps/vm-instance/values.yaml b/packages/apps/vm-instance/values.yaml index 92e399c2..9d0a1522 100644 --- a/packages/apps/vm-instance/values.yaml +++ b/packages/apps/vm-instance/values.yaml @@ -10,8 +10,8 @@ ## @field {string} name - Disk name. ## @field {string} [bus] - Disk bus type (e.g. "sata"). -## @typedef {struct} Network - Network to attach the VM to. -## @field {string} [name] - Network attachment name. +## @typedef {struct} Subnet - Additional subnets +## @field {string} [name] - Subnet name ## @typedef {struct} GPU - GPU device configuration. ## @field {string} name - The name of the GPU resource to attach. @@ -31,18 +31,8 @@ externalMethod: PortList externalPorts: - 22 -## @param {bool} externalAllowICMP - Whether to accept ICMP traffic to the VM in PortList mode (preserves ping and PMTU discovery). No effect in WholeIP mode. Default true so ping behaves as users expect even when port filtering is in effect. -externalAllowICMP: true - -## @enum {string} RunStrategy - Requested running state of the VirtualMachineInstance -## @value Always - VMI should always be running -## @value Halted - VMI should never be running -## @value Manual - VMI can be started/stopped using API endpoints -## @value RerunOnFailure - VMI will initially be running and restarted if a failure occurs, but will not be restarted upon successful completion -## @value Once - VMI will run once and not be restarted upon completion regardless if the completion is of phase Failure or Success - -## @param {RunStrategy} runStrategy - Requested running state of the VirtualMachineInstance -runStrategy: Always +## @param {bool} running - Determines if the virtual machine should be running. +running: true ## @param {string} instanceType - Virtual Machine instance type. instanceType: "u1.medium" @@ -58,15 +48,13 @@ disks: [] ## - name: example-data ## bus: sata -## @param {[]Network} networks - Networks to attach the VM to. -networks: [] +## @param {[]Subnet} subnets - Additional subnets +subnets: [] ## Example: -## networks: +## subnets: ## - name: subnet-84dbec17 ## - name: subnet-aa8896b5 - -## @param {[]Network} subnets - Deprecated: use networks instead. -subnets: [] +## - name: subnet-e9b97196 ## @param {[]GPU} gpus - List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). gpus: [] @@ -74,9 +62,6 @@ gpus: [] ## gpus: ## - name: nvidia.com/GA102GL_A10 -## @param {string} cpuModel - Model specifies the CPU model inside the VMI. List of available models https://github.com/libvirt/libvirt/tree/master/src/cpu_map -cpuModel: "" - ## @param {Resources} [resources] - Resource configuration for the virtual machine. resources: {} diff --git a/packages/apps/vpc/Makefile b/packages/apps/vpc/Makefile index 2f0c193f..ea4f5d1b 100644 --- a/packages/apps/vpc/Makefile +++ b/packages/apps/vpc/Makefile @@ -1,7 +1,7 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'vpc' -v values.yaml -s values.schema.json -g ../../../api/apps/v1alpha1/vpc/types.go + cozyvalues-gen -v values.yaml -s values.schema.json ../../../hack/update-crd.sh update: diff --git a/packages/apps/vpc/templates/vpc.yaml b/packages/apps/vpc/templates/vpc.yaml index 784c181b..eb113b4f 100644 --- a/packages/apps/vpc/templates/vpc.yaml +++ b/packages/apps/vpc/templates/vpc.yaml @@ -15,37 +15,9 @@ spec: enableExternal: false namespaces: - {{ .Release.Namespace }} -{{- if .Values.peers }} - vpcPeerings: -{{- range .Values.peers }} -{{- $remoteRelease := printf "virtualprivatecloud-%s" .vpcName }} -{{- $remoteVpcId := printf "vpc-%s" (printf "%s/%s" .tenantNamespace $remoteRelease | sha256sum | trunc 6) }} -{{- $sorted := list $vpcId $remoteVpcId | sortAlpha }} -{{- $pairKey := join "/" $sorted }} -{{- $pairHash := sha256sum $pairKey }} -{{- $byte0 := int (include "cozy-lib.strings.hexToInt" (substr 0 2 $pairHash)) }} -{{- $byte1 := int (include "cozy-lib.strings.hexToInt" (substr 2 4 $pairHash)) }} -{{- $oct3 := int (add (mod $byte0 254) 1) }} -{{- $base4 := int (mul (mod $byte1 64) 4) }} -{{- if eq $vpcId (index $sorted 0) }} - - remoteVpc: {{ $remoteVpcId }} - localConnectIP: {{ printf "169.254.%d.%d" $oct3 (int (add $base4 1)) }} -{{- else }} - - remoteVpc: {{ $remoteVpcId }} - localConnectIP: {{ printf "169.254.%d.%d" $oct3 (int (add $base4 2)) }} -{{- end }} -{{- end }} -{{- end }} -{{- if .Values.routes }} - staticRoutes: -{{- range .Values.routes }} - - cidr: {{ .cidr | quote }} - nextHopIP: {{ .nextHopIP | quote }} -{{- end }} -{{- end }} -{{- range .Values.subnets }} -{{- $subnetId := print "subnet-" (print $.Release.Namespace "/" $vpcId "/" .name | sha256sum | trunc 8) }} +{{- range $subnetName, $subnetConfig := .Values.subnets }} +{{- $subnetId := print "subnet-" (print $.Release.Namespace "/" $vpcId "/" $subnetName | sha256sum | trunc 8) }} --- apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition @@ -53,7 +25,7 @@ metadata: name: {{ $subnetId }} namespace: {{ $.Release.Namespace }} labels: - cozystack.io/subnetName: {{ .name }} + cozystack.io/subnetName: {{ $subnetName }} cozystack.io/vpcId: {{ $vpcId }} cozystack.io/vpcName: {{ $.Release.Name }} cozystack.io/tenantName: {{ $.Release.Namespace }} @@ -70,13 +42,13 @@ kind: Subnet metadata: name: {{ $subnetId }} labels: - cozystack.io/subnetName: {{ .name }} + cozystack.io/subnetName: {{ $subnetName }} cozystack.io/vpcId: {{ $vpcId }} cozystack.io/vpcName: {{ $.Release.Name }} cozystack.io/tenantName: {{ $.Release.Namespace }} spec: vpc: {{ $vpcId }} - cidrBlock: {{ .cidr }} + cidrBlock: {{ $subnetConfig.cidr }} provider: "{{ $subnetId }}.{{ $.Release.Namespace }}.ovn" protocol: IPv4 enableLb: false @@ -94,15 +66,9 @@ metadata: cozystack.io/vpcId: {{ $vpcId }} cozystack.io/tenantName: {{ $.Release.Namespace }} data: - {{- range .Values.subnets }} - {{ .name }}.ID: {{ print "subnet-" (print $.Release.Namespace "/" $vpcId "/" .name | sha256sum | trunc 8) }} - {{ .name }}.CIDR: {{ .cidr }} - {{- end }} - {{- range .Values.peers }} - {{- $remoteRelease := printf "virtualprivatecloud-%s" .vpcName }} - {{- $remoteVpcId := printf "vpc-%s" (printf "%s/%s" .tenantNamespace $remoteRelease | sha256sum | trunc 6) }} - peer.{{ .tenantNamespace }}.{{ .vpcName }}.vpcId: {{ $remoteVpcId | quote }} - peer.{{ .tenantNamespace }}.{{ .vpcName }}.tenantNamespace: {{ .tenantNamespace | quote }} + {{- range $subnetName, $subnetConfig := .Values.subnets }} + {{ $subnetName }}.ID: {{ print "subnet-" (print $.Release.Namespace "/" $vpcId "/" $subnetName | sha256sum | trunc 8) }} + {{ $subnetName }}.CIDR: {{ $subnetConfig.cidr }} {{- end }} --- apiVersion: rbac.authorization.k8s.io/v1 diff --git a/packages/apps/vpc/values.schema.json b/packages/apps/vpc/values.schema.json index b25b46ed..3e888de4 100644 --- a/packages/apps/vpc/values.schema.json +++ b/packages/apps/vpc/values.schema.json @@ -4,68 +4,17 @@ "properties": { "subnets": { "description": "Subnets of a VPC", - "type": "array", - "default": [], - "items": { + "type": "object", + "default": {}, + "additionalProperties": { "type": "object", - "required": [ - "name" - ], "properties": { "cidr": { "description": "IP address range", "type": "string" - }, - "name": { - "description": "Subnet name", - "type": "string" - } - } - } - }, - "peers": { - "description": "VPC peering connections (bidirectional declaration required)", - "type": "array", - "default": [], - "items": { - "type": "object", - "required": [ - "tenantNamespace", - "vpcName" - ], - "properties": { - "tenantNamespace": { - "description": "Namespace of the remote tenant", - "type": "string" - }, - "vpcName": { - "description": "Logical name of the remote VPC (without \"virtualprivatecloud-\" prefix)", - "type": "string" - } - } - } - }, - "routes": { - "description": "Static routes for the VPC", - "type": "array", - "default": [], - "items": { - "type": "object", - "required": [ - "cidr", - "nextHopIP" - ], - "properties": { - "cidr": { - "description": "Destination CIDR", - "type": "string" - }, - "nextHopIP": { - "description": "Next hop IP address", - "type": "string" } } } } } -} +} \ No newline at end of file diff --git a/packages/apps/vpc/values.yaml b/packages/apps/vpc/values.yaml index 8bd27589..e2bd5faa 100644 --- a/packages/apps/vpc/values.yaml +++ b/packages/apps/vpc/values.yaml @@ -3,36 +3,13 @@ ## ## @typedef {struct} Subnet - Subnet of a VPC -## @field {string} name - Subnet name ## @field {string} [cidr] - IP address range -## @param {[]Subnet} subnets - Subnets of a VPC -subnets: [] +## @param {map[string]Subnet} subnets - Subnets of a VPC +subnets: {} ## Example: ## subnets: -## - name: mysubnet0 +## mysubnet0: ## cidr: "172.16.0.0/24" -## - name: mysubnet1 +## mysubnet1: ## cidr: "172.16.1.0/24" - -## @typedef {struct} Peer - VPC peering target -## @field {string} vpcName - Logical name of the remote VPC (without "virtualprivatecloud-" prefix) -## @field {string} tenantNamespace - Namespace of the remote tenant - -## @param {[]Peer} peers - VPC peering connections (bidirectional declaration required) -peers: [] -## Example: -## peers: -## - vpcName: "other-vpc" -## tenantNamespace: "tenant-other" - -## @typedef {struct} Route - Static route entry -## @field {string} cidr - Destination CIDR -## @field {string} nextHopIP - Next hop IP address - -## @param {[]Route} routes - Static routes for the VPC -routes: [] -## Example: -## routes: -## - cidr: "172.16.1.0/24" -## nextHopIP: "10.0.0.1" diff --git a/packages/apps/vpn/Makefile b/packages/apps/vpn/Makefile index d0b8412f..d1cfda8e 100644 --- a/packages/apps/vpn/Makefile +++ b/packages/apps/vpn/Makefile @@ -1,5 +1,5 @@ include ../../../hack/package.mk generate: - cozyvalues-gen -m 'vpn' -v values.yaml -s values.schema.json -r README.md -g ../../../api/apps/v1alpha1/vpn/types.go + cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh diff --git a/packages/apps/vpn/templates/workloadmonitor.yaml b/packages/apps/vpn/templates/workloadmonitor.yaml index 7fc1ec7a..a75f7940 100644 --- a/packages/apps/vpn/templates/workloadmonitor.yaml +++ b/packages/apps/vpn/templates/workloadmonitor.yaml @@ -2,8 +2,6 @@ apiVersion: cozystack.io/v1alpha1 kind: WorkloadMonitor metadata: name: {{ $.Release.Name }} - labels: - workloads.cozystack.io/resource-preset: {{ .Values.resourcesPreset | quote }} spec: replicas: {{ .Values.replicas }} minReplicas: 1 diff --git a/packages/apps/vpn/values.schema.json b/packages/apps/vpn/values.schema.json index abfd7b52..14e85262 100644 --- a/packages/apps/vpn/values.schema.json +++ b/packages/apps/vpn/values.schema.json @@ -2,6 +2,24 @@ "title": "Chart Values", "type": "object", "properties": { + "external": { + "description": "Enable external access from outside the cluster.", + "type": "boolean", + "default": false + }, + "externalIPs": { + "description": "List of externalIPs for service. Optional. If not specified, will use LoadBalancer service by default.", + "type": "array", + "default": [], + "items": { + "type": "string" + } + }, + "host": { + "description": "Host used to substitute into generated URLs.", + "type": "string", + "default": "" + }, "replicas": { "description": "Number of VPN server replicas.", "type": "integer", @@ -54,16 +72,6 @@ "2xlarge" ] }, - "external": { - "description": "Enable external access from outside the cluster.", - "type": "boolean", - "default": false - }, - "host": { - "description": "Host used to substitute into generated URLs.", - "type": "string", - "default": "" - }, "users": { "description": "Users configuration map.", "type": "object", @@ -77,14 +85,6 @@ } } } - }, - "externalIPs": { - "description": "List of externalIPs for service. Optional. If not specified, will use LoadBalancer service by default.", - "type": "array", - "default": [], - "items": { - "type": "string" - } } } -} +} \ No newline at end of file diff --git a/packages/core/installer/.helmignore b/packages/core/installer/.helmignore deleted file mode 100644 index 6901ff3d..00000000 --- a/packages/core/installer/.helmignore +++ /dev/null @@ -1,9 +0,0 @@ -# VCS and IDE -.git -.gitignore - -# Build artifacts -Makefile -images/ -example/ -*.tgz diff --git a/packages/core/installer/Makefile b/packages/core/installer/Makefile index a661bed4..ad9982b5 100644 --- a/packages/core/installer/Makefile +++ b/packages/core/installer/Makefile @@ -15,7 +15,7 @@ apply: diff: cozyhr show --namespace $(NAMESPACE) $(NAME) --plain | kubectl diff -f - -image: pre-checks image-operator image-packages chart +image: pre-checks image-operator image-packages image-operator: docker buildx build -f images/cozystack-operator/Dockerfile ../../.. \ @@ -31,7 +31,6 @@ image-operator: image-packages: mkdir -p ../../../_out/assets images - echo $$(git rev-parse HEAD; git diff HEAD; git ls-files --others --exclude-standard) | shasum -a 256 > ../platform/.build-revision flux push artifact \ oci://$(REGISTRY)/cozystack-packages:$(call settag,$(TAG)) \ --path=../../../packages \ @@ -44,9 +43,3 @@ image-packages: test -n "$$DIGEST" && \ yq -i '.cozystackOperator.platformSourceUrl = strenv(REPO)' values.yaml && \ yq -i '.cozystackOperator.platformSourceRef = "digest=" + strenv(DIGEST)' values.yaml - -chart: - set -e; \ - PKG=$$(helm package . --version $(COZYSTACK_VERSION) | awk '{print $$NF}'); \ - trap 'rm -f "$$PKG"' EXIT; \ - if [ "$(PUSH)" = "1" ]; then helm push "$$PKG" oci://$(REGISTRY); fi diff --git a/internal/crdinstall/manifests/.gitattributes b/packages/core/installer/definitions/.gitattributes similarity index 100% rename from internal/crdinstall/manifests/.gitattributes rename to packages/core/installer/definitions/.gitattributes diff --git a/internal/crdinstall/manifests/cozystack.io_packages.yaml b/packages/core/installer/definitions/cozystack.io_packages.yaml similarity index 100% rename from internal/crdinstall/manifests/cozystack.io_packages.yaml rename to packages/core/installer/definitions/cozystack.io_packages.yaml diff --git a/internal/crdinstall/manifests/cozystack.io_packagesources.yaml b/packages/core/installer/definitions/cozystack.io_packagesources.yaml similarity index 92% rename from internal/crdinstall/manifests/cozystack.io_packagesources.yaml rename to packages/core/installer/definitions/cozystack.io_packagesources.yaml index 1d0037df..0acfcdd2 100644 --- a/internal/crdinstall/manifests/cozystack.io_packagesources.yaml +++ b/packages/core/installer/definitions/cozystack.io_packagesources.yaml @@ -118,19 +118,6 @@ spec: ReleaseName is the name of the HelmRelease resource that will be created If not specified, defaults to the component Name field type: string - upgradeCRDs: - description: |- - UpgradeCRDs controls how CRDs from the chart's crds/ directory are - handled on HelmRelease upgrades. Maps to HelmRelease.Spec.Upgrade.CRDs. - Empty string (default) preserves the helm-controller default (Skip). - Use "CreateReplace" for operators that evolve their CRD set between - versions. Warning: CreateReplace overwrites CRDs and may cause data - loss if upstream drops fields from a CRD with live objects. - enum: - - Skip - - Create - - CreateReplace - type: string type: object libraries: description: |- diff --git a/packages/core/installer/templates/cozystack-operator-generic.yaml b/packages/core/installer/templates/cozystack-operator-generic.yaml new file mode 100644 index 00000000..510a92c8 --- /dev/null +++ b/packages/core/installer/templates/cozystack-operator-generic.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: cozy-system + labels: + cozystack.io/system: "true" + pod-security.kubernetes.io/enforce: privileged +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cozystack + namespace: cozy-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cozystack +subjects: +- kind: ServiceAccount + name: cozystack + namespace: cozy-system +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cozystack-operator + namespace: cozy-system +spec: + replicas: 1 + selector: + matchLabels: + app: cozystack-operator + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + template: + metadata: + labels: + app: cozystack-operator + spec: + serviceAccountName: cozystack + containers: + - name: cozystack-operator + image: "{{ .Values.cozystackOperator.image }}" + args: + - --leader-elect=true + - --install-flux=true + - --metrics-bind-address=0 + - --health-probe-bind-address= + {{- if .Values.cozystackOperator.disableTelemetry }} + - --disable-telemetry + {{- end }} + - --platform-source-name=cozystack-platform + - --platform-source-url={{ .Values.cozystackOperator.platformSourceUrl }} + {{- if .Values.cozystackOperator.platformSourceRef }} + - --platform-source-ref={{ .Values.cozystackOperator.platformSourceRef }} + {{- end }} + env: + # Generic Kubernetes: read from ConfigMap + # Create cozystack-operator-config ConfigMap before applying this manifest + - name: KUBERNETES_SERVICE_HOST + valueFrom: + configMapKeyRef: + name: cozystack-operator-config + key: KUBERNETES_SERVICE_HOST + optional: false + - name: KUBERNETES_SERVICE_PORT + valueFrom: + configMapKeyRef: + name: cozystack-operator-config + key: KUBERNETES_SERVICE_PORT + optional: false + hostNetwork: true + tolerations: + - key: "node.kubernetes.io/not-ready" + operator: "Exists" + - key: "node.kubernetes.io/unreachable" + operator: "Exists" + - key: "node.cilium.io/agent-not-ready" + operator: "Exists" + - key: "node.cloudprovider.kubernetes.io/uninitialized" + operator: "Exists" diff --git a/packages/core/installer/templates/cozystack-operator-hosted.yaml b/packages/core/installer/templates/cozystack-operator-hosted.yaml new file mode 100644 index 00000000..38ccdf75 --- /dev/null +++ b/packages/core/installer/templates/cozystack-operator-hosted.yaml @@ -0,0 +1,77 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: cozy-system + labels: + cozystack.io/system: "true" + pod-security.kubernetes.io/enforce: privileged +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cozystack + namespace: cozy-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cozystack +subjects: +- kind: ServiceAccount + name: cozystack + namespace: cozy-system +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cozystack-operator + namespace: cozy-system +spec: + replicas: 1 + selector: + matchLabels: + app: cozystack-operator + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + template: + metadata: + labels: + app: cozystack-operator + spec: + serviceAccountName: cozystack + containers: + - name: cozystack-operator + image: "{{ .Values.cozystackOperator.image }}" + args: + - --leader-elect=true + - --install-flux=true + - --metrics-bind-address=0 + - --health-probe-bind-address= + {{- if .Values.cozystackOperator.disableTelemetry }} + - --disable-telemetry + {{- end }} + - --platform-source-name=cozystack-platform + - --platform-source-url={{ .Values.cozystackOperator.platformSourceUrl }} + {{- if .Values.cozystackOperator.platformSourceRef }} + - --platform-source-ref={{ .Values.cozystackOperator.platformSourceRef }} + {{- end }} + # Hosted: use in-cluster service account, no env override needed + env: [] + hostNetwork: true + tolerations: + - key: "node.kubernetes.io/not-ready" + operator: "Exists" + - key: "node.kubernetes.io/unreachable" + operator: "Exists" + - key: "node.cilium.io/agent-not-ready" + operator: "Exists" + - key: "node.cloudprovider.kubernetes.io/uninitialized" + operator: "Exists" diff --git a/packages/core/installer/templates/cozystack-operator.yaml b/packages/core/installer/templates/cozystack-operator.yaml index aded0995..c40dc663 100644 --- a/packages/core/installer/templates/cozystack-operator.yaml +++ b/packages/core/installer/templates/cozystack-operator.yaml @@ -1,7 +1,3 @@ -{{- $validVariants := list "talos" "generic" "hosted" -}} -{{- if not (has .Values.cozystackOperator.variant $validVariants) -}} -{{- fail (printf "Invalid cozystackOperator.variant %q: must be one of talos, generic, hosted" .Values.cozystackOperator.variant) -}} -{{- end -}} --- apiVersion: v1 kind: Namespace @@ -10,8 +6,6 @@ metadata: labels: cozystack.io/system: "true" pod-security.kubernetes.io/enforce: privileged - annotations: - helm.sh/resource-policy: keep --- apiVersion: v1 kind: ServiceAccount @@ -59,12 +53,8 @@ spec: args: - --leader-elect=true - --install-flux=true - # The operator applies embedded CRDs via server-side apply on every - # startup, ensuring they stay up to date. - # To fully remove CRDs, delete them manually after helm uninstall. - - --install-crds=true - --metrics-bind-address=0 - - --health-probe-bind-address=0 + - --health-probe-bind-address= {{- if .Values.cozystackOperator.disableTelemetry }} - --disable-telemetry {{- end }} @@ -73,24 +63,12 @@ spec: {{- if .Values.cozystackOperator.platformSourceRef }} - --platform-source-ref={{ .Values.cozystackOperator.platformSourceRef }} {{- end }} - {{- if eq .Values.cozystackOperator.variant "talos" }} env: # Talos KubePrism endpoint - name: KUBERNETES_SERVICE_HOST value: "localhost" - name: KUBERNETES_SERVICE_PORT value: "7445" - {{- else if eq .Values.cozystackOperator.variant "generic" }} - env: - # Generic Kubernetes: API server endpoint - - name: KUBERNETES_SERVICE_HOST - value: {{ required "cozystack.apiServerHost is required in generic mode" .Values.cozystack.apiServerHost | quote }} - - name: KUBERNETES_SERVICE_PORT - value: {{ .Values.cozystack.apiServerPort | quote }} - {{- else if eq .Values.cozystackOperator.variant "hosted" }} - # Hosted: use in-cluster service account, no env override needed - env: [] - {{- end }} hostNetwork: true tolerations: - key: "node.kubernetes.io/not-ready" diff --git a/packages/system/backupstrategy-controller/templates/crds.yaml b/packages/core/installer/templates/crds.yaml similarity index 95% rename from packages/system/backupstrategy-controller/templates/crds.yaml rename to packages/core/installer/templates/crds.yaml index 32b438c1..7c7ea584 100644 --- a/packages/system/backupstrategy-controller/templates/crds.yaml +++ b/packages/core/installer/templates/crds.yaml @@ -1,4 +1,3 @@ {{- range $path, $_ := .Files.Glob "definitions/*.yaml" }} ---- {{ $.Files.Get $path }} {{- end }} diff --git a/packages/core/installer/templates/packagesource.yaml b/packages/core/installer/templates/packagesource.yaml new file mode 100644 index 00000000..f4a5f6d0 --- /dev/null +++ b/packages/core/installer/templates/packagesource.yaml @@ -0,0 +1,53 @@ +--- +apiVersion: cozystack.io/v1alpha1 +kind: PackageSource +metadata: + name: cozystack.cozystack-platform + annotations: + operator.cozystack.io/skip-cozystack-values: "true" +spec: + sourceRef: + kind: OCIRepository + name: cozystack-platform + namespace: cozy-system + path: / + variants: + - name: default + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - name: isp-full + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - values-isp-full.yaml + - name: isp-hosted + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - values-isp-hosted.yaml + - name: isp-full-generic + components: + - install: + namespace: cozy-system + releaseName: cozystack-platform + name: platform + path: core/platform + valuesFiles: + - values.yaml + - values-isp-full-generic.yaml diff --git a/packages/core/installer/values.yaml b/packages/core/installer/values.yaml index eef691ea..2325647e 100644 --- a/packages/core/installer/values.yaml +++ b/packages/core/installer/values.yaml @@ -1,15 +1,4 @@ cozystackOperator: - # Deployment variant: talos, generic, hosted - variant: talos - image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.3.0@sha256:62574f12486bb40c901cf5ed484cca264405ce5810196d86555cbb27cce1ba48 + image: ghcr.io/cozystack/cozystack/cozystack-operator:v1.0.0-beta.2@sha256:aaea9d8430187f208e6464cb6f102dcbbcdb0584b6a7a8a690ad91fc1f5d45e6 platformSourceUrl: 'oci://ghcr.io/cozystack/cozystack/cozystack-packages' - platformSourceRef: 'digest=sha256:a0b9ef938446b3132d3d22ad2262beb1027c48c9037b6c2346fdc2f19acd3036' -# Generic variant configuration (only used when cozystackOperator.variant=generic) -cozystack: - # Kubernetes API server host (IP only, no protocol/port) - # Must be the INTERNAL IP of the control-plane node - # (the IP visible on the node's network interface, not a public/NAT IP) - # Used by the operator and networking components (cilium, kube-ovn) - apiServerHost: "" - # Kubernetes API server port - apiServerPort: "6443" + platformSourceRef: 'digest=sha256:f59e562f2c91446117773ad457251d567706ea2964251a2b0acc65060fd1f3bc' diff --git a/packages/core/platform/Makefile b/packages/core/platform/Makefile index 15ed7b36..e47af225 100644 --- a/packages/core/platform/Makefile +++ b/packages/core/platform/Makefile @@ -1,18 +1,19 @@ -NAME=cozystack-platform +NAME=platform NAMESPACE=cozy-system include ../../../hack/common-envs.mk show: - cozyhr show --namespace $(NAMESPACE) $(NAME) + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain apply: - cozyhr apply --namespace $(NAMESPACE) $(NAME) + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain | kubectl apply --filename - + kubectl delete helmreleases.helm.toolkit.fluxcd.io --selector cozystack.io/marked-for-deletion=true --all-namespaces reconcile: apply diff: - cozyhr diff --namespace $(NAMESPACE) $(NAME) + cozyhr show --namespace $(NAMESPACE) $(NAME) --plain | kubectl diff --filename - image: image-migrations diff --git a/packages/core/platform/images/migrations/migrations/23 b/packages/core/platform/images/migrations/migrations/23 index 7cb9c85e..4e8c8e18 100755 --- a/packages/core/platform/images/migrations/migrations/23 +++ b/packages/core/platform/images/migrations/migrations/23 @@ -6,13 +6,6 @@ set -euo pipefail # Remove old cozystack-resource-definition-crd HelmRelease (renamed to application-definition-crd) kubectl delete hr -n cozy-system cozystack-resource-definition-crd --ignore-not-found -kubectl delete secrets -n cozy-system $( - kubectl get secrets -n cozy-system \ - -l owner=helm \ - -o jsonpath='{range .items[*]}{.metadata.labels.name}{" "}{.metadata.name}{"\n"}{end}' \ - | awk '$1 ~ /-rd$/ {print $2}' -) --ignore-not-found - # Stamp version kubectl create configmap -n cozy-system cozystack-version \ --from-literal=version=24 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/25 b/packages/core/platform/images/migrations/migrations/25 deleted file mode 100755 index 655cce23..00000000 --- a/packages/core/platform/images/migrations/migrations/25 +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# Migration 25 --> 26 -# Remove legacy installer components during upgrade to v1.0 - -set -euo pipefail - -echo "Removing legacy installer components..." - -# Delete old cozystack installer deployment -kubectl delete deploy cozystack -n cozy-system --ignore-not-found - -# Delete old cozystack-assets statefulset -kubectl delete sts cozystack-assets -n cozy-system --ignore-not-found - -# Delete old bootbox HelmReleases (will be recreated by new platform chart if enabled) -kubectl delete hr bootbox -n cozy-system --ignore-not-found -kubectl delete hr bootbox-rd -n cozy-system --ignore-not-found - -echo "Legacy cleanup completed" - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=26 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/26 b/packages/core/platform/images/migrations/migrations/26 deleted file mode 100755 index 96fb9851..00000000 --- a/packages/core/platform/images/migrations/migrations/26 +++ /dev/null @@ -1,172 +0,0 @@ -#!/bin/sh -# Migration 26 --> 27 -# Migrate monitoring resources from extra/monitoring to system/monitoring -# This migration re-labels resources so they become owned by monitoring-system HelmRelease -# and deletes old helm release secrets so that helm does not diff old vs new chart manifests. - -set -euo pipefail - -echo "Starting monitoring migration to monitoring-system" - -# Function to relabel resources of a given type in a namespace -relabel_resources() { - local ns="$1" - local resource_type="$2" - - # Get resources with monitoring release annotation - local resources - resources=$(kubectl get "$resource_type" -n "$ns" -o json 2>/dev/null | \ - jq -r '.items[] | select(.metadata.annotations["meta.helm.sh/release-name"] == "monitoring") | .metadata.name' 2>/dev/null || true) - - for resource_name in $resources; do - # Skip dashboard-resourcemap resources (they stay with parent monitoring release) - if echo "$resource_name" | grep -q "dashboard-resources"; then - echo " Skipping $resource_type/$resource_name (stays with parent release)" - continue - fi - - echo " Relabeling $resource_type/$resource_name" - - # Update annotations and labels - kubectl annotate "$resource_type" -n "$ns" "$resource_name" \ - meta.helm.sh/release-name=monitoring-system --overwrite 2>/dev/null || true - - kubectl label "$resource_type" -n "$ns" "$resource_name" \ - helm.toolkit.fluxcd.io/name=monitoring-system --overwrite 2>/dev/null || true - done -} - -# Delete all helm release secrets for a given release name in a namespace. -# Uses both label selector and name-pattern matching to ensure complete cleanup. -delete_helm_secrets() { - local ns="$1" - local release="$2" - - # Primary: delete by label selector - kubectl delete secrets -n "$ns" -l "name=${release},owner=helm" --ignore-not-found - - # Fallback: find and delete by name pattern (in case labels were modified) - local remaining - remaining=$(kubectl get secrets -n "$ns" -o name | { grep "^secret/sh\.helm\.release\.v1\.${release}\." || true; }) - if [ -n "$remaining" ]; then - echo " Found secrets not matched by label selector, deleting by name..." - echo "$remaining" | while IFS= read -r secret; do - echo " Deleting $secret" - kubectl delete -n "$ns" "$secret" --ignore-not-found - done - fi - - # Verify all secrets are gone - remaining=$(kubectl get secrets -n "$ns" -o name | { grep "^secret/sh\.helm\.release\.v1\.${release}\." || true; }) - if [ -n "$remaining" ]; then - echo " ERROR: Failed to delete helm release secrets:" - echo "$remaining" - return 1 - fi -} - -# Find all tenant namespaces with monitoring HelmRelease -echo "Finding tenant namespaces with monitoring HelmRelease..." -NAMESPACES=$(kubectl get hr --all-namespaces -l cozystack.io/ui=true --field-selector=metadata.name=monitoring \ - -o jsonpath='{range .items[*]}{.metadata.namespace}{"\n"}{end}' | sort -u) - -if [ -z "$NAMESPACES" ]; then - echo "No monitoring HelmReleases found in tenant namespaces, skipping migration" - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=27 --dry-run=client -o yaml | kubectl apply -f- - exit 0 -fi - -echo "Found namespaces with monitoring:" -echo "$NAMESPACES" - -# Process each namespace -for ns in $NAMESPACES; do - echo "" - echo "=========================================" - echo "Processing namespace: $ns" - echo "=========================================" - - # Check if monitoring HelmRelease exists - if ! kubectl get hr -n "$ns" monitoring >/dev/null 2>&1; then - echo "No monitoring HelmRelease in $ns, skipping" - continue - fi - - # Step 1: Suspend the HelmRelease - echo "" - echo "Step 1: Suspending HelmRelease monitoring..." - kubectl patch hr -n "$ns" monitoring --type=merge -p '{"spec":{"suspend":true}}' - - # Wait a moment for reconciliation to stop - sleep 2 - - # Step 2: Delete helm secrets for the monitoring release - echo "" - echo "Step 2: Deleting helm secrets for monitoring release..." - delete_helm_secrets "$ns" "monitoring" - - # Step 3: Relabel resources to be owned by monitoring-system - echo "" - echo "Step 3: Relabeling resources to monitoring-system..." - - # Core resources - echo "Processing core resources..." - relabel_resources "$ns" "secrets" - relabel_resources "$ns" "configmaps" - relabel_resources "$ns" "services" - - # Apps resources - echo "Processing apps resources..." - relabel_resources "$ns" "deployments.apps" - - # Networking resources - echo "Processing networking resources..." - relabel_resources "$ns" "ingresses.networking.k8s.io" - - # PostgreSQL operator resources - echo "Processing PostgreSQL resources..." - relabel_resources "$ns" "clusters.postgresql.cnpg.io" - - # Grafana operator resources - echo "Processing Grafana resources..." - relabel_resources "$ns" "grafanas.grafana.integreatly.org" - relabel_resources "$ns" "grafanadashboards.grafana.integreatly.org" - relabel_resources "$ns" "grafanadatasources.grafana.integreatly.org" - - # VictoriaMetrics operator resources - echo "Processing VictoriaMetrics resources..." - relabel_resources "$ns" "vmagents.operator.victoriametrics.com" - relabel_resources "$ns" "vmalerts.operator.victoriametrics.com" - relabel_resources "$ns" "vmalertmanagers.operator.victoriametrics.com" - relabel_resources "$ns" "vmclusters.operator.victoriametrics.com" - relabel_resources "$ns" "vmservicescrapes.operator.victoriametrics.com" - relabel_resources "$ns" "vlogs.operator.victoriametrics.com" - - # VPA resources - echo "Processing VPA resources..." - relabel_resources "$ns" "verticalpodautoscalers.autoscaling.k8s.io" - - # Cozystack resources - echo "Processing Cozystack resources..." - relabel_resources "$ns" "workloadmonitors.cozystack.io" - - # Step 4: Delete the suspended HelmRelease - # Helm secrets are already gone, so flux finalizer will find no release to uninstall - # and will simply remove the finalizer without deleting any resources. - echo "" - echo "Step 4: Deleting suspended HelmRelease monitoring..." - kubectl delete hr -n "$ns" monitoring --ignore-not-found - - echo "" - echo "Completed migration for namespace: $ns" -done - -echo "" -echo "=========================================" -echo "Monitoring migration completed successfully" -echo "=========================================" - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=27 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/27 b/packages/core/platform/images/migrations/migrations/27 deleted file mode 100755 index 5708ebbb..00000000 --- a/packages/core/platform/images/migrations/migrations/27 +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# Migration 27 --> 28 - -set -euo pipefail - -# Migrate Piraeus CRDs to piraeus-operator-crds Helm release -for crd in linstorclusters.piraeus.io linstornodeconnections.piraeus.io linstorsatelliteconfigurations.piraeus.io linstorsatellites.piraeus.io; do - if kubectl get crd "$crd" >/dev/null 2>&1; then - echo " Relabeling CRD $crd" - kubectl annotate crd "$crd" meta.helm.sh/release-namespace=cozy-linstor meta.helm.sh/release-name=piraeus-operator-crds --overwrite - kubectl label crd "$crd" app.kubernetes.io/managed-by=Helm helm.toolkit.fluxcd.io/namespace=cozy-linstor helm.toolkit.fluxcd.io/name=piraeus-operator-crds --overwrite - else - echo " CRD $crd not found, skipping" - fi -done - -# Delete old piraeus-operator helm secrets (by label and by name pattern) -kubectl delete secret -n cozy-linstor -l name=piraeus-operator,owner=helm --ignore-not-found -remaining=$(kubectl get secrets -n cozy-linstor -o name 2>/dev/null | { grep "^secret/sh\.helm\.release\.v1\.piraeus-operator\." || true; }) -if [ -n "$remaining" ]; then - echo " Deleting remaining piraeus-operator helm secrets by name..." - echo "$remaining" | while IFS= read -r secret; do - kubectl delete -n cozy-linstor "$secret" --ignore-not-found - done -fi - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=28 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/28 b/packages/core/platform/images/migrations/migrations/28 deleted file mode 100755 index 5174c9b0..00000000 --- a/packages/core/platform/images/migrations/migrations/28 +++ /dev/null @@ -1,629 +0,0 @@ -#!/bin/bash -# Migration 28 --> 29 -# Rename all mysql-prefixed resources to mariadb- across the cluster. -# Discovers all MySQL HelmReleases by label, migrates each instance. -# Idempotent: safe to re-run. - -set -euo pipefail - -OLD_PREFIX="mysql" -NEW_PREFIX="mariadb" -MARIADB_OPERATOR_NS="cozy-mariadb-operator" -MARIADB_WEBHOOK_NAME="mariadb-operator-webhook" -PROTECTION_WEBHOOK_NAME="protection-webhook" -PROTECTION_WEBHOOK_NS="protection-webhook" -declare -A OPERATOR_REPLICAS=() -declare -A ORIGINAL_PV_POLICIES=() - -# ============================================================ -# Helper functions -# ============================================================ - -resource_exists() { - local ns="$1" type="$2" name="$3" - kubectl -n "$ns" get "$type" "$name" --no-headers 2>/dev/null | grep -q . -} - -delete_resource() { - local ns="$1" type="$2" name="$3" - if resource_exists "$ns" "$type" "$name"; then - echo " [DELETE] ${type}/${name}" - kubectl -n "$ns" delete "$type" "$name" --wait=false - else - echo " [SKIP] ${type}/${name} already gone" - fi -} - -clone_resource() { - local ns="$1" type="$2" old_name="$3" new_name="$4" old_instance="$5" new_instance="$6" - - if resource_exists "$ns" "$type" "$new_name"; then - echo " [SKIP] ${type}/${new_name} already exists" - return 0 - fi - if ! resource_exists "$ns" "$type" "$old_name"; then - echo " [SKIP] ${type}/${old_name} not found" - return 0 - fi - - echo " [CREATE] ${type}/${new_name} from ${old_name}" - kubectl -n "$ns" get "$type" "$old_name" -o json | \ - jq --arg new_name "$new_name" --arg old "$old_instance" --arg new "$new_instance" ' - .metadata.name = $new_name | - del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, - .metadata.generation, .metadata.managedFields, .metadata.selfLink, - .metadata.ownerReferences) | - del(.status) | - .metadata.labels = ((.metadata.labels // {}) | with_entries( - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .metadata.annotations = ((.metadata.annotations // {}) | with_entries( - select(.key != "kubectl.kubernetes.io/last-applied-configuration") | - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) - ' | kubectl -n "$ns" apply -f - -} - -patch_webhook_policy() { - local name="$1" policy="$2" - echo " [PATCH] Set failurePolicy=${policy} on ValidatingWebhookConfiguration/${name}" - kubectl get validatingwebhookconfiguration "$name" -o json | \ - jq --arg p "$policy" '.webhooks[].failurePolicy = $p' | \ - kubectl apply -f - -} - -# ============================================================ -# STEP 1: Discover all MySQL instances -# ============================================================ -echo "=== Discovering MySQL HelmReleases ===" -INSTANCES=() -while IFS=/ read -r ns name; do - [ -z "$ns" ] && continue - instance="${name#${OLD_PREFIX}-}" - INSTANCES+=("${ns}/${instance}") - echo " Found: ${ns}/${name} (instance=${instance})" -done < <(kubectl get hr -A -l "apps.cozystack.io/application.kind=MySQL" \ - -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' 2>/dev/null) - -if [ ${#INSTANCES[@]} -eq 0 ]; then - echo " No MySQL HelmReleases found. Nothing to migrate." - - # Recover operator if a prior run left it scaled down - for deploy in mariadb-operator mariadb-operator-cert-controller mariadb-operator-webhook; do - current=$(kubectl -n "$MARIADB_OPERATOR_NS" get deploy "$deploy" \ - -o jsonpath='{.spec.replicas}' 2>/dev/null || echo "1") - if [ "$current" = "0" ]; then - echo " [RECOVER] Scaling ${deploy} -> 1" - kubectl -n "$MARIADB_OPERATOR_NS" scale deploy "$deploy" --replicas=1 - fi - done - - # Restore webhook if left at Ignore - current_policy=$(kubectl get validatingwebhookconfiguration "$MARIADB_WEBHOOK_NAME" \ - -o jsonpath='{.webhooks[0].failurePolicy}' 2>/dev/null || echo "unknown") - if [ "$current_policy" = "Ignore" ]; then - patch_webhook_policy "$MARIADB_WEBHOOK_NAME" "Fail" - fi - - # Unsuspend any new HelmReleases left suspended from a prior partial run - while IFS=/ read -r ns name; do - [ -z "$ns" ] && continue - suspended=$(kubectl -n "$ns" get hr "$name" -o jsonpath='{.spec.suspend}' 2>/dev/null || echo "false") - if [ "$suspended" = "true" ]; then - echo " [UNSUSPEND] ${ns}/hr/${name}" - kubectl -n "$ns" patch hr "$name" --type=merge -p '{"spec":{"suspend":false}}' - fi - done < <(kubectl get hr -A -l "apps.cozystack.io/application.kind=MariaDB" \ - -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' 2>/dev/null) - - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=29 --dry-run=client -o yaml | kubectl apply -f- - exit 0 -fi -echo " Total: ${#INSTANCES[@]} instance(s)" - -# ============================================================ -# STEP 2: Scale down mariadb-operator and disable its webhook -# ============================================================ -echo "" -echo "--- Step 2: Scale down mariadb-operator ---" -for deploy in mariadb-operator mariadb-operator-cert-controller mariadb-operator-webhook; do - current=$(kubectl -n "$MARIADB_OPERATOR_NS" get deploy "$deploy" -o jsonpath='{.spec.replicas}' 2>/dev/null || echo "0") - OPERATOR_REPLICAS["$deploy"]="$current" - if [ "$current" != "0" ]; then - echo " [SCALE] ${deploy} -> 0 (was ${current})" - kubectl -n "$MARIADB_OPERATOR_NS" scale deploy "$deploy" --replicas=0 - else - echo " [SKIP] ${deploy} already scaled to 0" - fi -done - -echo " Waiting for operator pods to terminate..." -kubectl -n "$MARIADB_OPERATOR_NS" wait --for=delete pod \ - -l app.kubernetes.io/instance=mariadb-operator --timeout=60s 2>/dev/null || true - -current_policy=$(kubectl get validatingwebhookconfiguration "$MARIADB_WEBHOOK_NAME" \ - -o jsonpath='{.webhooks[0].failurePolicy}' 2>/dev/null || echo "unknown") -if [ "$current_policy" = "Fail" ]; then - patch_webhook_policy "$MARIADB_WEBHOOK_NAME" "Ignore" -else - echo " [SKIP] Webhook ${MARIADB_WEBHOOK_NAME} already failurePolicy=${current_policy}" -fi - -# ============================================================ -# STEP 3: Migrate each instance -# ============================================================ -ALL_PV_NAMES=() -ALL_PROTECTED_RESOURCES=() - -for entry in "${INSTANCES[@]}"; do - NAMESPACE="${entry%%/*}" - INSTANCE="${entry#*/}" - OLD_NAME="${OLD_PREFIX}-${INSTANCE}" - NEW_NAME="${NEW_PREFIX}-${INSTANCE}" - - echo "" - echo "======================================================================" - echo "=== Migrating: ${OLD_NAME} -> ${NEW_NAME} in ${NAMESPACE}" - echo "======================================================================" - - # --- 3a: Suspend old HelmRelease --- - echo " --- Suspend HelmRelease ---" - if resource_exists "$NAMESPACE" "hr" "$OLD_NAME"; then - suspended=$(kubectl -n "$NAMESPACE" get hr "$OLD_NAME" -o jsonpath='{.spec.suspend}' 2>/dev/null || echo "false") - if [ "$suspended" != "true" ]; then - echo " [SUSPEND] hr/${OLD_NAME}" - kubectl -n "$NAMESPACE" patch hr "$OLD_NAME" --type=merge -p '{"spec":{"suspend":true}}' - else - echo " [SKIP] hr/${OLD_NAME} already suspended" - fi - else - echo " [SKIP] hr/${OLD_NAME} not found" - fi - - # --- 3b: Switch PV reclaim policy to Retain --- - echo " --- Switch PV reclaim to Retain ---" - PV_NAMES=() - replicas=$(kubectl -n "$NAMESPACE" get mariadb.k8s.mariadb.com "$OLD_NAME" \ - -o jsonpath='{.spec.replicas}' 2>/dev/null || true) - if [ -z "$replicas" ]; then - # Fallback: count existing PVCs matching the old or new name pattern - replicas=$(kubectl -n "$NAMESPACE" get pvc --no-headers -o name 2>/dev/null \ - | grep -cE "storage-${OLD_NAME}-[0-9]+$|storage-${NEW_NAME}-[0-9]+$" || echo "0") - echo " [INFO] MariaDB CR not found, derived replicas=${replicas} from existing PVCs" - fi - for i in $(seq 0 $((replicas - 1))); do - pvc_name="storage-${OLD_NAME}-${i}" - if resource_exists "$NAMESPACE" "pvc" "$pvc_name"; then - pv_name=$(kubectl -n "$NAMESPACE" get pvc "$pvc_name" -o jsonpath='{.spec.volumeName}') - PV_NAMES+=("$pv_name") - ALL_PV_NAMES+=("$pv_name") - current_policy=$(kubectl get pv "$pv_name" -o jsonpath='{.spec.persistentVolumeReclaimPolicy}') - if [ "$current_policy" != "Retain" ]; then - echo " [PATCH] PV ${pv_name}: ${current_policy} -> Retain" - ORIGINAL_PV_POLICIES["$pv_name"]="$current_policy" - kubectl patch pv "$pv_name" -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' - else - echo " [SKIP] PV ${pv_name} already Retain" - fi - else - new_pvc_name="storage-${NEW_NAME}-${i}" - if resource_exists "$NAMESPACE" "pvc" "$new_pvc_name"; then - pv_name=$(kubectl -n "$NAMESPACE" get pvc "$new_pvc_name" -o jsonpath='{.spec.volumeName}') - PV_NAMES+=("$pv_name") - ALL_PV_NAMES+=("$pv_name") - echo " [SKIP] New PVC ${new_pvc_name} already exists, PV=${pv_name}" - else - echo " [WARN] Neither old nor new PVC found for index ${i}" - PV_NAMES+=("") - fi - fi - done - - # --- 3c: Delete old StatefulSet and Deployment --- - echo " --- Delete old StatefulSet/Deployment ---" - if resource_exists "$NAMESPACE" "statefulset" "$OLD_NAME"; then - echo " [DELETE] statefulset/${OLD_NAME} (cascade=orphan)" - kubectl -n "$NAMESPACE" delete statefulset "$OLD_NAME" --cascade=orphan - else - echo " [SKIP] statefulset/${OLD_NAME} already gone" - fi - if resource_exists "$NAMESPACE" "deployment" "${OLD_NAME}-metrics"; then - echo " [DELETE] deployment/${OLD_NAME}-metrics" - kubectl -n "$NAMESPACE" delete deployment "${OLD_NAME}-metrics" - else - echo " [SKIP] deployment/${OLD_NAME}-metrics already gone" - fi - - # --- 3d: Delete old pods --- - echo " --- Delete old pods ---" - for i in $(seq 0 $((replicas - 1))); do - pod_name="${OLD_NAME}-${i}" - if resource_exists "$NAMESPACE" "pod" "$pod_name"; then - echo " [DELETE] pod/${pod_name}" - kubectl -n "$NAMESPACE" delete pod "$pod_name" --grace-period=30 - else - echo " [SKIP] pod/${pod_name} already gone" - fi - done - for pod in $(kubectl -n "$NAMESPACE" get pods \ - -l app.kubernetes.io/name=mysqld-exporter,app.kubernetes.io/instance="${OLD_NAME}" \ - -o name 2>/dev/null); do - echo " [DELETE] ${pod}" - kubectl -n "$NAMESPACE" delete "$pod" --grace-period=30 - done - - # --- 3e: Migrate PVCs --- - echo " --- Migrate PVCs ---" - for i in $(seq 0 $((replicas - 1))); do - old_pvc="storage-${OLD_NAME}-${i}" - new_pvc="storage-${NEW_NAME}-${i}" - pv_name="${PV_NAMES[$i]:-}" - - if [ -z "$pv_name" ]; then - echo " [WARN] No PV found for index ${i}, skipping" - continue - fi - - if resource_exists "$NAMESPACE" "pvc" "$new_pvc"; then - new_phase=$(kubectl -n "$NAMESPACE" get pvc "$new_pvc" \ - -o jsonpath='{.status.phase}' 2>/dev/null || echo "unknown") - if [ "$new_phase" = "Bound" ]; then - echo " [SKIP] PVC ${new_pvc} already Bound" - continue - fi - fi - - if resource_exists "$NAMESPACE" "pvc" "$old_pvc"; then - storage_size=$(kubectl -n "$NAMESPACE" get pvc "$old_pvc" \ - -o jsonpath='{.spec.resources.requests.storage}') - storage_class=$(kubectl -n "$NAMESPACE" get pvc "$old_pvc" \ - -o jsonpath='{.spec.storageClassName}') - old_labels=$(kubectl -n "$NAMESPACE" get pvc "$old_pvc" -o json | \ - jq --arg old "$OLD_NAME" --arg new "$NEW_NAME" \ - '(.metadata.labels // {}) | with_entries( - if (.value | type) == "string" and .value == $old then .value = $new else . end)') - - if ! resource_exists "$NAMESPACE" "pvc" "$new_pvc"; then - echo " [CREATE] PVC ${new_pvc} -> PV ${pv_name}" - cat < ${new_pvc}" - kubectl patch pv "$pv_name" --type=merge -p "{ - \"spec\":{\"claimRef\":{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolumeClaim\", - \"name\":\"${new_pvc}\",\"namespace\":\"${NAMESPACE}\",\"uid\":\"${new_pvc_uid}\"}} - }" - - echo " Waiting for PVC ${new_pvc} to bind..." - kubectl -n "$NAMESPACE" wait pvc "$new_pvc" \ - --for=jsonpath='{.status.phase}'=Bound --timeout=60s - echo " [OK] PVC ${new_pvc} is Bound" - fi - done - - # --- 3f: Clone Services --- - echo " --- Clone Services ---" - for suffix in "" "-internal" "-primary" "-secondary" "-metrics"; do - old_svc="${OLD_NAME}${suffix}" - new_svc="${NEW_NAME}${suffix}" - if resource_exists "$NAMESPACE" "svc" "$old_svc"; then - if resource_exists "$NAMESPACE" "svc" "$new_svc"; then - echo " [SKIP] svc/${new_svc} already exists" - else - echo " [CREATE] svc/${new_svc} from ${old_svc}" - kubectl -n "$NAMESPACE" get svc "$old_svc" -o json | \ - jq --arg new_svc "$new_svc" --arg old "$OLD_NAME" --arg new "$NEW_NAME" ' - .metadata.name = $new_svc | - del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, - .metadata.generation, .metadata.managedFields, .metadata.selfLink, - .metadata.ownerReferences) | - del(.status) | - del(.spec.clusterIP, .spec.clusterIPs) | - .metadata.labels = ((.metadata.labels // {}) | with_entries( - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .metadata.annotations = ((.metadata.annotations // {}) | with_entries( - select(.key != "kubectl.kubernetes.io/last-applied-configuration") | - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .spec.selector = ((.spec.selector // {}) | with_entries( - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) - ' | kubectl -n "$NAMESPACE" apply -f - - fi - fi - done - - # --- 3g: Clone Secrets --- - echo " --- Clone Secrets ---" - for secret in $(kubectl -n "$NAMESPACE" get secret -o name 2>/dev/null \ - | { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; }); do - old_secret_name="${secret#secret/}" - new_secret_name="${NEW_NAME}${old_secret_name#${OLD_NAME}}" - clone_resource "$NAMESPACE" "secret" "$old_secret_name" "$new_secret_name" "$OLD_NAME" "$NEW_NAME" - done - - # --- 3h: Clone ConfigMaps --- - echo " --- Clone ConfigMaps ---" - for cm in $(kubectl -n "$NAMESPACE" get configmap -o name 2>/dev/null \ - | { grep "configmap/${OLD_NAME}" || true; }); do - old_cm_name="${cm#configmap/}" - new_cm_name="${NEW_NAME}${old_cm_name#${OLD_NAME}}" - clone_resource "$NAMESPACE" "configmap" "$old_cm_name" "$new_cm_name" "$OLD_NAME" "$NEW_NAME" - done - - # --- 3i: Clone MariaDB CR --- - echo " --- Clone MariaDB CR ---" - if resource_exists "$NAMESPACE" "mariadb.k8s.mariadb.com" "$OLD_NAME"; then - if resource_exists "$NAMESPACE" "mariadb.k8s.mariadb.com" "$NEW_NAME"; then - echo " [SKIP] mariadb.k8s.mariadb.com/${NEW_NAME} already exists" - else - echo " [CREATE] mariadb.k8s.mariadb.com/${NEW_NAME}" - kubectl -n "$NAMESPACE" get mariadb.k8s.mariadb.com "$OLD_NAME" -o json | \ - jq --arg old "$OLD_NAME" --arg new "$NEW_NAME" ' - .metadata.name = $new | - del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, - .metadata.generation, .metadata.managedFields, .metadata.selfLink, - .metadata.finalizers, .metadata.ownerReferences) | - del(.status) | - .metadata.labels = ((.metadata.labels // {}) | with_entries( - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .metadata.annotations = ((.metadata.annotations // {}) | with_entries( - select(.key != "kubectl.kubernetes.io/last-applied-configuration") | - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .spec = (.spec | tostring | gsub($old; $new) | fromjson) - ' | kubectl -n "$NAMESPACE" apply -f - - fi - fi - - # --- 3j: Clone Users, Databases, Grants --- - echo " --- Clone Users, Databases, Grants ---" - for kind in "user.k8s.mariadb.com" "database.k8s.mariadb.com" "grant.k8s.mariadb.com"; do - for resource in $(kubectl -n "$NAMESPACE" get "$kind" -o name 2>/dev/null | grep "${OLD_NAME}"); do - old_res_name="${resource##*/}" - new_res_name="${NEW_NAME}${old_res_name#${OLD_NAME}}" - if resource_exists "$NAMESPACE" "$kind" "$new_res_name"; then - echo " [SKIP] ${kind}/${new_res_name} already exists" - else - echo " [CREATE] ${kind}/${new_res_name}" - kubectl -n "$NAMESPACE" get "$kind" "$old_res_name" -o json | \ - jq --arg old "$OLD_NAME" --arg new "$NEW_NAME" --arg new_name "$new_res_name" ' - .metadata.name = $new_name | - del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, - .metadata.generation, .metadata.managedFields, .metadata.selfLink, - .metadata.finalizers, .metadata.ownerReferences) | - del(.status) | - .metadata.labels = ((.metadata.labels // {}) | with_entries( - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .metadata.annotations = ((.metadata.annotations // {}) | with_entries( - select(.key != "kubectl.kubernetes.io/last-applied-configuration") | - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .spec = (.spec | tostring | gsub($old; $new) | fromjson) - ' | kubectl -n "$NAMESPACE" apply -f - - fi - done - done - - # --- 3k: Clone WorkloadMonitor --- - echo " --- Clone WorkloadMonitor ---" - clone_resource "$NAMESPACE" "workloadmonitor.cozystack.io" "$OLD_NAME" "$NEW_NAME" "$OLD_NAME" "$NEW_NAME" - - # --- 3l: Create new HelmRelease (suspended) --- - echo " --- Create new HelmRelease (suspended) ---" - if resource_exists "$NAMESPACE" "hr" "$NEW_NAME"; then - echo " [SKIP] hr/${NEW_NAME} already exists" - elif resource_exists "$NAMESPACE" "hr" "$OLD_NAME"; then - echo " [CREATE] hr/${NEW_NAME} from ${OLD_NAME} (suspended)" - kubectl -n "$NAMESPACE" get hr "$OLD_NAME" -o json | \ - jq --arg old "$OLD_NAME" --arg new "$NEW_NAME" \ - --arg old_prefix "$OLD_PREFIX" --arg new_prefix "$NEW_PREFIX" ' - .metadata.name = $new | - del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, - .metadata.generation, .metadata.managedFields, .metadata.selfLink, - .metadata.finalizers, .metadata.ownerReferences) | - del(.status) | - .metadata.labels = ((.metadata.labels // {}) | with_entries( - if (.value | type) == "string" then .value |= gsub($old; $new) else . end) | - if .["apps.cozystack.io/application.kind"] == "MySQL" - then .["apps.cozystack.io/application.kind"] = "MariaDB" - else . end) | - .metadata.annotations = ((.metadata.annotations // {}) | with_entries( - select(.key != "kubectl.kubernetes.io/last-applied-configuration") | - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - (if .spec.chart.spec.chart == $old_prefix - then .spec.chart.spec.chart = $new_prefix else . end) | - .spec.suspend = true - ' | kubectl -n "$NAMESPACE" apply -f - - else - echo " [WARN] hr/${OLD_NAME} not found, cannot clone" - fi - - # --- 3m: Delete old unprotected resources --- - echo " --- Delete old resources ---" - for kind in "grant.k8s.mariadb.com" "database.k8s.mariadb.com" "user.k8s.mariadb.com"; do - for resource in $(kubectl -n "$NAMESPACE" get "$kind" -o name 2>/dev/null | grep "${OLD_NAME}"); do - old_res_name="${resource##*/}" - kubectl -n "$NAMESPACE" patch "$kind" "$old_res_name" --type=json \ - -p='[{"op":"remove","path":"/metadata/finalizers"}]' 2>/dev/null || true - echo " [DELETE] ${kind}/${old_res_name}" - kubectl -n "$NAMESPACE" delete "$kind" "$old_res_name" --wait=false 2>/dev/null || true - done - done - - if resource_exists "$NAMESPACE" "mariadb.k8s.mariadb.com" "$OLD_NAME"; then - kubectl -n "$NAMESPACE" patch mariadb.k8s.mariadb.com "$OLD_NAME" --type=json \ - -p='[{"op":"remove","path":"/metadata/finalizers"}]' 2>/dev/null || true - delete_resource "$NAMESPACE" "mariadb.k8s.mariadb.com" "$OLD_NAME" - fi - - for secret in $(kubectl -n "$NAMESPACE" get secret -o name 2>/dev/null \ - | { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; }); do - old_secret_name="${secret#secret/}" - delete_resource "$NAMESPACE" "secret" "$old_secret_name" - done - - for cm in $(kubectl -n "$NAMESPACE" get configmap -o name 2>/dev/null \ - | { grep "configmap/${OLD_NAME}" || true; }); do - old_cm_name="${cm#configmap/}" - delete_resource "$NAMESPACE" "configmap" "$old_cm_name" - done - - delete_resource "$NAMESPACE" "workloadmonitor.cozystack.io" "$OLD_NAME" - - if resource_exists "$NAMESPACE" "hr" "$OLD_NAME"; then - kubectl -n "$NAMESPACE" patch hr "$OLD_NAME" --type=json \ - -p='[{"op":"remove","path":"/metadata/finalizers"}]' 2>/dev/null || true - delete_resource "$NAMESPACE" "hr" "$OLD_NAME" - fi - - echo " [DELETE] secrets with label owner=helm,name=${OLD_NAME}" - kubectl -n "$NAMESPACE" delete secret -l "owner=helm,name=${OLD_NAME}" 2>/dev/null || true - - # Collect protected resources for batch deletion - for suffix in "" "-internal" "-primary" "-secondary" "-metrics"; do - svc_name="${OLD_NAME}${suffix}" - if resource_exists "$NAMESPACE" "svc" "$svc_name"; then - ALL_PROTECTED_RESOURCES+=("${NAMESPACE}:svc/${svc_name}") - fi - done - for i in $(seq 0 $((replicas - 1))); do - old_pvc="storage-${OLD_NAME}-${i}" - if resource_exists "$NAMESPACE" "pvc" "$old_pvc"; then - ALL_PROTECTED_RESOURCES+=("${NAMESPACE}:pvc/${old_pvc}") - fi - done -done - -# ============================================================ -# STEP 4: Delete protected resources (PVCs, Services) -# ============================================================ -echo "" -echo "--- Step 4: Delete protected resources ---" - -if [ ${#ALL_PROTECTED_RESOURCES[@]} -gt 0 ]; then - echo " --- Temporarily disabling protection-webhook ---" - - WEBHOOK_REPLICAS=$(kubectl -n "$PROTECTION_WEBHOOK_NS" get deploy "$PROTECTION_WEBHOOK_NAME" \ - -o jsonpath='{.spec.replicas}' 2>/dev/null || echo "1") - - echo " [SCALE] ${PROTECTION_WEBHOOK_NAME} -> 0 (was ${WEBHOOK_REPLICAS})" - kubectl -n "$PROTECTION_WEBHOOK_NS" scale deploy "$PROTECTION_WEBHOOK_NAME" --replicas=0 - - patch_webhook_policy "$PROTECTION_WEBHOOK_NAME" "Ignore" - - echo " Waiting for webhook pods to terminate..." - kubectl -n "$PROTECTION_WEBHOOK_NS" wait --for=delete pod \ - -l app.kubernetes.io/name=protection-webhook --timeout=60s 2>/dev/null || true - sleep 3 - - for entry in "${ALL_PROTECTED_RESOURCES[@]}"; do - ns="${entry%%:*}" - res="${entry#*:}" - echo " [DELETE] ${ns}/${res}" - kubectl -n "$ns" delete "$res" --wait=false 2>/dev/null || true - done - - patch_webhook_policy "$PROTECTION_WEBHOOK_NAME" "Fail" - - echo " [SCALE] ${PROTECTION_WEBHOOK_NAME} -> ${WEBHOOK_REPLICAS}" - kubectl -n "$PROTECTION_WEBHOOK_NS" scale deploy "$PROTECTION_WEBHOOK_NAME" \ - --replicas="$WEBHOOK_REPLICAS" - echo " --- protection-webhook restored ---" -else - echo " [SKIP] No protected resources to delete" -fi - -# ============================================================ -# STEP 5: Restore PV reclaim policies -# ============================================================ -echo "" -echo "--- Step 5: Restore PV reclaim policies ---" -for pv_name in "${ALL_PV_NAMES[@]}"; do - if [ -n "$pv_name" ]; then - original="${ORIGINAL_PV_POLICIES[$pv_name]:-}" - if [ -n "$original" ]; then - echo " [PATCH] PV ${pv_name}: Retain -> ${original}" - kubectl patch pv "$pv_name" -p "{\"spec\":{\"persistentVolumeReclaimPolicy\":\"${original}\"}}" - else - echo " [SKIP] PV ${pv_name} was already Retain, leaving as-is" - fi - fi -done - -# ============================================================ -# STEP 6: Restore mariadb-operator -# ============================================================ -echo "" -echo "--- Step 6: Restore mariadb-operator ---" - -current_policy=$(kubectl get validatingwebhookconfiguration "$MARIADB_WEBHOOK_NAME" \ - -o jsonpath='{.webhooks[0].failurePolicy}' 2>/dev/null || echo "unknown") -if [ "$current_policy" = "Ignore" ]; then - patch_webhook_policy "$MARIADB_WEBHOOK_NAME" "Fail" -else - echo " [SKIP] Webhook ${MARIADB_WEBHOOK_NAME} already failurePolicy=${current_policy}" -fi - -for deploy in mariadb-operator mariadb-operator-cert-controller mariadb-operator-webhook; do - current=$(kubectl -n "$MARIADB_OPERATOR_NS" get deploy "$deploy" \ - -o jsonpath='{.spec.replicas}' 2>/dev/null || echo "1") - if [ "$current" = "0" ]; then - target="${OPERATOR_REPLICAS[$deploy]:-1}" - echo " [SCALE] ${deploy} -> ${target}" - kubectl -n "$MARIADB_OPERATOR_NS" scale deploy "$deploy" --replicas="$target" - else - echo " [SKIP] ${deploy} already running (replicas=${current})" - fi -done - -# ============================================================ -# STEP 7: Unsuspend all new HelmReleases -# ============================================================ -echo "" -echo "--- Step 7: Unsuspend new HelmReleases ---" -for entry in "${INSTANCES[@]}"; do - ns="${entry%%/*}" - instance="${entry#*/}" - new_name="${NEW_PREFIX}-${instance}" - if resource_exists "$ns" "hr" "$new_name"; then - suspended=$(kubectl -n "$ns" get hr "$new_name" \ - -o jsonpath='{.spec.suspend}' 2>/dev/null || echo "false") - if [ "$suspended" = "true" ]; then - echo " [UNSUSPEND] ${ns}/hr/${new_name}" - kubectl -n "$ns" patch hr "$new_name" --type=merge -p '{"spec":{"suspend":false}}' - else - echo " [SKIP] ${ns}/hr/${new_name} already not suspended" - fi - fi -done - -echo "" -echo "=== Migration complete (${#INSTANCES[@]} instance(s)) ===" - -# ============================================================ -# STEP 8: Clean up orphaned mysql-rd system HelmRelease -# ============================================================ -echo "" -echo "--- Step 8: Clean up orphaned mysql-rd HelmRelease ---" -if kubectl -n cozy-system get hr mysql-rd --no-headers 2>/dev/null | grep -q .; then - echo " [DELETE] hr/mysql-rd" - kubectl -n cozy-system delete hr mysql-rd --wait=false -else - echo " [SKIP] hr/mysql-rd already gone" -fi -kubectl -n cozy-system delete secret -l "owner=helm,name=mysql-rd" --ignore-not-found - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=29 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/29 b/packages/core/platform/images/migrations/migrations/29 deleted file mode 100755 index b72c2a93..00000000 --- a/packages/core/platform/images/migrations/migrations/29 +++ /dev/null @@ -1,733 +0,0 @@ -#!/bin/bash -# Migration 29 --> 30 -# Convert virtual-machine HelmReleases to vm-disk + vm-instance. -# Discovers all VirtualMachine HelmReleases by label, migrates each instance. -# Idempotent: safe to re-run. - -set -euo pipefail - -OLD_PREFIX="virtual-machine" -NEW_DISK_PREFIX="vm-disk" -NEW_INSTANCE_PREFIX="vm-instance" -CDI_APISERVER_NS="cozy-kubevirt-cdi" -CDI_APISERVER_DEPLOY="cdi-apiserver" -CDI_VALIDATING_WEBHOOKS="cdi-api-datavolume-validate cdi-api-dataimportcron-validate cdi-api-populator-validate cdi-api-validate" -CDI_MUTATING_WEBHOOKS="cdi-api-datavolume-mutate" - -# ============================================================ -# Helper functions -# ============================================================ - -resource_exists() { - local ns="$1" type="$2" name="$3" - kubectl -n "$ns" get "$type" "$name" --no-headers 2>/dev/null | grep -q . -} - -delete_resource() { - local ns="$1" type="$2" name="$3" - if resource_exists "$ns" "$type" "$name"; then - echo " [DELETE] ${type}/${name}" - kubectl -n "$ns" delete "$type" "$name" --wait=false - else - echo " [SKIP] ${type}/${name} already gone" - fi -} - -clone_resource() { - local ns="$1" type="$2" old_name="$3" new_name="$4" old_instance="$5" new_instance="$6" - - if resource_exists "$ns" "$type" "$new_name"; then - echo " [SKIP] ${type}/${new_name} already exists" - return 0 - fi - if ! resource_exists "$ns" "$type" "$old_name"; then - echo " [SKIP] ${type}/${old_name} not found" - return 0 - fi - - echo " [CREATE] ${type}/${new_name} from ${old_name}" - kubectl -n "$ns" get "$type" "$old_name" -o json | \ - jq --arg new_name "$new_name" --arg old "$old_instance" --arg new "$new_instance" ' - .metadata.name = $new_name | - del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, - .metadata.generation, .metadata.managedFields, .metadata.selfLink, - .metadata.ownerReferences) | - del(.status) | - .metadata.labels = ((.metadata.labels // {}) | with_entries( - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) | - .metadata.annotations = ((.metadata.annotations // {}) | with_entries( - select(.key != "kubectl.kubernetes.io/last-applied-configuration") | - if (.value | type) == "string" then .value |= gsub($old; $new) else . end)) - ' | kubectl -n "$ns" apply -f - -} - -# ============================================================ -# STEP 1: Discover all VirtualMachine instances -# ============================================================ -echo "=== Discovering VirtualMachine HelmReleases ===" -INSTANCES=() -while IFS=/ read -r ns name; do - [ -z "$ns" ] && continue - instance="${name#${OLD_PREFIX}-}" - INSTANCES+=("${ns}/${instance}") - echo " Found: ${ns}/${name} (instance=${instance})" -done < <(kubectl get hr -A -l "apps.cozystack.io/application.kind=VirtualMachine" \ - -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' 2>/dev/null) - -if [ ${#INSTANCES[@]} -eq 0 ]; then - echo " No VirtualMachine HelmReleases found. Nothing to migrate." - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=30 --dry-run=client -o yaml | kubectl apply -f- - exit 0 -fi -echo " Total: ${#INSTANCES[@]} instance(s)" - -# ============================================================ -# STEP 2: Migrate each instance -# ============================================================ -ALL_PV_NAMES=() - -for entry in "${INSTANCES[@]}"; do - NAMESPACE="${entry%%/*}" - INSTANCE="${entry#*/}" - OLD_NAME="${OLD_PREFIX}-${INSTANCE}" - NEW_DISK_NAME="${NEW_DISK_PREFIX}-${INSTANCE}" - NEW_INSTANCE_NAME="${NEW_INSTANCE_PREFIX}-${INSTANCE}" - - echo "" - echo "======================================================================" - echo "=== Migrating: ${OLD_NAME} -> ${NEW_DISK_NAME} + ${NEW_INSTANCE_NAME} in ${NAMESPACE}" - echo "======================================================================" - - # --- 2a: Suspend old HelmRelease --- - echo " --- Suspend HelmRelease ---" - if resource_exists "$NAMESPACE" "hr" "$OLD_NAME"; then - suspended=$(kubectl -n "$NAMESPACE" get hr "$OLD_NAME" -o jsonpath='{.spec.suspend}' 2>/dev/null || echo "false") - if [ "$suspended" != "true" ]; then - echo " [SUSPEND] hr/${OLD_NAME}" - kubectl -n "$NAMESPACE" patch hr "$OLD_NAME" --type=merge -p '{"spec":{"suspend":true}}' - else - echo " [SKIP] hr/${OLD_NAME} already suspended" - fi - else - echo " [SKIP] hr/${OLD_NAME} not found" - fi - - # --- 2b: Extract values from HelmRelease --- - echo " --- Extract values ---" - VALUES_SECRET="" - VALUES_KEY="values.yaml" - if resource_exists "$NAMESPACE" "hr" "$OLD_NAME"; then - VALUES_SECRET=$(kubectl -n "$NAMESPACE" get hr "$OLD_NAME" -o json | \ - jq -r '.spec.valuesFrom // [] | map(select(.kind == "Secret" and (.name | test("cozystack-values") | not))) | .[0].name // ""') - if [ -n "$VALUES_SECRET" ]; then - VALUES_KEY=$(kubectl -n "$NAMESPACE" get hr "$OLD_NAME" -o json | \ - jq -r '.spec.valuesFrom // [] | map(select(.kind == "Secret" and (.name | test("cozystack-values") | not))) | .[0].valuesKey // "values.yaml"') - fi - fi - - # Extract values from secret - EXTERNAL="false" - EXTERNAL_METHOD="PortList" - EXTERNAL_PORTS='[22]' - INSTANCE_TYPE="u1.medium" - INSTANCE_PROFILE="ubuntu" - RUN_STRATEGY="Always" - SYSTEM_DISK_IMAGE="ubuntu" - SYSTEM_DISK_STORAGE="5Gi" - SYSTEM_DISK_STORAGE_CLASS="replicated" - SSH_KEYS="[]" - CLOUD_INIT="" - CLOUD_INIT_SEED="" - SUBNETS="[]" - GPUS="[]" - CPU_MODEL="" - RESOURCES="{}" - - if [ -n "$VALUES_SECRET" ] && resource_exists "$NAMESPACE" "secret" "$VALUES_SECRET"; then - echo " Reading values from secret: ${VALUES_SECRET}" - VALUES_YAML=$(kubectl -n "$NAMESPACE" get secret "$VALUES_SECRET" -o jsonpath="{.data.${VALUES_KEY}}" 2>/dev/null | base64 -d 2>/dev/null || true) - if [ -z "$VALUES_YAML" ]; then - VALUES_YAML=$(kubectl -n "$NAMESPACE" get secret "$VALUES_SECRET" -o jsonpath="{.stringData.${VALUES_KEY}}" 2>/dev/null || true) - fi - if [ -n "$VALUES_YAML" ]; then - EXTERNAL=$(echo "$VALUES_YAML" | yq -r '.external // false') - EXTERNAL_METHOD=$(echo "$VALUES_YAML" | yq -r '.externalMethod // "PortList"') - EXTERNAL_PORTS=$(echo "$VALUES_YAML" | yq -c '.externalPorts // [22]') - INSTANCE_TYPE=$(echo "$VALUES_YAML" | yq -r '.instanceType // "u1.medium"') - INSTANCE_PROFILE=$(echo "$VALUES_YAML" | yq -r '.instanceProfile // "ubuntu"') - RUN_STRATEGY=$(echo "$VALUES_YAML" | yq -r '.runStrategy // (if .running == false then "Halted" else "Always" end)') - SYSTEM_DISK_IMAGE=$(echo "$VALUES_YAML" | yq -r '.systemDisk.image // "ubuntu"') - SYSTEM_DISK_STORAGE=$(echo "$VALUES_YAML" | yq -r '.systemDisk.storage // "5Gi"') - SYSTEM_DISK_STORAGE_CLASS=$(echo "$VALUES_YAML" | yq -r '.systemDisk.storageClass // "replicated"') - SSH_KEYS=$(echo "$VALUES_YAML" | yq -c '.sshKeys // []') - CLOUD_INIT=$(echo "$VALUES_YAML" | yq -r '.cloudInit // ""') - CLOUD_INIT_SEED=$(echo "$VALUES_YAML" | yq -r '.cloudInitSeed // ""') - SUBNETS=$(echo "$VALUES_YAML" | yq -c '.subnets // []') - GPUS=$(echo "$VALUES_YAML" | yq -c '.gpus // []') - CPU_MODEL=$(echo "$VALUES_YAML" | yq -r '.cpuModel // ""') - RESOURCES=$(echo "$VALUES_YAML" | yq -c '.resources // {}') - fi - fi - - echo " external=${EXTERNAL}, instanceType=${INSTANCE_TYPE}, image=${SYSTEM_DISK_IMAGE}" - - # --- 2c: Save kube-ovn IP --- - echo " --- Save kube-ovn IP ---" - OVN_IP="" - OVN_MAC="" - OVN_SUBNET="ovn-default" - OVN_IP_NAME="${OLD_NAME}.${NAMESPACE}" - if kubectl get ip.kubeovn.io "$OVN_IP_NAME" --no-headers 2>/dev/null | grep -q .; then - OVN_IP=$(kubectl get ip.kubeovn.io "$OVN_IP_NAME" -o jsonpath='{.spec.ipAddress}') - OVN_MAC=$(kubectl get ip.kubeovn.io "$OVN_IP_NAME" -o jsonpath='{.spec.macAddress}') - OVN_SUBNET=$(kubectl get ip.kubeovn.io "$OVN_IP_NAME" -o jsonpath='{.spec.subnet}') - echo " kube-ovn IP: ${OVN_IP}, MAC: ${OVN_MAC}, subnet: ${OVN_SUBNET}" - else - echo " [SKIP] No kube-ovn IP resource found" - fi - - # --- 2d: Save LoadBalancer IP (if external=true) --- - echo " --- Save LoadBalancer IP ---" - LB_IP="" - if [ "$EXTERNAL" = "true" ] && resource_exists "$NAMESPACE" "svc" "$OLD_NAME"; then - LB_IP=$(kubectl -n "$NAMESPACE" get svc "$OLD_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null || true) - if [ -n "$LB_IP" ]; then - echo " LoadBalancer IP: ${LB_IP}" - else - echo " [WARN] external=true but no LoadBalancer IP assigned" - fi - else - echo " [SKIP] Not external or no service" - fi - - # --- 2e: Switch PV reclaim policy to Retain --- - echo " --- Switch PV reclaim to Retain ---" - PV_NAME="" - if resource_exists "$NAMESPACE" "pvc" "$OLD_NAME"; then - PV_NAME=$(kubectl -n "$NAMESPACE" get pvc "$OLD_NAME" -o jsonpath='{.spec.volumeName}') - if [ -n "$PV_NAME" ]; then - ALL_PV_NAMES+=("$PV_NAME") - current_policy=$(kubectl get pv "$PV_NAME" -o jsonpath='{.spec.persistentVolumeReclaimPolicy}') - if [ "$current_policy" != "Retain" ]; then - echo " [PATCH] PV ${PV_NAME}: ${current_policy} -> Retain" - kubectl patch pv "$PV_NAME" -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}' - else - echo " [SKIP] PV ${PV_NAME} already Retain" - fi - fi - elif resource_exists "$NAMESPACE" "pvc" "$NEW_DISK_NAME"; then - PV_NAME=$(kubectl -n "$NAMESPACE" get pvc "$NEW_DISK_NAME" -o jsonpath='{.spec.volumeName}') - ALL_PV_NAMES+=("$PV_NAME") - echo " [SKIP] New PVC ${NEW_DISK_NAME} already exists, PV=${PV_NAME}" - else - echo " [WARN] No PVC found for ${OLD_NAME} or ${NEW_DISK_NAME}" - fi - - # --- 2f: Stop and delete the VirtualMachine --- - echo " --- Stop VirtualMachine ---" - if resource_exists "$NAMESPACE" "vm" "$OLD_NAME"; then - echo " [PATCH] Stop VM ${OLD_NAME}" - kubectl -n "$NAMESPACE" patch vm "$OLD_NAME" --type merge -p '{"spec":{"runStrategy":"Halted"}}' 2>/dev/null || \ - kubectl -n "$NAMESPACE" patch vm "$OLD_NAME" --type merge -p '{"spec":{"running":false}}' 2>/dev/null || true - - echo " Waiting for VMI to terminate..." - kubectl -n "$NAMESPACE" wait --for=delete vmi "$OLD_NAME" --timeout=120s 2>/dev/null || true - fi - - # --- 2g: Delete VirtualMachine CR (cascades to DataVolume and PVC) --- - echo " --- Delete VirtualMachine CR ---" - if resource_exists "$NAMESPACE" "vm" "$OLD_NAME"; then - echo " [DELETE] vm/${OLD_NAME}" - kubectl -n "$NAMESPACE" delete vm "$OLD_NAME" --wait=true --timeout=60s 2>/dev/null || true - fi - - echo " Waiting for old PVC to be deleted..." - for i in $(seq 1 30); do - if ! resource_exists "$NAMESPACE" "pvc" "$OLD_NAME"; then - echo " [OK] PVC ${OLD_NAME} deleted" - break - fi - sleep 2 - done - - # If PVC still exists (orphaned), delete it manually - if resource_exists "$NAMESPACE" "pvc" "$OLD_NAME"; then - echo " [DELETE] Orphaned pvc/${OLD_NAME}" - kubectl -n "$NAMESPACE" delete pvc "$OLD_NAME" --wait=false 2>/dev/null || true - fi - - # Delete orphaned DataVolume if still present - if resource_exists "$NAMESPACE" "dv" "$OLD_NAME"; then - echo " [DELETE] Orphaned dv/${OLD_NAME}" - kubectl -n "$NAMESPACE" delete dv "$OLD_NAME" --wait=false 2>/dev/null || true - fi - - # --- 2h: Create new PVC for vm-disk --- - echo " --- Create new PVC for vm-disk ---" - if [ -n "$PV_NAME" ]; then - if resource_exists "$NAMESPACE" "pvc" "$NEW_DISK_NAME"; then - new_phase=$(kubectl -n "$NAMESPACE" get pvc "$NEW_DISK_NAME" \ - -o jsonpath='{.status.phase}' 2>/dev/null || echo "unknown") - if [ "$new_phase" = "Bound" ]; then - echo " [SKIP] PVC ${NEW_DISK_NAME} already Bound" - fi - else - PV_VOLUME_MODE=$(kubectl get pv "$PV_NAME" -o jsonpath='{.spec.volumeMode}' 2>/dev/null || echo "Filesystem") - echo " [CREATE] PVC ${NEW_DISK_NAME} -> PV ${PV_NAME} (volumeMode=${PV_VOLUME_MODE})" - cat < ${NEW_DISK_NAME}" - kubectl patch pv "$PV_NAME" --type=merge -p "{ - \"spec\":{\"claimRef\":{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolumeClaim\", - \"name\":\"${NEW_DISK_NAME}\",\"namespace\":\"${NAMESPACE}\",\"uid\":\"${new_pvc_uid}\"}} - }" - - echo " Waiting for PVC ${NEW_DISK_NAME} to bind..." - kubectl -n "$NAMESPACE" wait pvc "$NEW_DISK_NAME" \ - --for=jsonpath='{.status.phase}'=Bound --timeout=60s - echo " [OK] PVC ${NEW_DISK_NAME} is Bound" - fi - fi - - # --- 2i: Clone Secrets --- - echo " --- Clone Secrets ---" - kubectl -n "$NAMESPACE" get secret -o name 2>/dev/null \ - | { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; } | { grep -v "values" || true; } \ - | while IFS= read -r secret; do - old_secret_name="${secret#secret/}" - suffix="${old_secret_name#${OLD_NAME}}" - new_secret_name="${NEW_INSTANCE_NAME}${suffix}" - clone_resource "$NAMESPACE" "secret" "$old_secret_name" "$new_secret_name" "$OLD_NAME" "$NEW_INSTANCE_NAME" - done - - # --- 2j: Clone WorkloadMonitor --- - echo " --- Clone WorkloadMonitor ---" - clone_resource "$NAMESPACE" "workloadmonitor.cozystack.io" "$OLD_NAME" "$NEW_INSTANCE_NAME" "$OLD_NAME" "$NEW_INSTANCE_NAME" - - # --- 2k: Migrate kube-ovn IP --- - echo " --- Migrate kube-ovn IP ---" - NEW_OVN_IP_NAME="${NEW_INSTANCE_NAME}.${NAMESPACE}" - if [ -n "$OVN_IP" ]; then - if kubectl get ip.kubeovn.io "$NEW_OVN_IP_NAME" --no-headers 2>/dev/null | grep -q .; then - echo " [SKIP] ip.kubeovn.io/${NEW_OVN_IP_NAME} already exists" - else - echo " [CREATE] ip.kubeovn.io/${NEW_OVN_IP_NAME}" - cat </dev/null | grep -q .; then - echo " [DELETE] ip.kubeovn.io/${OVN_IP_NAME}" - kubectl delete ip.kubeovn.io "$OVN_IP_NAME" 2>/dev/null || true - fi - fi - - # --- 2l: Create vm-disk values secret --- - echo " --- Create vm-disk values secret ---" - DISK_VALUES_SECRET="${NEW_DISK_NAME}-values" - if ! resource_exists "$NAMESPACE" "secret" "$DISK_VALUES_SECRET"; then - echo " [CREATE] secret/${DISK_VALUES_SECRET}" - cat </dev/null \ - | { grep "secret/${OLD_NAME}" || true; } | { grep -v "sh.helm.release" || true; } | { grep -v "values" || true; } \ - | while IFS= read -r secret; do - old_secret_name="${secret#secret/}" - delete_resource "$NAMESPACE" "secret" "$old_secret_name" - done - - delete_resource "$NAMESPACE" "workloadmonitor.cozystack.io" "$OLD_NAME" - - if resource_exists "$NAMESPACE" "hr" "$OLD_NAME"; then - kubectl -n "$NAMESPACE" patch hr "$OLD_NAME" --type=json \ - -p='[{"op":"remove","path":"/metadata/finalizers"}]' 2>/dev/null || true - delete_resource "$NAMESPACE" "hr" "$OLD_NAME" - fi - - echo " [DELETE] secrets with label owner=helm,name=${OLD_NAME}" - kubectl -n "$NAMESPACE" delete secret -l "owner=helm,name=${OLD_NAME}" 2>/dev/null || true - - # Delete old values secret - if [ -n "$VALUES_SECRET" ]; then - delete_resource "$NAMESPACE" "secret" "$VALUES_SECRET" - fi - - # Delete old service (if exists) - if resource_exists "$NAMESPACE" "svc" "$OLD_NAME"; then - delete_resource "$NAMESPACE" "svc" "$OLD_NAME" - fi -done - -# ============================================================ -# STEP 3: Restore PV reclaim policies -# ============================================================ -echo "" -echo "--- Step 3: Restore PV reclaim policies ---" -for pv_name in "${ALL_PV_NAMES[@]}"; do - if [ -n "$pv_name" ]; then - current_policy=$(kubectl get pv "$pv_name" \ - -o jsonpath='{.spec.persistentVolumeReclaimPolicy}' 2>/dev/null || echo "unknown") - if [ "$current_policy" = "Retain" ]; then - echo " [PATCH] PV ${pv_name}: Retain -> Delete" - kubectl patch pv "$pv_name" -p '{"spec":{"persistentVolumeReclaimPolicy":"Delete"}}' - else - echo " [SKIP] PV ${pv_name} already ${current_policy}" - fi - fi -done - -# ============================================================ -# STEP 4: Temporarily disable CDI datavolume webhooks -# ============================================================ -# CDI's datavolume-validate webhook rejects DataVolume creation when a PVC -# with the same name already exists. We must disable it so that vm-disk -# HelmReleases can reconcile and adopt the pre-created PVCs. -# We scale down both cdi-operator (which recreates webhook configs) and -# cdi-apiserver (which serves the webhooks), then delete webhook configs. -# Both are restored after vm-disk HRs reconcile. -echo "" -echo "--- Step 4: Temporarily disable CDI webhooks ---" - -CDI_OPERATOR_REPLICAS=$(kubectl -n "$CDI_APISERVER_NS" get deploy cdi-operator \ - -o jsonpath='{.spec.replicas}' 2>/dev/null || echo "1") -CDI_APISERVER_REPLICAS=$(kubectl -n "$CDI_APISERVER_NS" get deploy "$CDI_APISERVER_DEPLOY" \ - -o jsonpath='{.spec.replicas}' 2>/dev/null || echo "1") - -echo " [SCALE] cdi-operator -> 0 (was ${CDI_OPERATOR_REPLICAS})" -kubectl -n "$CDI_APISERVER_NS" scale deploy cdi-operator --replicas=0 -echo " [SCALE] ${CDI_APISERVER_DEPLOY} -> 0 (was ${CDI_APISERVER_REPLICAS})" -kubectl -n "$CDI_APISERVER_NS" scale deploy "$CDI_APISERVER_DEPLOY" --replicas=0 - -echo " Waiting for cdi pods to terminate..." -kubectl -n "$CDI_APISERVER_NS" wait --for=delete pod \ - -l cdi.kubevirt.io=cdi-apiserver --timeout=60s 2>/dev/null || true -kubectl -n "$CDI_APISERVER_NS" wait --for=delete pod \ - -l name=cdi-operator --timeout=60s 2>/dev/null || true - -for wh in $CDI_VALIDATING_WEBHOOKS; do - if kubectl get validatingwebhookconfiguration "$wh" >/dev/null 2>&1; then - echo " [DELETE] validatingwebhookconfiguration/${wh}" - kubectl delete validatingwebhookconfiguration "$wh" 2>/dev/null || true - fi -done -for wh in $CDI_MUTATING_WEBHOOKS; do - if kubectl get mutatingwebhookconfiguration "$wh" >/dev/null 2>&1; then - echo " [DELETE] mutatingwebhookconfiguration/${wh}" - kubectl delete mutatingwebhookconfiguration "$wh" 2>/dev/null || true - fi -done -sleep 2 - -# ============================================================ -# STEP 5: Unsuspend vm-disk HelmReleases first -# ============================================================ -echo "" -echo "--- Step 5: Unsuspend vm-disk HelmReleases ---" -for entry in "${INSTANCES[@]}"; do - ns="${entry%%/*}" - instance="${entry#*/}" - disk_name="${NEW_DISK_PREFIX}-${instance}" - if resource_exists "$ns" "hr" "$disk_name"; then - suspended=$(kubectl -n "$ns" get hr "$disk_name" \ - -o jsonpath='{.spec.suspend}' 2>/dev/null || echo "false") - if [ "$suspended" = "true" ]; then - echo " [UNSUSPEND] ${ns}/hr/${disk_name}" - kubectl -n "$ns" patch hr "$disk_name" --type=merge -p '{"spec":{"suspend":false}}' - else - echo " [SKIP] ${ns}/hr/${disk_name} already not suspended" - fi - # Force immediate reconciliation - echo " [TRIGGER] Reconcile ${ns}/hr/${disk_name}" - kubectl -n "$ns" annotate hr "$disk_name" --overwrite \ - "reconcile.fluxcd.io/requestedAt=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" 2>/dev/null || true - fi -done - -# Wait for disk HelmReleases to become ready -echo " Waiting for vm-disk HelmReleases to reconcile..." -for entry in "${INSTANCES[@]}"; do - ns="${entry%%/*}" - instance="${entry#*/}" - disk_name="${NEW_DISK_PREFIX}-${instance}" - for i in $(seq 1 60); do - ready=$(kubectl -n "$ns" get hr "$disk_name" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || true) - if [ "$ready" = "True" ]; then - echo " [OK] ${ns}/hr/${disk_name} is Ready" - break - fi - if [ "$i" = "60" ]; then - echo " [WARN] ${ns}/hr/${disk_name} did not become Ready within timeout" - fi - sleep 5 - done -done - -# ============================================================ -# STEP 6: Restore CDI webhooks -# ============================================================ -# Scale cdi-operator and cdi-apiserver back up. -# cdi-apiserver will recreate webhook configurations automatically on start. -echo "" -echo "--- Step 6: Restore CDI webhooks ---" - -echo " [SCALE] cdi-operator -> ${CDI_OPERATOR_REPLICAS}" -kubectl -n "$CDI_APISERVER_NS" scale deploy cdi-operator \ - --replicas="$CDI_OPERATOR_REPLICAS" -echo " [SCALE] ${CDI_APISERVER_DEPLOY} -> ${CDI_APISERVER_REPLICAS}" -kubectl -n "$CDI_APISERVER_NS" scale deploy "$CDI_APISERVER_DEPLOY" \ - --replicas="$CDI_APISERVER_REPLICAS" - -echo " Waiting for CDI to be ready..." -kubectl -n "$CDI_APISERVER_NS" rollout status deploy cdi-operator --timeout=120s 2>/dev/null || true -kubectl -n "$CDI_APISERVER_NS" rollout status deploy "$CDI_APISERVER_DEPLOY" --timeout=120s 2>/dev/null || true -echo " --- CDI webhooks restored ---" - -# ============================================================ -# STEP 7: Unsuspend vm-instance HelmReleases -# ============================================================ -echo "" -echo "--- Step 7: Unsuspend vm-instance HelmReleases ---" -for entry in "${INSTANCES[@]}"; do - ns="${entry%%/*}" - instance="${entry#*/}" - instance_name="${NEW_INSTANCE_PREFIX}-${instance}" - if resource_exists "$ns" "hr" "$instance_name"; then - suspended=$(kubectl -n "$ns" get hr "$instance_name" \ - -o jsonpath='{.spec.suspend}' 2>/dev/null || echo "false") - if [ "$suspended" = "true" ]; then - echo " [UNSUSPEND] ${ns}/hr/${instance_name}" - kubectl -n "$ns" patch hr "$instance_name" --type=merge -p '{"spec":{"suspend":false}}' - else - echo " [SKIP] ${ns}/hr/${instance_name} already not suspended" - fi - fi -done - -echo "" -echo "=== Migration complete (${#INSTANCES[@]} instance(s)) ===" - -# ============================================================ -# STEP 8: Clean up orphaned virtual-machine-rd system HelmRelease -# ============================================================ -echo "" -echo "--- Step 8: Clean up orphaned virtual-machine-rd HelmRelease ---" -if kubectl -n cozy-system get hr virtual-machine-rd --no-headers 2>/dev/null | grep -q .; then - echo " [DELETE] hr/virtual-machine-rd" - kubectl -n cozy-system delete hr virtual-machine-rd --wait=false -else - echo " [SKIP] hr/virtual-machine-rd already gone" -fi -kubectl -n cozy-system delete secret -l "owner=helm,name=virtual-machine-rd" --ignore-not-found - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=30 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/30 b/packages/core/platform/images/migrations/migrations/30 deleted file mode 100755 index 64b89305..00000000 --- a/packages/core/platform/images/migrations/migrations/30 +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash -# Migration 30 --> 31 -# Convert VPC subnets from map format to array format in HelmRelease values. -# Map format: subnets: {name: {cidr: x}} -# Array format: subnets: [{name: name, cidr: x}] -# Idempotent: skips if subnets is already an array or empty/null. - -set -euo pipefail - -# ============================================================ -# STEP 1: Discover all VirtualPrivateCloud HelmReleases -# ============================================================ -echo "=== Discovering VirtualPrivateCloud HelmReleases ===" -INSTANCES=() -while IFS=/ read -r ns name; do - [ -z "$ns" ] && continue - INSTANCES+=("${ns}/${name}") - echo " Found: ${ns}/${name}" -done < <(kubectl get hr -A -l "apps.cozystack.io/application.kind=VirtualPrivateCloud" \ - -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' 2>/dev/null) - -if [ ${#INSTANCES[@]} -eq 0 ]; then - echo " No VirtualPrivateCloud HelmReleases found. Nothing to migrate." - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=31 --dry-run=client -o yaml | kubectl apply -f- - exit 0 -fi -echo " Total: ${#INSTANCES[@]} instance(s)" - -# ============================================================ -# STEP 2: Migrate each instance -# ============================================================ -for entry in "${INSTANCES[@]}"; do - NAMESPACE="${entry%%/*}" - HR_NAME="${entry#*/}" - - echo "" - echo "======================================================================" - echo "=== Processing: ${HR_NAME} in ${NAMESPACE}" - echo "======================================================================" - - # --- Find values Secret --- - VALUES_SECRET=$(kubectl -n "$NAMESPACE" get hr "$HR_NAME" -o json | \ - jq -r '.spec.valuesFrom // [] | map(select(.kind == "Secret" and (.name | test("cozystack-values") | not))) | .[0].name // ""') - VALUES_KEY=$(kubectl -n "$NAMESPACE" get hr "$HR_NAME" -o json | \ - jq -r '.spec.valuesFrom // [] | map(select(.kind == "Secret" and (.name | test("cozystack-values") | not))) | .[0].valuesKey // "values.yaml"') - - if [ -z "$VALUES_SECRET" ]; then - echo " [SKIP] No values Secret found for hr/${HR_NAME}" - continue - fi - - if ! kubectl -n "$NAMESPACE" get secret "$VALUES_SECRET" --no-headers 2>/dev/null | grep -q .; then - echo " [SKIP] Secret ${VALUES_SECRET} not found" - continue - fi - - echo " Reading values from secret: ${VALUES_SECRET} (key: ${VALUES_KEY})" - - # --- Decode current values --- - VALUES_YAML=$(kubectl -n "$NAMESPACE" get secret "$VALUES_SECRET" \ - -o jsonpath="{.data.${VALUES_KEY}}" 2>/dev/null | base64 -d 2>/dev/null || true) - if [ -z "$VALUES_YAML" ]; then - VALUES_YAML=$(kubectl -n "$NAMESPACE" get secret "$VALUES_SECRET" \ - -o jsonpath="{.stringData.${VALUES_KEY}}" 2>/dev/null || true) - fi - - if [ -z "$VALUES_YAML" ]; then - echo " [SKIP] Could not read values from secret" - continue - fi - - # --- Check subnets type --- - SUBNETS_TYPE=$(echo "$VALUES_YAML" | yq -r '.subnets | type') - - case "$SUBNETS_TYPE" in - "!!map"|"object") - echo " [CONVERT] subnets is a map, converting to array" - ;; - "!!seq"|"array") - echo " [SKIP] subnets is already an array" - continue - ;; - "!!null"|"null") - echo " [SKIP] subnets is null/empty" - continue - ;; - *) - echo " [SKIP] subnets has unexpected type: ${SUBNETS_TYPE}" - continue - ;; - esac - - # --- Convert map to array --- - # {name: {cidr: x}} -> [{name: name, cidr: x}] - NEW_VALUES=$(echo "$VALUES_YAML" | yq ' - .subnets = ([.subnets | to_entries[] | {"name": .key} + .value]) - ') - - # --- Patch the Secret --- - NEW_VALUES_B64=$(echo "$NEW_VALUES" | base64) - echo " [PATCH] Updating secret/${VALUES_SECRET}" - kubectl -n "$NAMESPACE" get secret "$VALUES_SECRET" -o json | \ - jq --arg key "$VALUES_KEY" --arg val "$NEW_VALUES_B64" \ - '.data[$key] = $val' | \ - kubectl apply -f - - - echo " [OK] Converted subnets for ${HR_NAME}" -done - -echo "" -echo "=== Migration complete (${#INSTANCES[@]} instance(s)) ===" - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=31 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/31 b/packages/core/platform/images/migrations/migrations/31 deleted file mode 100755 index 2a261d9b..00000000 --- a/packages/core/platform/images/migrations/migrations/31 +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -# Migration 31 --> 32 -# Adopt tenant-root resources into cozystack-basics Helm release. -# -# In v0.41.x tenant-root Namespace and HelmRelease were applied via -# kubectl apply (no Helm tracking). In v1.0 they are managed by the -# cozystack-basics Helm release. Without Helm ownership annotations -# the install of cozystack-basics fails because the resources already -# exist. This migration adds the required annotations and labels so -# Helm can adopt them. - -set -euo pipefail - -RELEASE_NAME="cozystack-basics" -RELEASE_NS="cozy-system" - -# Adopt Namespace tenant-root -if kubectl get namespace tenant-root >/dev/null 2>&1; then - echo "Adopting Namespace tenant-root into $RELEASE_NAME" - kubectl annotate namespace tenant-root \ - meta.helm.sh/release-name="$RELEASE_NAME" \ - meta.helm.sh/release-namespace="$RELEASE_NS" \ - --overwrite - kubectl label namespace tenant-root \ - app.kubernetes.io/managed-by=Helm \ - --overwrite -fi - -# Adopt HelmRelease tenant-root -if kubectl get helmrelease -n tenant-root tenant-root >/dev/null 2>&1; then - echo "Adopting HelmRelease tenant-root into $RELEASE_NAME" - kubectl annotate helmrelease -n tenant-root tenant-root \ - meta.helm.sh/release-name="$RELEASE_NAME" \ - meta.helm.sh/release-namespace="$RELEASE_NS" \ - helm.sh/resource-policy=keep \ - --overwrite - kubectl label helmrelease -n tenant-root tenant-root \ - app.kubernetes.io/managed-by=Helm \ - sharding.fluxcd.io/key=tenants \ - --overwrite -fi - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=32 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/32 b/packages/core/platform/images/migrations/migrations/32 deleted file mode 100755 index c93a9312..00000000 --- a/packages/core/platform/images/migrations/migrations/32 +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh -# Migration 32 --> 33 -# Convert publishing.certificates.issuerType to solver + issuerName in -# the cozystack-platform Package resource. -# -# Old field (pre-refactor schema): -# publishing.certificates.issuerType: "http01" | "cloudflare" -# New fields: -# publishing.certificates.solver: "http01" | "dns01" -# publishing.certificates.issuerName: "letsencrypt-prod" (or custom) -# -# Conversion table: -# cloudflare -> solver: dns01, issuerName: letsencrypt-prod -# http01 -> solver: http01, issuerName: letsencrypt-prod -# -> issuerName: (solver left at chart default) -# -> no-op - -set -euo pipefail - -PACKAGE_NAME="cozystack.cozystack-platform" - -# Check if Package exists -if ! kubectl get package "$PACKAGE_NAME" >/dev/null 2>&1; then - echo "Package $PACKAGE_NAME not found, skipping migration" - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=33 --dry-run=client -o yaml | kubectl apply -f - - exit 0 -fi - -# Read current issuerType value -ISSUER_TYPE=$(kubectl get package "$PACKAGE_NAME" -o json | \ - jq -r '.spec.components.platform.values.publishing.certificates.issuerType // ""') - -if [ -z "$ISSUER_TYPE" ]; then - echo "No issuerType found in Package $PACKAGE_NAME, nothing to migrate" - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=33 --dry-run=client -o yaml | kubectl apply -f - - exit 0 -fi - -echo "Found issuerType: $ISSUER_TYPE" - -# Convert old issuerType to new solver/issuerName -SOLVER="" -ISSUER_NAME="" -case "$ISSUER_TYPE" in - cloudflare) - SOLVER="dns01" - ISSUER_NAME="letsencrypt-prod" - ;; - http01) - SOLVER="http01" - ISSUER_NAME="letsencrypt-prod" - ;; - *) - # Unrecognised value — treat as custom ClusterIssuer name, no solver override - ISSUER_NAME="$ISSUER_TYPE" - ;; -esac - -echo "Converting to: solver=${SOLVER:-}, issuerName=${ISSUER_NAME:-}" - -# Build the certificates patch: -# - null removes issuerType (JSON merge patch semantics) -# - solver and issuerName are included only when non-empty -CERTS_PATCH=$(jq -n --arg solver "$SOLVER" --arg issuerName "$ISSUER_NAME" ' - {"issuerType": null} - + (if $solver != "" then {"solver": $solver} else {} end) - + (if $issuerName != "" then {"issuerName": $issuerName} else {} end) -') - -PATCH_JSON=$(jq -n --argjson certs "$CERTS_PATCH" '{ - "spec": { - "components": { - "platform": { - "values": { - "publishing": { - "certificates": $certs - } - } - } - } - } -}') - -kubectl patch package "$PACKAGE_NAME" --type=merge --patch "$PATCH_JSON" - -echo "Migration complete: issuerType=$ISSUER_TYPE -> solver=${SOLVER:-} issuerName=${ISSUER_NAME:-}" - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=33 --dry-run=client -o yaml | kubectl apply -f - diff --git a/packages/core/platform/images/migrations/migrations/33 b/packages/core/platform/images/migrations/migrations/33 deleted file mode 100755 index 5da6788f..00000000 --- a/packages/core/platform/images/migrations/migrations/33 +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# Migration 33 --> 34 -# Clean up orphaned system -rd HelmReleases left after application renames. -# -# These HelmReleases reference ExternalArtifacts that no longer exist: -# ferretdb-rd -> replaced by mongodb-rd -# mysql-rd -> replaced by mariadb-rd (migration 28 handled user HRs only) -# virtual-machine-rd -> replaced by vm-disk-rd + vm-instance-rd (migration 29 handled user HRs only) -# -# Idempotent: safe to re-run. - -set -euo pipefail - -echo "=== Cleaning up orphaned -rd HelmReleases ===" - -for hr_name in ferretdb-rd mysql-rd virtual-machine-rd; do - if kubectl -n cozy-system get hr "$hr_name" --no-headers 2>/dev/null | grep -q .; then - echo " [DELETE] hr/${hr_name}" - kubectl -n cozy-system delete hr "$hr_name" --wait=false - else - echo " [SKIP] hr/${hr_name} already gone" - fi - kubectl -n cozy-system delete secret -l "owner=helm,name=${hr_name}" --ignore-not-found -done - -echo "=== Cleanup complete ===" - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=34 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/34 b/packages/core/platform/images/migrations/migrations/34 deleted file mode 100755 index f031d590..00000000 --- a/packages/core/platform/images/migrations/migrations/34 +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# Migration 34 --> 35 -# Backfill spec.version on rabbitmq.apps.cozystack.io resources. -# -# Before this migration RabbitMQ had no user-selectable version; the -# operator always used its built-in default image (v3.x). A version field -# was added in this release. Without this migration every existing cluster -# would be upgraded to the new default (v4.2) on the next reconcile. -# -# Set spec.version to "v3.13" for any rabbitmq app resource that does not -# already have it set. - -set -euo pipefail - -DEFAULT_VERSION="v3.13" - -# Skip if the CRD does not exist (rabbitmq was never installed) -if ! kubectl api-resources --api-group=apps.cozystack.io -o name 2>/dev/null | grep -q '^rabbitmqs\.'; then - echo "CRD rabbitmqs.apps.cozystack.io not found, skipping migration" - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=35 --dry-run=client -o yaml | kubectl apply -f- - exit 0 -fi - -RABBITMQS=$(kubectl get rabbitmqs.apps.cozystack.io -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}') -for resource in $RABBITMQS; do - NS="${resource%%/*}" - APP_NAME="${resource##*/}" - - # Skip if spec.version is already set - CURRENT_VER=$(kubectl get rabbitmqs.apps.cozystack.io -n "$NS" "$APP_NAME" \ - -o jsonpath='{.spec.version}') - if [ -n "$CURRENT_VER" ]; then - echo "SKIP $NS/$APP_NAME: spec.version already set to '$CURRENT_VER'" - continue - fi - - echo "Patching rabbitmq/$APP_NAME in $NS: setting version=$DEFAULT_VERSION" - - kubectl patch rabbitmqs.apps.cozystack.io -n "$NS" "$APP_NAME" --type=merge \ - --patch "{\"spec\":{\"version\":\"${DEFAULT_VERSION}\"}}" -done - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=35 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/35 b/packages/core/platform/images/migrations/migrations/35 deleted file mode 100755 index a7471180..00000000 --- a/packages/core/platform/images/migrations/migrations/35 +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# Migration 35 --> 36 -# Add helm.sh/resource-policy=keep annotation to existing VLogs resources -# so they are preserved when the monitoring helm release upgrades to VLCluster. -# Users will need to manually verify the new cluster is working, then optionally -# migrate historical data and delete old VLogs resources. - -set -euo pipefail - -VLOGS=$(kubectl get vlogs.operator.victoriametrics.com --all-namespaces --output jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}' 2>/dev/null || true) -for resource in $VLOGS; do - NS="${resource%%/*}" - NAME="${resource##*/}" - echo "Adding keep annotation to VLogs/$NAME in $NS" - kubectl annotate vlogs.operator.victoriametrics.com --namespace "$NS" "$NAME" \ - helm.sh/resource-policy=keep \ - --overwrite -done - -kubectl create configmap --namespace cozy-system cozystack-version \ - --from-literal=version=36 --dry-run=client --output yaml | kubectl apply --filename - diff --git a/packages/core/platform/images/migrations/migrations/36 b/packages/core/platform/images/migrations/migrations/36 deleted file mode 100755 index 0f0a94dd..00000000 --- a/packages/core/platform/images/migrations/migrations/36 +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# Migration 36 --> 37 -# -# Copy spec.subnets to spec.networks in VMInstance resources. -# The old "subnets" field is kept intact because migrations run before -# the new CRD is applied; removing it now would lose data. - -set -e - -if ! kubectl get crd vminstances.apps.cozystack.io >/dev/null 2>&1; then - echo "VMInstance CRD not found, skipping migration" -else -kubectl get vminstances.apps.cozystack.io -A -o json | jq -r ' - .items[] - | select(.spec.subnets != null and (.spec.subnets | length) > 0) - | select(.spec.networks == null or (.spec.networks | length) == 0) - | "kubectl -n \(.metadata.namespace) patch vminstances.apps.cozystack.io \(.metadata.name) --type=json -p '\''[{\"op\":\"add\",\"path\":\"/spec/networks\",\"value\":\(.spec.subnets|tojson)}]'\''" -' | sh -ex -fi - -# Write version to cozystack-version config -kubectl create configmap -n cozy-system cozystack-version --from-literal=version=37 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/37 b/packages/core/platform/images/migrations/migrations/37 deleted file mode 100755 index 856da262..00000000 --- a/packages/core/platform/images/migrations/migrations/37 +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash -# Migration 37 --> 38 -# Pin PostgreSQL image to 17.7-standard-trixie for system databases. -# -# This migration updates the imageName for all CNPG clusters belonging to -# system components (keycloak-db, grafana-db, alerta-db, seaweedfs-db, and -# harbor's dynamically-named DB): -# - If imageName is not set: pins to 17.7-standard-trixie -# - If imageName has any PG 17 tag: forces 17.7-standard-trixie -# - If imageName has a bare version tag (e.g. :18.1): appends -standard-trixie -# -# NOTE: This migration ONLY updates system CNPG Cluster resources (clusters.postgresql.cnpg.io), -# NOT user-created Postgres applications. - -set -euo pipefail - -TARGET_IMAGE="ghcr.io/cloudnative-pg/postgresql:17.7-standard-trixie" - -# Static system database names -STATIC_DB_NAMES="keycloak-db grafana-db alerta-db seaweedfs-db" - -echo "=== Updating PostgreSQL images for system databases ===" -echo "Target image: $TARGET_IMAGE" - -# Fetch all CNPG clusters with their name, namespace, imageName, and Helm release annotation in one call -ALL_CLUSTERS=$(kubectl get clusters.postgresql.cnpg.io -A \ - -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.imageName}{"\t"}{.metadata.annotations.meta\.helm\.sh/release-name}{"\n"}{end}' 2>/dev/null || true) - -while IFS=$'\t' read -r NAMESPACE CLUSTER_NAME CURRENT_IMAGE HELM_RELEASE; do - [ -z "$NAMESPACE" ] && continue - - # Check if cluster name matches one of the static system databases - MATCH=false - for db_name in $STATIC_DB_NAMES; do - if [ "$CLUSTER_NAME" = "$db_name" ]; then - MATCH=true - break - fi - done - - # For harbor: match clusters ending with -db whose Helm release ends with -system - if [ "$MATCH" = false ] && [[ "$CLUSTER_NAME" == *-db ]] && [[ "$HELM_RELEASE" == *-system ]]; then - MATCH=true - fi - - if [ "$MATCH" = false ]; then - continue - fi - - PATCH_IMAGE="" - - if [ -z "$CURRENT_IMAGE" ]; then - # imageName not set — pin to target - PATCH_IMAGE="$TARGET_IMAGE" - echo "PATCH $NAMESPACE/$CLUSTER_NAME: imageName not set, setting to $PATCH_IMAGE" - elif [[ "$CURRENT_IMAGE" =~ :17\. ]]; then - # Any PG 17 image — force to the pinned 17.7-standard-trixie - PATCH_IMAGE="$TARGET_IMAGE" - echo "PATCH $NAMESPACE/$CLUSTER_NAME: PG 17 detected, $CURRENT_IMAGE -> $PATCH_IMAGE" - elif [[ "$CURRENT_IMAGE" =~ :[0-9]+\.[0-9]+$ ]]; then - # Bare version tag for other majors (e.g. :18.1) — append -standard-trixie suffix - PATCH_IMAGE="${CURRENT_IMAGE}-standard-trixie" - echo "PATCH $NAMESPACE/$CLUSTER_NAME: bare tag detected, $CURRENT_IMAGE -> $PATCH_IMAGE" - else - echo "SKIP $NAMESPACE/$CLUSTER_NAME: imageName already set to $CURRENT_IMAGE" - continue - fi - - kubectl patch clusters.postgresql.cnpg.io -n "$NAMESPACE" "$CLUSTER_NAME" \ - --type=merge \ - --patch "{\"spec\":{\"imageName\":\"${PATCH_IMAGE}\"}}" -done <<< "$ALL_CLUSTERS" - -echo "=== PostgreSQL image update completed ===" - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=38 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/migrations/38 b/packages/core/platform/images/migrations/migrations/38 deleted file mode 100755 index 59536cb1..00000000 --- a/packages/core/platform/images/migrations/migrations/38 +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh -# Migration 38 --> 39 -# Rename DataVolumes/PVCs in cozy-public from vm-image- to vm-default-images-. -# -# The vm-disk package previously looked up golden images with the prefix "vm-image-". -# The new vm-default-images package uses the prefix "vm-default-images-". -# This migration renames any existing DataVolumes so that live vm-disk resources -# continue to resolve their source PVC after upgrade. - -set -euo pipefail - -NAMESPACE="cozy-public" - -# Skip if CDI DataVolume CRD is not installed -if ! kubectl api-resources --api-group=cdi.kubevirt.io -o name 2>/dev/null | grep -q '^datavolumes\.'; then - echo "CDI DataVolume CRD not found, skipping rename" - kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=39 --dry-run=client -o yaml | kubectl apply -f- - exit 0 -fi - -# Find DataVolumes whose name starts with "vm-image-" -DVNAMES=$(kubectl get datavolumes.cdi.kubevirt.io -n "$NAMESPACE" \ - -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null \ - | grep '^vm-image-' || true) - -if [ -z "$DVNAMES" ]; then - echo "No vm-image-* DataVolumes found in $NAMESPACE, nothing to rename" -else - for DVNAME in $DVNAMES; do - NEWNAME="vm-default-images-${DVNAME#vm-image-}" - echo "Renaming DataVolume $DVNAME -> $NEWNAME in namespace $NAMESPACE" - - # Export existing DV spec, swap name, and apply as new object - kubectl get datavolumes.cdi.kubevirt.io -n "$NAMESPACE" "$DVNAME" -o json \ - | jq --arg new "$NEWNAME" ' - del(.metadata.resourceVersion, .metadata.uid, .metadata.creationTimestamp, - .metadata.generation, .metadata.selfLink, .metadata.managedFields, - .status) - | .metadata.name = $new - ' \ - | kubectl apply -f - - - # Delete the old DataVolume - kubectl delete datavolumes.cdi.kubevirt.io -n "$NAMESPACE" "$DVNAME" --ignore-not-found=true - echo "Renamed $DVNAME -> $NEWNAME" - done -fi - -# Stamp version -kubectl create configmap -n cozy-system cozystack-version \ - --from-literal=version=39 --dry-run=client -o yaml | kubectl apply -f- diff --git a/packages/core/platform/images/migrations/run-migrations.sh b/packages/core/platform/images/migrations/run-migrations.sh index a8224ef7..c35ade21 100755 --- a/packages/core/platform/images/migrations/run-migrations.sh +++ b/packages/core/platform/images/migrations/run-migrations.sh @@ -24,7 +24,7 @@ if [ "$CURRENT_VERSION" -ge "$TARGET_VERSION" ]; then fi # Run migrations sequentially from current version to target version -for i in $(seq $CURRENT_VERSION $((TARGET_VERSION - 1))); do +for i in $(seq $((CURRENT_VERSION + 1)) $TARGET_VERSION); do if [ -f "/migrations/$i" ]; then echo "Running migration $i" chmod +x /migrations/$i diff --git a/packages/core/platform/sources/backupstrategy-controller.yaml b/packages/core/platform/sources/backupstrategy-controller.yaml deleted file mode 100644 index b86c5c0d..00000000 --- a/packages/core/platform/sources/backupstrategy-controller.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.backupstrategy-controller -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - components: - - name: backupstrategy-controller - path: system/backupstrategy-controller - install: - privileged: true - namespace: cozy-backup-controller - releaseName: backupstrategy-controller diff --git a/packages/core/platform/sources/cluster-autoscaler-azure.yaml b/packages/core/platform/sources/cluster-autoscaler-azure.yaml deleted file mode 100644 index 7709f3f7..00000000 --- a/packages/core/platform/sources/cluster-autoscaler-azure.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.cluster-autoscaler-azure -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - components: - - name: cluster-autoscaler-azure - path: system/cluster-autoscaler - valuesFiles: - - values.yaml - - values-azure.yaml - install: - namespace: cozy-cluster-autoscaler-azure - releaseName: cluster-autoscaler-azure diff --git a/packages/core/platform/sources/cluster-autoscaler-hetzner.yaml b/packages/core/platform/sources/cluster-autoscaler-hetzner.yaml deleted file mode 100644 index bbb1a85b..00000000 --- a/packages/core/platform/sources/cluster-autoscaler-hetzner.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.cluster-autoscaler-hetzner -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - components: - - name: cluster-autoscaler-hetzner - path: system/cluster-autoscaler - valuesFiles: - - values.yaml - - values-hetzner.yaml - install: - namespace: cozy-cluster-autoscaler-hetzner - releaseName: cluster-autoscaler-hetzner diff --git a/packages/core/platform/sources/clustersecret-operator.yaml b/packages/core/platform/sources/clustersecret-operator.yaml deleted file mode 100644 index 2dc800ab..00000000 --- a/packages/core/platform/sources/clustersecret-operator.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.clustersecret-operator -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - components: - - name: clustersecret-operator - path: system/clustersecret-operator - install: - namespace: cozy-clustersecret-operator - releaseName: clustersecret-operator diff --git a/packages/core/platform/sources/cozystack-scheduler.yaml b/packages/core/platform/sources/cozystack-scheduler.yaml deleted file mode 100644 index 52e85a4f..00000000 --- a/packages/core/platform/sources/cozystack-scheduler.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.cozystack-scheduler -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - components: - - name: cozystack-scheduler - path: system/cozystack-scheduler - install: - namespace: kube-system - releaseName: cozystack-scheduler - - name: linstor - dependsOn: - - cozystack.linstor-scheduler - components: - - name: cozystack-scheduler - path: system/cozystack-scheduler - valuesFiles: - - values-linstor.yaml - install: - namespace: kube-system - releaseName: cozystack-scheduler diff --git a/packages/core/platform/sources/etcd-operator.yaml b/packages/core/platform/sources/etcd-operator.yaml index 5f42a4a0..599ed2a3 100644 --- a/packages/core/platform/sources/etcd-operator.yaml +++ b/packages/core/platform/sources/etcd-operator.yaml @@ -14,7 +14,6 @@ spec: dependsOn: - cozystack.networking - cozystack.cert-manager - - cozystack.vertical-pod-autoscaler components: - name: etcd-operator path: system/etcd-operator diff --git a/packages/core/platform/sources/qdrant-application.yaml b/packages/core/platform/sources/ferretdb-application.yaml similarity index 59% rename from packages/core/platform/sources/qdrant-application.yaml rename to packages/core/platform/sources/ferretdb-application.yaml index 6477cc37..447745a5 100644 --- a/packages/core/platform/sources/qdrant-application.yaml +++ b/packages/core/platform/sources/ferretdb-application.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.qdrant-application + name: cozystack.ferretdb-application spec: sourceRef: kind: OCIRepository @@ -17,13 +17,11 @@ spec: - name: cozy-lib path: library/cozy-lib components: - - name: qdrant-system - path: system/qdrant - - name: qdrant - path: apps/qdrant - libraries: ["cozy-lib"] - - name: qdrant-rd - path: system/qdrant-rd + - name: ferretdb + path: apps/ferretdb + libraries: [cozy-lib] + - name: ferretdb-rd + path: system/ferretdb-rd install: namespace: cozy-system - releaseName: qdrant-rd + releaseName: ferretdb-rd diff --git a/packages/core/platform/sources/harbor-application.yaml b/packages/core/platform/sources/harbor-application.yaml deleted file mode 100644 index c2773bdd..00000000 --- a/packages/core/platform/sources/harbor-application.yaml +++ /dev/null @@ -1,32 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.harbor-application -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - - cozystack.postgres-operator - - cozystack.redis-operator - - cozystack.objectstorage-controller - libraries: - - name: cozy-lib - path: library/cozy-lib - components: - - name: harbor-system - path: system/harbor - - name: harbor - path: apps/harbor - libraries: ["cozy-lib"] - - name: harbor-rd - path: system/harbor-rd - install: - namespace: cozy-system - releaseName: harbor-rd diff --git a/packages/core/platform/sources/hami.yaml b/packages/core/platform/sources/kilo.yaml similarity index 59% rename from packages/core/platform/sources/hami.yaml rename to packages/core/platform/sources/kilo.yaml index 0184e405..72602164 100644 --- a/packages/core/platform/sources/hami.yaml +++ b/packages/core/platform/sources/kilo.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.hami + name: cozystack.kilo spec: sourceRef: kind: OCIRepository @@ -12,13 +12,11 @@ spec: variants: - name: default dependsOn: - - cozystack.gpu-operator + - cozystack.networking components: - - name: hami - path: system/hami - valuesFiles: - - values.yaml + - name: kilo + path: system/kilo install: privileged: true - namespace: cozy-hami - releaseName: hami + namespace: cozy-kilo + releaseName: kilo diff --git a/packages/core/platform/sources/kubernetes-application.yaml b/packages/core/platform/sources/kubernetes-application.yaml index 088383ad..9787cb19 100644 --- a/packages/core/platform/sources/kubernetes-application.yaml +++ b/packages/core/platform/sources/kubernetes-application.yaml @@ -52,8 +52,6 @@ spec: path: system/cilium - name: kubernetes-gpu-operator path: system/gpu-operator - - name: kubernetes-hami - path: system/hami - name: kubernetes-vertical-pod-autoscaler path: system/vertical-pod-autoscaler - name: kubernetes-prometheus-operator-crds diff --git a/packages/core/platform/sources/linstor-gui.yaml b/packages/core/platform/sources/linstor-gui.yaml deleted file mode 100644 index 005e1fb7..00000000 --- a/packages/core/platform/sources/linstor-gui.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.linstor-gui -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.linstor - components: - - name: linstor-gui - path: system/linstor-gui - install: - namespace: cozy-linstor - releaseName: linstor-gui diff --git a/packages/core/platform/sources/linstor.yaml b/packages/core/platform/sources/linstor.yaml index 6e2ec01a..f440affe 100644 --- a/packages/core/platform/sources/linstor.yaml +++ b/packages/core/platform/sources/linstor.yaml @@ -18,19 +18,11 @@ spec: - cozystack.reloader - cozystack.snapshot-controller components: - - name: piraeus-operator-crds - path: system/piraeus-operator-crds - install: - privileged: true - namespace: cozy-linstor - releaseName: piraeus-operator-crds - name: piraeus-operator path: system/piraeus-operator install: namespace: cozy-linstor releaseName: piraeus-operator - dependsOn: - - piraeus-operator-crds - name: linstor path: system/linstor install: diff --git a/packages/core/platform/sources/monitoring-application.yaml b/packages/core/platform/sources/monitoring-application.yaml index 119aaa37..6ea5a2d0 100644 --- a/packages/core/platform/sources/monitoring-application.yaml +++ b/packages/core/platform/sources/monitoring-application.yaml @@ -14,15 +14,10 @@ spec: dependsOn: - cozystack.networking - cozystack.postgres-operator - - cozystack.grafana-operator - - cozystack.victoria-metrics-operator libraries: - name: cozy-lib path: library/cozy-lib components: - - name: monitoring-system - path: system/monitoring - libraries: ["cozy-lib"] - name: monitoring path: extra/monitoring libraries: ["cozy-lib"] diff --git a/packages/core/platform/sources/monitoring.yaml b/packages/core/platform/sources/monitoring.yaml deleted file mode 100644 index ea2007ec..00000000 --- a/packages/core/platform/sources/monitoring.yaml +++ /dev/null @@ -1,43 +0,0 @@ - -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.monitoring - annotations: - operator.cozystack.io/skip-cozystack-values: "true" -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.vertical-pod-autoscaler - - cozystack.networking - - cozystack.postgres-operator - - cozystack.grafana-operator - - cozystack.victoria-metrics-operator - - cozystack.prometheus-operator-crds - libraries: - - name: cozy-lib - path: library/cozy-lib - components: - - name: monitoring - path: system/monitoring - libraries: ["cozy-lib"] - install: - privileged: true - namespace: cozy-monitoring - releaseName: monitoring - - name: vertical-pod-autoscaler - path: system/vertical-pod-autoscaler - - name: postgres-operator - path: system/postgres-operator - - name: grafana-operator - path: system/grafana-operator - - name: victoria-metrics-operator - path: system/victoria-metrics-operator - - name: prometheus-operator-crds - path: system/prometheus-operator-crds \ No newline at end of file diff --git a/packages/core/platform/sources/mariadb-application.yaml b/packages/core/platform/sources/mysql-application.yaml similarity index 71% rename from packages/core/platform/sources/mariadb-application.yaml rename to packages/core/platform/sources/mysql-application.yaml index 34ff901b..4b22e36e 100644 --- a/packages/core/platform/sources/mariadb-application.yaml +++ b/packages/core/platform/sources/mysql-application.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.mariadb-application + name: cozystack.mysql-application spec: sourceRef: kind: OCIRepository @@ -18,11 +18,11 @@ spec: - name: cozy-lib path: library/cozy-lib components: - - name: mariadb - path: apps/mariadb + - name: mysql + path: apps/mysql libraries: ["cozy-lib"] - - name: mariadb-rd - path: system/mariadb-rd + - name: mysql-rd + path: system/mysql-rd install: namespace: cozy-system - releaseName: mariadb-rd + releaseName: mysql-rd diff --git a/packages/core/platform/sources/networking.yaml b/packages/core/platform/sources/networking.yaml index bece76f8..9694dcc3 100644 --- a/packages/core/platform/sources/networking.yaml +++ b/packages/core/platform/sources/networking.yaml @@ -33,31 +33,6 @@ spec: releaseName: cilium-networkpolicy dependsOn: - cilium - - name: cilium-kilo - dependsOn: [] - components: - - name: cilium - path: system/cilium - valuesFiles: - - values.yaml - - values-talos.yaml - - values-kilo.yaml - install: - privileged: true - namespace: cozy-cilium - releaseName: cilium - dependsOn: [] - - name: kilo - path: system/kilo - valuesFiles: - - values.yaml - - values-cilium.yaml - install: - privileged: true - namespace: cozy-kilo - releaseName: kilo - dependsOn: - - cilium # Generic Cilium variant for non-Talos clusters (kubeadm, k3s, RKE2, etc.) - name: cilium-generic dependsOn: [] @@ -66,7 +41,6 @@ spec: path: system/cilium valuesFiles: - values.yaml - - values-apparmor.yaml install: privileged: true namespace: cozy-cilium @@ -118,7 +92,6 @@ spec: path: system/cilium valuesFiles: - values.yaml - - values-apparmor.yaml - values-kubeovn.yaml install: privileged: true diff --git a/packages/core/platform/sources/openbao-application.yaml b/packages/core/platform/sources/openbao-application.yaml deleted file mode 100644 index 438148af..00000000 --- a/packages/core/platform/sources/openbao-application.yaml +++ /dev/null @@ -1,29 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.openbao-application -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - libraries: - - name: cozy-lib - path: library/cozy-lib - components: - - name: openbao-system - path: system/openbao - - name: openbao - path: apps/openbao - libraries: ["cozy-lib"] - - name: openbao-rd - path: system/openbao-rd - install: - namespace: cozy-system - releaseName: openbao-rd diff --git a/packages/core/platform/sources/opensearch-application.yaml b/packages/core/platform/sources/opensearch-application.yaml deleted file mode 100644 index 19358c21..00000000 --- a/packages/core/platform/sources/opensearch-application.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.opensearch-application -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - - cozystack.opensearch-operator - libraries: - - name: cozy-lib - path: library/cozy-lib - components: - - name: opensearch - path: apps/opensearch - libraries: ["cozy-lib"] - - name: opensearch-rd - path: system/opensearch-rd - install: - namespace: cozy-system - releaseName: opensearch-rd diff --git a/packages/core/platform/sources/opensearch-operator.yaml b/packages/core/platform/sources/opensearch-operator.yaml deleted file mode 100644 index 21dd7a43..00000000 --- a/packages/core/platform/sources/opensearch-operator.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.opensearch-operator -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - - cozystack.prometheus-operator-crds - components: - - name: opensearch-operator - path: system/opensearch-operator - install: - namespace: cozy-opensearch-operator - releaseName: opensearch-operator diff --git a/packages/core/platform/sources/external-dns-application.yaml b/packages/core/platform/sources/virtual-machine-application.yaml similarity index 52% rename from packages/core/platform/sources/external-dns-application.yaml rename to packages/core/platform/sources/virtual-machine-application.yaml index 0a37dc52..b2583e7e 100644 --- a/packages/core/platform/sources/external-dns-application.yaml +++ b/packages/core/platform/sources/virtual-machine-application.yaml @@ -2,7 +2,7 @@ apiVersion: cozystack.io/v1alpha1 kind: PackageSource metadata: - name: cozystack.external-dns-application + name: cozystack.virtual-machine-application spec: sourceRef: kind: OCIRepository @@ -10,20 +10,20 @@ spec: namespace: cozy-system path: / variants: - - name: default + - name: kubevirt dependsOn: - cozystack.networking + - cozystack.kubevirt + - cozystack.kubevirt-cdi libraries: - name: cozy-lib path: library/cozy-lib components: - - name: external-dns-system - path: system/external-dns - - name: external-dns - path: extra/external-dns - libraries: ["cozy-lib"] - - name: external-dns-rd - path: system/external-dns-rd + - name: virtual-machine + path: apps/virtual-machine + libraries: [cozy-lib] + - name: virtual-machine-rd + path: system/virtual-machine-rd install: namespace: cozy-system - releaseName: external-dns-rd + releaseName: virtual-machine-rd diff --git a/packages/core/platform/sources/vm-default-images.yaml b/packages/core/platform/sources/vm-default-images.yaml deleted file mode 100644 index 16cd6a94..00000000 --- a/packages/core/platform/sources/vm-default-images.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -apiVersion: cozystack.io/v1alpha1 -kind: PackageSource -metadata: - name: cozystack.vm-default-images -spec: - sourceRef: - kind: OCIRepository - name: cozystack-packages - namespace: cozy-system - path: / - variants: - - name: default - dependsOn: - - cozystack.networking - - cozystack.kubevirt-cdi - components: - - name: vm-default-images - path: system/vm-default-images - install: - namespace: cozy-system - releaseName: vm-default-images diff --git a/packages/core/platform/templates/_helpers.tpl b/packages/core/platform/templates/_helpers.tpl index 4bc02429..684ee812 100644 --- a/packages/core/platform/templates/_helpers.tpl +++ b/packages/core/platform/templates/_helpers.tpl @@ -13,8 +13,6 @@ apiVersion: cozystack.io/v1alpha1 kind: Package metadata: name: {{ $name }} - annotations: - helm.sh/resource-policy: keep spec: variant: {{ $variant }} {{- if $components }} @@ -42,8 +40,6 @@ apiVersion: cozystack.io/v1alpha1 kind: Package metadata: name: {{ $name }} - annotations: - helm.sh/resource-policy: keep spec: variant: {{ $variant }} {{- end }} diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml index 6e1ae25a..ee3b35cf 100644 --- a/packages/core/platform/templates/apps.yaml +++ b/packages/core/platform/templates/apps.yaml @@ -21,25 +21,18 @@ stringData: _cluster: root-host: {{ $rootHost | quote }} bundle-name: {{ .Values.bundles.system.variant | quote }} - solver: {{ .Values.publishing.certificates.solver | quote }} - issuer-name: {{ .Values.publishing.certificates.issuerName | quote }} + clusterissuer: {{ .Values.publishing.certificates.issuerType | quote }} oidc-enabled: {{ .Values.authentication.oidc.enabled | quote }} - oidc-insecure-skip-verify: {{ .Values.authentication.oidc.insecureSkipVerify | quote }} extra-keycloak-redirect-uri-for-dashboard: {{ index .Values.authentication.oidc.keycloakExtraRedirectUri | quote }} - keycloak-internal-url: {{ .Values.authentication.oidc.keycloakInternalUrl | quote }} expose-services: {{ .Values.publishing.exposedServices | join "," | quote }} expose-ingress: {{ .Values.publishing.ingressName | quote }} expose-external-ips: {{ .Values.publishing.externalIPs | join "," | quote }} - expose-mode: {{ .Values.publishing.exposure | default "externalIPs" | quote }} cluster-domain: {{ .Values.networking.clusterDomain | quote }} api-server-endpoint: {{ .Values.publishing.apiServerEndpoint | quote }} {{- with .Values.branding }} branding: {{- . | toYaml | nindent 8 }} {{- end }} - cpu-allocation-ratio: {{ .Values.resources.cpuAllocationRatio | quote }} - memory-allocation-ratio: {{ .Values.resources.memoryAllocationRatio | quote }} - ephemeral-storage-allocation-ratio: {{ .Values.resources.ephemeralStorageAllocationRatio | quote }} {{- with .Values.scheduling }} scheduling: {{- . | toYaml | nindent 8 }} diff --git a/packages/core/platform/templates/bundles/iaas.yaml b/packages/core/platform/templates/bundles/iaas.yaml index 66ec98b2..7c856b8c 100644 --- a/packages/core/platform/templates/bundles/iaas.yaml +++ b/packages/core/platform/templates/bundles/iaas.yaml @@ -2,15 +2,9 @@ {{- fail "bundles.iaas.enabled can only be true when bundles.system.variant is 'isp-full' or 'isp-full-generic'" }} {{- end }} {{- if and .Values.bundles.iaas.enabled (or (eq .Values.bundles.system.variant "isp-full") (eq .Values.bundles.system.variant "isp-full-generic")) }} -{{- $kubevirtComponents := dict -}} -{{- if .Values.resources.cpuAllocationRatio -}} -{{- $_ := set $kubevirtComponents "kubevirt" (dict "values" (dict "cpuAllocationRatio" (.Values.resources.cpuAllocationRatio | int))) -}} -{{- end -}} -{{include "cozystack.platform.package" (list "cozystack.kubevirt" "default" $ $kubevirtComponents) }} +{{include "cozystack.platform.package.default" (list "cozystack.kubevirt" $) }} {{include "cozystack.platform.package.default" (list "cozystack.kubevirt-cdi" $) }} -{{include "cozystack.platform.package.optional.default" (list "cozystack.vm-default-images" $) }} {{include "cozystack.platform.package.optional.default" (list "cozystack.gpu-operator" $) }} -{{include "cozystack.platform.package.optional.default" (list "cozystack.hami" $) }} {{include "cozystack.platform.package.default" (list "cozystack.kamaji" $) }} {{include "cozystack.platform.package.default" (list "cozystack.capi-operator" $) }} {{include "cozystack.platform.package.default" (list "cozystack.capi-provider-bootstrap-kubeadm" $) }} @@ -19,6 +13,7 @@ {{include "cozystack.platform.package.default" (list "cozystack.capi-provider-infra-kubevirt" $) }} {{include "cozystack.platform.package.default" (list "cozystack.bucket-application" $) }} {{include "cozystack.platform.package" (list "cozystack.kubernetes-application" "kubevirt" $) }} +{{include "cozystack.platform.package" (list "cozystack.virtual-machine-application" "kubevirt" $) }} {{include "cozystack.platform.package" (list "cozystack.virtualprivatecloud-application" "kubevirt" $) }} {{include "cozystack.platform.package" (list "cozystack.vm-disk-application" "kubevirt" $) }} {{include "cozystack.platform.package" (list "cozystack.vm-instance-application" "kubevirt" $) }} diff --git a/packages/core/platform/templates/bundles/paas.yaml b/packages/core/platform/templates/bundles/paas.yaml index 54854368..359f0959 100644 --- a/packages/core/platform/templates/bundles/paas.yaml +++ b/packages/core/platform/templates/bundles/paas.yaml @@ -10,15 +10,13 @@ {{include "cozystack.platform.package.default" (list "cozystack.redis-operator" $) }} {{include "cozystack.platform.package.default" (list "cozystack.mongodb-operator" $) }} {{include "cozystack.platform.package.default" (list "cozystack.clickhouse-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.ferretdb-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.foundationdb-application" $) }} -{{include "cozystack.platform.package.default" (list "cozystack.harbor-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.kafka-application" $) }} -{{include "cozystack.platform.package.default" (list "cozystack.mariadb-application" $) }} +{{include "cozystack.platform.package.default" (list "cozystack.mysql-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.mongodb-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.nats-application" $) }} -{{include "cozystack.platform.package.default" (list "cozystack.openbao-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.postgres-application" $) }} -{{include "cozystack.platform.package.default" (list "cozystack.qdrant-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.rabbitmq-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.redis-application" $) }} {{- end }} diff --git a/packages/core/platform/templates/bundles/system.yaml b/packages/core/platform/templates/bundles/system.yaml index 6c587c82..c206cb44 100644 --- a/packages/core/platform/templates/bundles/system.yaml +++ b/packages/core/platform/templates/bundles/system.yaml @@ -25,12 +25,10 @@ {{include "cozystack.platform.package" (list "cozystack.networking" "kubeovn-cilium" $ $networkingComponents) }} {{include "cozystack.platform.system.common-packages" $ }} {{include "cozystack.platform.package.default" (list "cozystack.linstor" $) }} -{{include "cozystack.platform.package" (list "cozystack.cozystack-scheduler" "linstor" $) }} {{- end }} {{- if eq .Values.bundles.system.variant "isp-hosted" }} {{include "cozystack.platform.package" (list "cozystack.networking" "noop" $) }} -{{include "cozystack.platform.package.default" (list "cozystack.cozystack-scheduler" $) }} {{- end }} {{- if eq .Values.bundles.system.variant "isp-full-generic" }} @@ -72,12 +70,15 @@ "SVC_CIDR" $svcCIDR "JOIN_CIDR" $joinCIDR -}} {{- $kubeovnDict := dict "ipv4" $kubeovnIpv4 -}} -{{- /* Set MASTER_NODES: explicit value or empty (let kube-ovn discover nodes by label) */ -}} +{{- /* Set MASTER_NODES: explicit value > parsed from apiServerEndpoint > empty (use helm lookup) */ -}} {{- $masterNodes := .Values.networking.kubeovn.MASTER_NODES -}} +{{- if and (not $masterNodes) $apiServerEndpoint -}} +{{- $masterNodes = $apiHost -}} +{{- end -}} {{- if $masterNodes -}} {{- $_ := set $kubeovnDict "MASTER_NODES" $masterNodes -}} {{- end -}} -{{- /* For generic k8s (k3s), control-plane label has value "true" */ -}} +{{- /* For generic k8s (k3s, kubeadm), control-plane label has value "true" */ -}} {{- $_ := set $kubeovnDict "MASTER_NODES_LABEL" "node-role.kubernetes.io/control-plane=true" -}} {{- $kubeovnValues := dict "kube-ovn" $kubeovnDict -}} {{- $_ := set $networkingComponents "kubeovn" (dict "values" $kubeovnValues) -}} @@ -94,7 +95,6 @@ {{- /* Pass talos.enabled: false to linstor for generic Linux */ -}} {{- $linstorComponents := dict "linstor" (dict "values" (dict "talos" (dict "enabled" false))) -}} {{include "cozystack.platform.package" (list "cozystack.linstor" "default" $ $linstorComponents) }} -{{include "cozystack.platform.package" (list "cozystack.cozystack-scheduler" "linstor" $) }} {{- end }} # Cozystack Engine @@ -105,6 +105,9 @@ {{- /* cozystack-api DaemonSet */ -}} {{- $apiValues := dict "cozystackAPI" (dict "nodeSelector" $genericNodeSelector) -}} {{- $_ := set $cozystackEngineComponents "cozystack-api" (dict "values" $apiValues) -}} +{{- /* lineage-controller-webhook DaemonSet */ -}} +{{- $lineageValues := dict "lineageControllerWebhook" (dict "nodeSelector" $genericNodeSelector) -}} +{{- $_ := set $cozystackEngineComponents "lineage-controller-webhook" (dict "values" $lineageValues) -}} {{- end -}} {{- if .Values.authentication.oidc.enabled }} {{include "cozystack.platform.package" (list "cozystack.cozystack-engine" "oidc" $ $cozystackEngineComponents) }} @@ -128,12 +131,11 @@ {{include "cozystack.platform.package.default" (list "cozystack.monitoring-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.etcd-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.cozystack-basics" $) }} -{{include "cozystack.platform.package.default" (list "cozystack.backupstrategy-controller" $) }} {{include "cozystack.platform.package.default" (list "cozystack.backup-controller" $) }} +{{include "cozystack.platform.package.optional.default" (list "cozystack.velero" $) }} {{include "cozystack.platform.package.default" (list "cozystack.vertical-pod-autoscaler" $) }} {{include "cozystack.platform.package.default" (list "cozystack.metrics-server" $) }} -{{- $monitoringAgentsComponents := dict "monitoring-agents" (dict "values" (dict "global" (dict "target" "tenant-root"))) -}} -{{include "cozystack.platform.package" (list "cozystack.monitoring-agents" "default" $ $monitoringAgentsComponents) }} +{{include "cozystack.platform.package.default" (list "cozystack.monitoring-agents" $) }} {{include "cozystack.platform.package.default" (list "cozystack.goldpinger" $) }} {{include "cozystack.platform.package.default" (list "cozystack.prometheus-operator-crds" $) }} {{include "cozystack.platform.package.default" (list "cozystack.grafana-operator" $) }} @@ -145,10 +147,7 @@ {{include "cozystack.platform.package.optional.default" (list "cozystack.nfs-driver" $) }} {{include "cozystack.platform.package.optional.default" (list "cozystack.telepresence" $) }} {{include "cozystack.platform.package.optional.default" (list "cozystack.external-dns" $) }} -{{include "cozystack.platform.package.optional.default" (list "cozystack.external-dns-application" $) }} {{include "cozystack.platform.package.optional.default" (list "cozystack.external-secrets-operator" $) }} -{{include "cozystack.platform.package.optional.default" (list "cozystack.velero" $) }} -{{include "cozystack.platform.package.optional.default" (list "cozystack.linstor-gui" $) }} {{- if has "cozystack.bootbox" (default (list) .Values.bundles.enabledPackages) }} {{include "cozystack.platform.package.default" (list "cozystack.bootbox-application" $) }} {{include "cozystack.platform.package.default" (list "cozystack.bootbox" $) }} diff --git a/packages/core/platform/templates/cozystack-version.yaml b/packages/core/platform/templates/cozystack-version.yaml index 09b845c2..8e3ff6c6 100644 --- a/packages/core/platform/templates/cozystack-version.yaml +++ b/packages/core/platform/templates/cozystack-version.yaml @@ -6,8 +6,6 @@ kind: ConfigMap metadata: name: cozystack-version namespace: {{ .Release.Namespace }} - annotations: - helm.sh/resource-policy: keep data: version: {{ .Values.migrations.targetVersion | quote }} {{- end }} diff --git a/packages/core/platform/values.yaml b/packages/core/platform/values.yaml index 605e23bc..f7fec687 100644 --- a/packages/core/platform/values.yaml +++ b/packages/core/platform/values.yaml @@ -5,8 +5,8 @@ sourceRef: path: / migrations: enabled: false - image: ghcr.io/cozystack/cozystack/platform-migrations:v1.3.0@sha256:555e4b76421361805a84bc9088b01b23a9c4a9430bd8ebd2db82ef9677d7008c - targetVersion: 39 + image: ghcr.io/cozystack/cozystack/platform-migrations:latest + targetVersion: 24 # Bundle deployment configuration bundles: system: @@ -45,55 +45,13 @@ publishing: - cdi-uploadproxy apiServerEndpoint: "" # example: "https://api.example.org" externalIPs: [] - # Exposure mode for the ingress-nginx Service. When "externalIPs" (current - # default) is selected, the Service is created as ClusterIP with - # Service.spec.externalIPs set from publishing.externalIPs. When - # "loadBalancer" is selected, the Service is type: LoadBalancer and a - # CiliumLoadBalancerIPPool makes those same addresses allocatable via LB IPAM. - # - # Service.spec.externalIPs is deprecated upstream in Kubernetes v1.36 - # (KEP-5707). The AllowServiceExternalIPs feature gate is expected to default - # to false around v1.40 and the implementation removed around v1.43 — switch - # to "loadBalancer" before upgrading past v1.40. - # - # Caveats for the "loadBalancer" mode: - # - publishing.externalIPs must contain at least one non-empty address, - # otherwise the chart render fails with an explicit error (a LoadBalancer - # Service without a pool would sit in forever). - # - The ingress-nginx Service is created with externalTrafficPolicy: Local - # to preserve the client source IP. Traffic arriving on a node that does - # not host an ingress-nginx pod is dropped, so the external IP must be - # routed to a node that runs the ingress pod (floating IP / keepalived / - # upstream router / podAntiAffinity). - # - Cilium does NOT announce the IP on its own unless L2 announcements or - # BGP are enabled in the Cilium values (disabled by default in Cozystack). - # This mode assumes the operator already routes the externalIPs to a - # cluster node; enabling announcements is out of scope for this setting. - # - Switching this value on a running cluster causes the ingress-nginx - # Service to be recreated (the HelmRelease has upgrade.force: true and - # the Service kind changes between ClusterIP and LoadBalancer). Expect a - # brief interruption of ingress traffic during the flip. - # - # Scope: this setting only controls the ingress-nginx Service. Other - # cozystack components that currently write Service.spec.externalIPs directly - # (e.g. the vpn app at packages/apps/vpn/templates/service.yaml) are NOT - # migrated by flipping this value and must be addressed separately before - # the AllowServiceExternalIPs feature gate flips to off in ~v1.40. - exposure: externalIPs # "externalIPs" or "loadBalancer" certificates: - solver: http01 # "http01" or "dns01" - issuerName: letsencrypt-prod + issuerType: http01 # "http01" or "cloudflare" # Authentication configuration authentication: oidc: enabled: false - insecureSkipVerify: false keycloakExtraRedirectUri: "" - # Internal URL to access KeyCloak realm for backend-to-backend requests (bypasses external DNS). - # When set, oauth2-proxy uses --skip-oidc-discovery and routes all backend calls (token, jwks, - # userinfo, logout) through this URL while keeping browser redirects on the external URL. - # Example: http://keycloak-http.cozy-keycloak.svc:8080/realms/cozy - keycloakInternalUrl: "" # Pod scheduling configuration scheduling: globalAppTopologySpreadConstraints: "" diff --git a/packages/core/talos/images/talos/profiles/initramfs.yaml b/packages/core/talos/images/talos/profiles/initramfs.yaml index 182fb3e8..20bc27d3 100644 --- a/packages/core/talos/images/talos/profiles/initramfs.yaml +++ b/packages/core/talos/images/talos/profiles/initramfs.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.12.6 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.12.6" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20260309@sha256:716cd5350f77e7b10eebef88d8abdd0c32f2d929acd2bceac7ea33c0aac3b1a7 - - imageRef: ghcr.io/siderolabs/amdgpu:20260309-v1.12.6@sha256:64c7cbcde57a69742c76e3899385f5cd6af1238b0aba094962197fd4098838bd - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20260309@sha256:b17b87d9a20c806cf186e95ab351b771ffd622a35afcbd41eb07d4642680a231 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20260309@sha256:eee55c66cb23fe93380b83909af2cd4ede970205b861c0aa147404c88e8c7f65 - - imageRef: ghcr.io/siderolabs/i915:20260309-v1.12.6@sha256:6d150e23b2ca98ed34fca2b0510bc97e912f95839926bf6e02c55952e15387c2 - - imageRef: ghcr.io/siderolabs/intel-ucode:20260227@sha256:6112f6426a7081727545f7c33dcf2a89ff672494847b180380b4c58f3544a7b2 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20260309@sha256:b97cfde1e252412ba594a16302a3505f80aee1f105e2aa76b3bdf3b9dcc56cab - - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.6@sha256:f524139c5be4626d7f2b6bd47745ce93648f3f1ab2b681fb00f8ab97ec2c19a3 - - imageRef: ghcr.io/siderolabs/zfs:2.4.1-v1.12.6@sha256:059d39f1d2d6dde263dbd8062207d0aa68805bb0748c087494791c7f985b87d1 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: initramfs imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/installer.yaml b/packages/core/talos/images/talos/profiles/installer.yaml index c56c1d32..b219e012 100644 --- a/packages/core/talos/images/talos/profiles/installer.yaml +++ b/packages/core/talos/images/talos/profiles/installer.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.12.6 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.12.6" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20260309@sha256:716cd5350f77e7b10eebef88d8abdd0c32f2d929acd2bceac7ea33c0aac3b1a7 - - imageRef: ghcr.io/siderolabs/amdgpu:20260309-v1.12.6@sha256:64c7cbcde57a69742c76e3899385f5cd6af1238b0aba094962197fd4098838bd - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20260309@sha256:b17b87d9a20c806cf186e95ab351b771ffd622a35afcbd41eb07d4642680a231 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20260309@sha256:eee55c66cb23fe93380b83909af2cd4ede970205b861c0aa147404c88e8c7f65 - - imageRef: ghcr.io/siderolabs/i915:20260309-v1.12.6@sha256:6d150e23b2ca98ed34fca2b0510bc97e912f95839926bf6e02c55952e15387c2 - - imageRef: ghcr.io/siderolabs/intel-ucode:20260227@sha256:6112f6426a7081727545f7c33dcf2a89ff672494847b180380b4c58f3544a7b2 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20260309@sha256:b97cfde1e252412ba594a16302a3505f80aee1f105e2aa76b3bdf3b9dcc56cab - - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.6@sha256:f524139c5be4626d7f2b6bd47745ce93648f3f1ab2b681fb00f8ab97ec2c19a3 - - imageRef: ghcr.io/siderolabs/zfs:2.4.1-v1.12.6@sha256:059d39f1d2d6dde263dbd8062207d0aa68805bb0748c087494791c7f985b87d1 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: installer imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/iso.yaml b/packages/core/talos/images/talos/profiles/iso.yaml index 25fc336a..5773c6a6 100644 --- a/packages/core/talos/images/talos/profiles/iso.yaml +++ b/packages/core/talos/images/talos/profiles/iso.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.12.6 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.12.6" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20260309@sha256:716cd5350f77e7b10eebef88d8abdd0c32f2d929acd2bceac7ea33c0aac3b1a7 - - imageRef: ghcr.io/siderolabs/amdgpu:20260309-v1.12.6@sha256:64c7cbcde57a69742c76e3899385f5cd6af1238b0aba094962197fd4098838bd - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20260309@sha256:b17b87d9a20c806cf186e95ab351b771ffd622a35afcbd41eb07d4642680a231 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20260309@sha256:eee55c66cb23fe93380b83909af2cd4ede970205b861c0aa147404c88e8c7f65 - - imageRef: ghcr.io/siderolabs/i915:20260309-v1.12.6@sha256:6d150e23b2ca98ed34fca2b0510bc97e912f95839926bf6e02c55952e15387c2 - - imageRef: ghcr.io/siderolabs/intel-ucode:20260227@sha256:6112f6426a7081727545f7c33dcf2a89ff672494847b180380b4c58f3544a7b2 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20260309@sha256:b97cfde1e252412ba594a16302a3505f80aee1f105e2aa76b3bdf3b9dcc56cab - - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.6@sha256:f524139c5be4626d7f2b6bd47745ce93648f3f1ab2b681fb00f8ab97ec2c19a3 - - imageRef: ghcr.io/siderolabs/zfs:2.4.1-v1.12.6@sha256:059d39f1d2d6dde263dbd8062207d0aa68805bb0748c087494791c7f985b87d1 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: iso imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/kernel.yaml b/packages/core/talos/images/talos/profiles/kernel.yaml index d0153bf8..2f80bbda 100644 --- a/packages/core/talos/images/talos/profiles/kernel.yaml +++ b/packages/core/talos/images/talos/profiles/kernel.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.12.6 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.12.6" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20260309@sha256:716cd5350f77e7b10eebef88d8abdd0c32f2d929acd2bceac7ea33c0aac3b1a7 - - imageRef: ghcr.io/siderolabs/amdgpu:20260309-v1.12.6@sha256:64c7cbcde57a69742c76e3899385f5cd6af1238b0aba094962197fd4098838bd - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20260309@sha256:b17b87d9a20c806cf186e95ab351b771ffd622a35afcbd41eb07d4642680a231 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20260309@sha256:eee55c66cb23fe93380b83909af2cd4ede970205b861c0aa147404c88e8c7f65 - - imageRef: ghcr.io/siderolabs/i915:20260309-v1.12.6@sha256:6d150e23b2ca98ed34fca2b0510bc97e912f95839926bf6e02c55952e15387c2 - - imageRef: ghcr.io/siderolabs/intel-ucode:20260227@sha256:6112f6426a7081727545f7c33dcf2a89ff672494847b180380b4c58f3544a7b2 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20260309@sha256:b97cfde1e252412ba594a16302a3505f80aee1f105e2aa76b3bdf3b9dcc56cab - - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.6@sha256:f524139c5be4626d7f2b6bd47745ce93648f3f1ab2b681fb00f8ab97ec2c19a3 - - imageRef: ghcr.io/siderolabs/zfs:2.4.1-v1.12.6@sha256:059d39f1d2d6dde263dbd8062207d0aa68805bb0748c087494791c7f985b87d1 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: kernel imageOptions: {} diff --git a/packages/core/talos/images/talos/profiles/metal.yaml b/packages/core/talos/images/talos/profiles/metal.yaml index 579cc333..d460e0d8 100644 --- a/packages/core/talos/images/talos/profiles/metal.yaml +++ b/packages/core/talos/images/talos/profiles/metal.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: metal secureboot: false -version: v1.12.6 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.12.6" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20260309@sha256:716cd5350f77e7b10eebef88d8abdd0c32f2d929acd2bceac7ea33c0aac3b1a7 - - imageRef: ghcr.io/siderolabs/amdgpu:20260309-v1.12.6@sha256:64c7cbcde57a69742c76e3899385f5cd6af1238b0aba094962197fd4098838bd - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20260309@sha256:b17b87d9a20c806cf186e95ab351b771ffd622a35afcbd41eb07d4642680a231 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20260309@sha256:eee55c66cb23fe93380b83909af2cd4ede970205b861c0aa147404c88e8c7f65 - - imageRef: ghcr.io/siderolabs/i915:20260309-v1.12.6@sha256:6d150e23b2ca98ed34fca2b0510bc97e912f95839926bf6e02c55952e15387c2 - - imageRef: ghcr.io/siderolabs/intel-ucode:20260227@sha256:6112f6426a7081727545f7c33dcf2a89ff672494847b180380b4c58f3544a7b2 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20260309@sha256:b97cfde1e252412ba594a16302a3505f80aee1f105e2aa76b3bdf3b9dcc56cab - - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.6@sha256:f524139c5be4626d7f2b6bd47745ce93648f3f1ab2b681fb00f8ab97ec2c19a3 - - imageRef: ghcr.io/siderolabs/zfs:2.4.1-v1.12.6@sha256:059d39f1d2d6dde263dbd8062207d0aa68805bb0748c087494791c7f985b87d1 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: image imageOptions: { diskSize: 1306525696, diskFormat: raw } diff --git a/packages/core/talos/images/talos/profiles/nocloud.yaml b/packages/core/talos/images/talos/profiles/nocloud.yaml index 24ad7f3c..3dfb37f7 100644 --- a/packages/core/talos/images/talos/profiles/nocloud.yaml +++ b/packages/core/talos/images/talos/profiles/nocloud.yaml @@ -3,24 +3,24 @@ arch: amd64 platform: nocloud secureboot: false -version: v1.12.6 +version: v1.12.1 input: kernel: path: /usr/install/amd64/vmlinuz initramfs: path: /usr/install/amd64/initramfs.xz baseInstaller: - imageRef: "ghcr.io/siderolabs/installer:v1.12.6" + imageRef: "ghcr.io/siderolabs/installer:v1.12.1" systemExtensions: - - imageRef: ghcr.io/siderolabs/amd-ucode:20260309@sha256:716cd5350f77e7b10eebef88d8abdd0c32f2d929acd2bceac7ea33c0aac3b1a7 - - imageRef: ghcr.io/siderolabs/amdgpu:20260309-v1.12.6@sha256:64c7cbcde57a69742c76e3899385f5cd6af1238b0aba094962197fd4098838bd - - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20260309@sha256:b17b87d9a20c806cf186e95ab351b771ffd622a35afcbd41eb07d4642680a231 - - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20260309@sha256:eee55c66cb23fe93380b83909af2cd4ede970205b861c0aa147404c88e8c7f65 - - imageRef: ghcr.io/siderolabs/i915:20260309-v1.12.6@sha256:6d150e23b2ca98ed34fca2b0510bc97e912f95839926bf6e02c55952e15387c2 - - imageRef: ghcr.io/siderolabs/intel-ucode:20260227@sha256:6112f6426a7081727545f7c33dcf2a89ff672494847b180380b4c58f3544a7b2 - - imageRef: ghcr.io/siderolabs/qlogic-firmware:20260309@sha256:b97cfde1e252412ba594a16302a3505f80aee1f105e2aa76b3bdf3b9dcc56cab - - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.6@sha256:f524139c5be4626d7f2b6bd47745ce93648f3f1ab2b681fb00f8ab97ec2c19a3 - - imageRef: ghcr.io/siderolabs/zfs:2.4.1-v1.12.6@sha256:059d39f1d2d6dde263dbd8062207d0aa68805bb0748c087494791c7f985b87d1 + - imageRef: ghcr.io/siderolabs/amd-ucode:20251125@sha256:aa2c684933d28cf10ef785f0d94f91d6d098e164374114648867cf81c2b585fe + - imageRef: ghcr.io/siderolabs/amdgpu:20251125-v1.12.1@sha256:b73aba10ac51cd0d74a6c45210ccee3f6b7d2d97f9b3151d0563b11aa0727599 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20251125@sha256:fe33c69c471a8d097c58ab9e5e1e099c3c6e5bb785e74f6f135fdbd71c3b0feb + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20251125@sha256:01458f60448e166eeb641ee989b941725cbe6759e10afe2251c6d1b1ca5ba1b7 + - imageRef: ghcr.io/siderolabs/i915:20251125-v1.12.1@sha256:fb89c85a04ecb85abaec9d400e03a1628bf68aef3580e98f340cbe8920a6e4ed + - imageRef: ghcr.io/siderolabs/intel-ucode:20251111@sha256:51b7d1c31cb82f340a96228f1870b1e829e8ed2dfeef6d39926975303736d26a + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20251125@sha256:485ef0a0b58328ded511e9a76014c353da24bb147c8b2929068827e5f9a22326 + - imageRef: ghcr.io/siderolabs/drbd:9.2.16-v1.12.1@sha256:2c0dc35d5f3e1ac23de6eeee5554d9da010ac848a733a538c9568a9ccc782d86 + - imageRef: ghcr.io/siderolabs/zfs:2.4.0-v1.12.1@sha256:926f4cdaaa2cfad09f080eda5cfd08b8ba0bad083df3ca59e9764f4104539246 output: kind: image imageOptions: { diskSize: 1306525696, diskFormat: raw } diff --git a/packages/core/testing/Makefile b/packages/core/testing/Makefile index ce21a8e1..baccbfce 100644 --- a/packages/core/testing/Makefile +++ b/packages/core/testing/Makefile @@ -25,17 +25,24 @@ image-e2e-sandbox: yq -i '.e2e.image = strenv(IMAGE)' values.yaml rm -f images/e2e-sandbox.json -test: test-openapi test-apps ## Run the end-to-end tests in existing sandbox +test: test-cluster test-openapi test-apps ## Run the end-to-end tests in existing sandbox copy-nocloud-image: docker cp ../../../_out/assets/nocloud-amd64.raw.xz "${SANDBOX_NAME}":/workspace/_out/assets/nocloud-amd64.raw.xz +copy-installer-manifest: + docker cp ../../../_out/assets/cozystack-crds.yaml "${SANDBOX_NAME}":/workspace/_out/assets/cozystack-crds.yaml + docker cp ../../../_out/assets/cozystack-operator.yaml "${SANDBOX_NAME}":/workspace/_out/assets/cozystack-operator.yaml + prepare-cluster: copy-nocloud-image docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && hack/cozytest.sh hack/e2e-prepare-cluster.bats' -install-cozystack: +install-cozystack: copy-installer-manifest docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && hack/cozytest.sh hack/e2e-install-cozystack.bats' +test-cluster: copy-nocloud-image copy-installer-manifest ## Run the end-to-end for creating a cluster + docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && hack/cozytest.sh hack/e2e-cluster.bats' + test-openapi: docker exec "${SANDBOX_NAME}" sh -c 'cd /workspace && hack/cozytest.sh hack/e2e-test-openapi.bats' diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index 9d4bdd10..1e77f663 100644 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.3.0@sha256:0367a03b981df2a3ea13f411d4cb7869c2bf2c89c07d3d5c8971b9a28921ccef + image: ghcr.io/cozystack/cozystack/e2e-sandbox:v1.0.0-beta.2@sha256:eac71ef0de3450fce96255629e77903630c63ade62b81e7055f1a689f92ee153 diff --git a/packages/extra/bootbox/images/matchbox.tag b/packages/extra/bootbox/images/matchbox.tag index f51c7675..05ee31c2 100644 --- a/packages/extra/bootbox/images/matchbox.tag +++ b/packages/extra/bootbox/images/matchbox.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/matchbox:v1.3.0@sha256:85b8e04bf6f0690612dd63e80475df269f4a436d16680f8a40f2860cf16e2f74 +ghcr.io/cozystack/cozystack/matchbox:v1.0.0-beta.2@sha256:3d8c93822ca7b344b718a9ab0fb196d8fab92fcf852907975b39528d129811f0 diff --git a/packages/extra/bootbox/templates/matchbox/ingress.yaml b/packages/extra/bootbox/templates/matchbox/ingress.yaml index 5eef3489..fa62165b 100644 --- a/packages/extra/bootbox/templates/matchbox/ingress.yaml +++ b/packages/extra/bootbox/templates/matchbox/ingress.yaml @@ -1,5 +1,4 @@ -{{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} {{- $ingress := .Values._namespace.ingress }} {{- $host := .Values._namespace.host }} apiVersion: networking.k8s.io/v1 @@ -9,10 +8,10 @@ metadata: labels: app: bootbox annotations: - {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + {{- if ne $issuerType "cloudflare" }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} - cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + cert-manager.io/cluster-issuer: letsencrypt-prod {{- if .Values.whitelistHTTP }} nginx.ingress.kubernetes.io/whitelist-source-range: "{{ join "," (.Values.whitelist | default "0.0.0.0/32") }}" {{- end }} diff --git a/packages/extra/bootbox/values.schema.json b/packages/extra/bootbox/values.schema.json index 8e243c12..994f47cd 100644 --- a/packages/extra/bootbox/values.schema.json +++ b/packages/extra/bootbox/values.schema.json @@ -2,19 +2,6 @@ "title": "Chart Values", "type": "object", "properties": { - "whitelistHTTP": { - "description": "Secure HTTP by enabling client networks whitelisting.", - "type": "boolean", - "default": true - }, - "whitelist": { - "description": "List of client networks.", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, "machines": { "description": "Configuration of physical machine instances.", "type": "array", @@ -91,6 +78,19 @@ } } } + }, + "whitelist": { + "description": "List of client networks.", + "type": "array", + "default": [], + "items": { + "type": "string" + } + }, + "whitelistHTTP": { + "description": "Secure HTTP by enabling client networks whitelisting.", + "type": "boolean", + "default": true } } -} +} \ No newline at end of file diff --git a/packages/extra/etcd/Makefile b/packages/extra/etcd/Makefile index 2b3ed61e..f37d6e1e 100644 --- a/packages/extra/etcd/Makefile +++ b/packages/extra/etcd/Makefile @@ -5,6 +5,3 @@ include ../../../hack/package.mk generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh - -test: - helm unittest . diff --git a/packages/extra/etcd/templates/etcd-cluster.yaml b/packages/extra/etcd/templates/etcd-cluster.yaml index a604b448..44851cc6 100644 --- a/packages/extra/etcd/templates/etcd-cluster.yaml +++ b/packages/extra/etcd/templates/etcd-cluster.yaml @@ -104,7 +104,6 @@ spec: - {{ .Release.Name }} secretName: etcd-peer-ca-tls privateKey: - rotationPolicy: Never algorithm: RSA size: 4096 issuerRef: @@ -131,7 +130,6 @@ spec: - {{ .Release.Name }} secretName: etcd-ca-tls privateKey: - rotationPolicy: Never algorithm: RSA size: 4096 issuerRef: diff --git a/packages/extra/etcd/templates/etcd-defrag.yaml b/packages/extra/etcd/templates/etcd-defrag.yaml index 0478129f..089df920 100644 --- a/packages/extra/etcd/templates/etcd-defrag.yaml +++ b/packages/extra/etcd/templates/etcd-defrag.yaml @@ -4,14 +4,9 @@ metadata: name: {{ .Release.Name }}-defrag spec: schedule: "0 * * * *" - concurrencyPolicy: Forbid - startingDeadlineSeconds: 300 successfulJobsHistoryLimit: 3 - failedJobsHistoryLimit: 1 jobTemplate: spec: - activeDeadlineSeconds: 1800 - backoffLimit: 2 template: spec: containers: diff --git a/packages/extra/etcd/templates/hook/job.yaml b/packages/extra/etcd/templates/hook/job.yaml new file mode 100644 index 00000000..3bf2f84b --- /dev/null +++ b/packages/extra/etcd/templates/hook/job.yaml @@ -0,0 +1,39 @@ +{{- $shouldUpdateCerts := true }} +{{- $configMap := lookup "v1" "ConfigMap" .Release.Namespace "etcd-deployed-version" }} +{{- if $configMap }} + {{- $deployedVersion := index $configMap "data" "version" }} + {{- if $deployedVersion | semverCompare ">= 2.6.1" }} + {{- $shouldUpdateCerts = false }} + {{- end }} +{{- end }} + +{{- if $shouldUpdateCerts }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: etcd-hook + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +spec: + template: + metadata: + labels: + policy.cozystack.io/allow-to-apiserver: "true" + spec: + serviceAccountName: etcd-hook + containers: + - name: kubectl + image: docker.io/alpine/k8s:1.33.4 + command: + - sh + args: + - -exc + - |- + kubectl --namespace={{ .Release.Namespace }} delete secrets etcd-ca-tls etcd-peer-ca-tls + sleep 10 + kubectl --namespace={{ .Release.Namespace }} delete secrets etcd-client-tls etcd-peer-tls etcd-server-tls + kubectl --namespace={{ .Release.Namespace }} delete pods --selector=app.kubernetes.io/instance=etcd,app.kubernetes.io/managed-by=etcd-operator,app.kubernetes.io/name=etcd,cozystack.io/service=etcd + restartPolicy: Never +{{- end }} diff --git a/packages/extra/etcd/templates/hook/role.yaml b/packages/extra/etcd/templates/hook/role.yaml new file mode 100644 index 00000000..327eeadb --- /dev/null +++ b/packages/extra/etcd/templates/hook/role.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + name: etcd-hook +rules: +- apiGroups: + - "" + resources: + - secrets + - pods + verbs: + - get + - list + - watch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch diff --git a/packages/extra/etcd/templates/hook/rolebinding.yaml b/packages/extra/etcd/templates/hook/rolebinding.yaml new file mode 100644 index 00000000..0ee0ffd1 --- /dev/null +++ b/packages/extra/etcd/templates/hook/rolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: etcd-hook + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: etcd-hook +subjects: + - kind: ServiceAccount + name: etcd-hook + namespace: {{ .Release.Namespace | quote }} diff --git a/packages/extra/etcd/templates/hook/serviceaccount.yaml b/packages/extra/etcd/templates/hook/serviceaccount.yaml new file mode 100644 index 00000000..552fb5fc --- /dev/null +++ b/packages/extra/etcd/templates/hook/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: etcd-hook + annotations: + helm.sh/hook: post-upgrade + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded diff --git a/packages/extra/etcd/templates/version.yaml b/packages/extra/etcd/templates/version.yaml new file mode 100644 index 00000000..cc9375bb --- /dev/null +++ b/packages/extra/etcd/templates/version.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: etcd-deployed-version +data: + version: {{ .Chart.Version }} diff --git a/packages/extra/etcd/tests/no-post-upgrade-hook_test.yaml b/packages/extra/etcd/tests/no-post-upgrade-hook_test.yaml deleted file mode 100644 index 0e4f5aa3..00000000 --- a/packages/extra/etcd/tests/no-post-upgrade-hook_test.yaml +++ /dev/null @@ -1,34 +0,0 @@ -suite: etcd chart does not ship a destructive post-upgrade cert-regeneration hook - -release: - name: etcd - namespace: tenant-root - -templates: - - templates/check-release-name.yaml - - templates/dashboard-resourcemap.yaml - - templates/datastore.yaml - - templates/etcd-defrag.yaml - - templates/hook/job.yaml - - templates/podscrape.yaml - - templates/prometheus-rules.yaml - - templates/version.yaml - -tests: - - it: renders no Job named etcd-hook - documentSelector: - path: metadata.name - value: etcd-hook - skipEmptyTemplates: true - asserts: - - hasDocuments: - count: 0 - - - it: renders no ConfigMap named etcd-deployed-version - documentSelector: - path: metadata.name - value: etcd-deployed-version - skipEmptyTemplates: true - asserts: - - hasDocuments: - count: 0 diff --git a/packages/extra/etcd/values.schema.json b/packages/extra/etcd/values.schema.json index 3c66664c..0f696c57 100644 --- a/packages/extra/etcd/values.schema.json +++ b/packages/extra/etcd/values.schema.json @@ -2,25 +2,6 @@ "title": "Chart Values", "type": "object", "properties": { - "size": { - "description": "Persistent Volume size.", - "default": "4Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "" - }, "replicas": { "description": "Number of etcd replicas.", "type": "integer", @@ -60,6 +41,25 @@ "x-kubernetes-int-or-string": true } } + }, + "size": { + "description": "Persistent Volume size.", + "default": "4Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "storageClass": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "" } } -} +} \ No newline at end of file diff --git a/packages/extra/external-dns/Chart.yaml b/packages/extra/external-dns/Chart.yaml deleted file mode 100644 index d9788a41..00000000 --- a/packages/extra/external-dns/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: external-dns -description: External DNS for automatic DNS record management -icon: /logos/external-dns.svg -type: application -version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/extra/external-dns/Makefile b/packages/extra/external-dns/Makefile deleted file mode 100644 index 8b8fbc2f..00000000 --- a/packages/extra/external-dns/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -NAME=external-dns - -include ../../../hack/package.mk - -generate: - cozyvalues-gen -v values.yaml -s values.schema.json -r README.md - ../../../hack/update-crd.sh diff --git a/packages/extra/external-dns/README.md b/packages/extra/external-dns/README.md deleted file mode 100644 index 027182c1..00000000 --- a/packages/extra/external-dns/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# External DNS - -## Parameters - -### Common parameters - -| Name | Description | Type | Value | -| ------------------ | ---------------------------------------------------------------------------------- | ---------- | ------------- | -| `provider` | DNS provider name. | `string` | `{}` | -| `domainFilters` | List of domains this external-dns instance can manage. | `[]string` | `[]` | -| `policy` | How DNS records are synchronized. | `string` | `upsert-only` | -| `extraArgs` | Extra arguments for external-dns. | `[]string` | `[]` | -| `gatewayAPI` | Enable Gateway API HTTPRoute as a source for DNS records. | `bool` | `false` | -| `annotationPrefix` | Custom annotation prefix for external-dns (useful for running multiple instances). | `string` | `""` | - - -### Cloudflare - -| Name | Description | Type | Value | -| ------------ | -------------------------------- | -------- | ----------------------------------------------------------- | -| `cloudflare` | Cloudflare provider credentials. | `object` | `{"apiEmail":"","apiKey":"","apiToken":"","proxied":false}` | - - -### AWS - -| Name | Description | Type | Value | -| ----- | --------------------------------- | -------- | ------------------------------------------------------------------- | -| `aws` | AWS Route53 provider credentials. | `object` | `{"accessKeyId":"","region":"","secretAccessKey":"","zoneType":""}` | - - -### Azure - -| Name | Description | Type | Value | -| ------- | ------------------------------- | -------- | ---------------------------------------------------------------------------------------------- | -| `azure` | Azure DNS provider credentials. | `object` | `{"aadClientId":"","aadClientSecret":"","resourceGroup":"","subscriptionId":"","tenantId":""}` | - - -### Google - -| Name | Description | Type | Value | -| -------- | -------------------------------------- | -------- | --------------------------------------- | -| `google` | Google Cloud DNS provider credentials. | `object` | `{"project":"","serviceAccountKey":""}` | - - -### DigitalOcean - -| Name | Description | Type | Value | -| -------------- | -------------------------------------- | -------- | -------------- | -| `digitalocean` | DigitalOcean DNS provider credentials. | `object` | `{"token":""}` | - - -### Linode - -| Name | Description | Type | Value | -| -------- | -------------------------------- | -------- | -------------- | -| `linode` | Linode DNS provider credentials. | `object` | `{"token":""}` | - - -### OVH - -| Name | Description | Type | Value | -| ----- | ----------------------------- | -------- | ----------------------------------------------------------------------------- | -| `ovh` | OVH DNS provider credentials. | `object` | `{"applicationKey":"","applicationSecret":"","consumerKey":"","endpoint":""}` | - - -### Exoscale - -| Name | Description | Type | Value | -| ---------- | ---------------------------------- | -------- | ------------------------------ | -| `exoscale` | Exoscale DNS provider credentials. | `object` | `{"apiKey":"","apiSecret":""}` | - - -### GoDaddy - -| Name | Description | Type | Value | -| --------- | --------------------------------- | -------- | ------------------------------ | -| `godaddy` | GoDaddy DNS provider credentials. | `object` | `{"apiKey":"","apiSecret":""}` | - - -### Resources - -| Name | Description | Type | Value | -| ------------------ | -------------------------------------------------------------------------------------------------------- | ---------- | ------ | -| `resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `resources.cpu` | CPU available to each replica. | `quantity` | `""` | -| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` | -| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` | - diff --git a/packages/extra/external-dns/charts/cozy-lib b/packages/extra/external-dns/charts/cozy-lib deleted file mode 120000 index e1813509..00000000 --- a/packages/extra/external-dns/charts/cozy-lib +++ /dev/null @@ -1 +0,0 @@ -../../../library/cozy-lib \ No newline at end of file diff --git a/packages/extra/external-dns/config.json b/packages/extra/external-dns/config.json deleted file mode 100644 index b2f956f3..00000000 --- a/packages/extra/external-dns/config.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "comments": { - "format": "##" - }, - "tags": { - "param": "@param", - "section": "@section", - "descriptionStart": "@descriptionStart", - "descriptionEnd": "@descriptionEnd", - "skip": "@skip", - "extra": "@extra" - }, - "modifiers": { - "array": "array", - "object": "object", - "string": "string", - "nullable": "nullable", - "default": "default" - }, - "regexp": { - "paramsSectionTitle": "Parameters" - } -} diff --git a/packages/extra/external-dns/logos/external-dns.svg b/packages/extra/external-dns/logos/external-dns.svg deleted file mode 100644 index b22ad8c4..00000000 --- a/packages/extra/external-dns/logos/external-dns.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/packages/extra/external-dns/templates/dashboard-resourcemap.yaml b/packages/extra/external-dns/templates/dashboard-resourcemap.yaml deleted file mode 100644 index edd96b74..00000000 --- a/packages/extra/external-dns/templates/dashboard-resourcemap.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: {{ .Release.Name }}-dashboard-resources -rules: -- apiGroups: - - helm.toolkit.fluxcd.io - resources: - - helmreleases - resourceNames: - - {{ .Release.Name }} - verbs: ["get", "list", "watch"] ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ .Release.Name }}-dashboard-resources -subjects: -{{ include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "admin" .Release.Namespace) }} -roleRef: - kind: Role - name: {{ .Release.Name }}-dashboard-resources - apiGroup: rbac.authorization.k8s.io diff --git a/packages/extra/external-dns/templates/external-dns.yaml b/packages/extra/external-dns/templates/external-dns.yaml deleted file mode 100644 index cdfb8901..00000000 --- a/packages/extra/external-dns/templates/external-dns.yaml +++ /dev/null @@ -1,169 +0,0 @@ -{{- if not .Values.provider }} -{{- fail "provider is required: set it to one of cloudflare, aws, azure, google, digitalocean, linode, ovh, exoscale, godaddy, inmemory" }} -{{- end }} -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ .Release.Name }}-system - labels: - app.kubernetes.io/instance: {{ .Release.Name }}-system - app.kubernetes.io/managed-by: {{ .Release.Service }} -spec: - chartRef: - kind: ExternalArtifact - name: cozystack-external-dns-application-default-external-dns-system - namespace: cozy-system - interval: 5m - timeout: 10m - install: - remediation: - retries: -1 - upgrade: - force: true - remediation: - retries: -1 - values: - external-dns: - namespaced: true - txtOwnerId: {{ .Release.Namespace | quote }} - policy: {{ .Values.policy | quote }} - {{- if .Values.annotationPrefix }} - annotationPrefix: {{ .Values.annotationPrefix | quote }} - {{- end }} - provider: - name: {{ .Values.provider | quote }} - sources: - - ingress - - service - {{- if .Values.gatewayAPI }} - - gateway-httproute - {{- end }} - {{- with .Values.domainFilters }} - domainFilters: - {{- toYaml . | nindent 8 }} - {{- end }} - - {{- /* Provider-specific credentials and config */}} - - {{- if eq .Values.provider "cloudflare" }} - {{- if or .Values.cloudflare.apiToken (and .Values.cloudflare.apiKey .Values.cloudflare.apiEmail) }} - env: - {{- if .Values.cloudflare.apiToken }} - - name: CF_API_TOKEN - value: {{ .Values.cloudflare.apiToken | quote }} - {{- else }} - - name: CF_API_KEY - value: {{ .Values.cloudflare.apiKey | quote }} - - name: CF_API_EMAIL - value: {{ .Values.cloudflare.apiEmail | quote }} - {{- end }} - {{- end }} - {{- if .Values.cloudflare.proxied }} - cloudflare: - proxied: true - {{- end }} - {{- end }} - - {{- if eq .Values.provider "aws" }} - {{- if or .Values.aws.accessKeyId .Values.aws.secretAccessKey .Values.aws.region }} - env: - {{- if .Values.aws.accessKeyId }} - - name: AWS_ACCESS_KEY_ID - value: {{ .Values.aws.accessKeyId | quote }} - {{- end }} - {{- if .Values.aws.secretAccessKey }} - - name: AWS_SECRET_ACCESS_KEY - value: {{ .Values.aws.secretAccessKey | quote }} - {{- end }} - {{- if .Values.aws.region }} - - name: AWS_DEFAULT_REGION - value: {{ .Values.aws.region | quote }} - {{- end }} - {{- end }} - {{- if .Values.aws.zoneType }} - aws: - zoneType: {{ .Values.aws.zoneType | quote }} - {{- end }} - {{- end }} - - {{- if eq .Values.provider "azure" }} - {{- if or .Values.azure.tenantId .Values.azure.subscriptionId .Values.azure.resourceGroup .Values.azure.aadClientId .Values.azure.aadClientSecret }} - azure: - tenantId: {{ .Values.azure.tenantId | quote }} - subscriptionId: {{ .Values.azure.subscriptionId | quote }} - resourceGroup: {{ .Values.azure.resourceGroup | quote }} - aadClientId: {{ .Values.azure.aadClientId | quote }} - aadClientSecret: {{ .Values.azure.aadClientSecret | quote }} - {{- end }} - {{- end }} - - {{- if eq .Values.provider "digitalocean" }} - {{- if .Values.digitalocean.token }} - env: - - name: DO_TOKEN - value: {{ .Values.digitalocean.token | quote }} - {{- end }} - {{- end }} - - {{- if eq .Values.provider "google" }} - {{- if or .Values.google.project .Values.google.serviceAccountKey }} - google: - project: {{ .Values.google.project | quote }} - {{- if .Values.google.serviceAccountKey }} - serviceAccountKey: {{ .Values.google.serviceAccountKey | quote }} - {{- end }} - {{- end }} - {{- end }} - - {{- if eq .Values.provider "linode" }} - {{- if .Values.linode.token }} - env: - - name: LINODE_TOKEN - value: {{ .Values.linode.token | quote }} - {{- end }} - {{- end }} - - {{- if eq .Values.provider "ovh" }} - {{- if or .Values.ovh.endpoint .Values.ovh.applicationKey .Values.ovh.applicationSecret .Values.ovh.consumerKey }} - env: - - name: OVH_ENDPOINT - value: {{ .Values.ovh.endpoint | quote }} - - name: OVH_APPLICATION_KEY - value: {{ .Values.ovh.applicationKey | quote }} - - name: OVH_APPLICATION_SECRET - value: {{ .Values.ovh.applicationSecret | quote }} - - name: OVH_CONSUMER_KEY - value: {{ .Values.ovh.consumerKey | quote }} - {{- end }} - {{- end }} - - {{- if eq .Values.provider "exoscale" }} - {{- if or .Values.exoscale.apiKey .Values.exoscale.apiSecret }} - env: - - name: EXOSCALE_API_KEY - value: {{ .Values.exoscale.apiKey | quote }} - - name: EXOSCALE_API_SECRET - value: {{ .Values.exoscale.apiSecret | quote }} - {{- end }} - {{- end }} - - {{- /* extraArgs: merge user-supplied args with provider-specific args (godaddy) */}} - {{- $godaddyArgs := list }} - {{- if eq .Values.provider "godaddy" }} - {{- if .Values.godaddy.apiKey }} - {{- $godaddyArgs = append $godaddyArgs (printf "--godaddy-api-key=%s" .Values.godaddy.apiKey) }} - {{- end }} - {{- if .Values.godaddy.apiSecret }} - {{- $godaddyArgs = append $godaddyArgs (printf "--godaddy-api-secret=%s" .Values.godaddy.apiSecret) }} - {{- end }} - {{- end }} - {{- $allArgs := concat (.Values.extraArgs | default list) $godaddyArgs }} - {{- with $allArgs }} - extraArgs: - {{- toYaml . | nindent 8 }} - {{- end }} - - {{- with (include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $)) }} - resources: - {{- . | nindent 8 }} - {{- end }} diff --git a/packages/extra/external-dns/values.schema.json b/packages/extra/external-dns/values.schema.json deleted file mode 100644 index 08de0f8e..00000000 --- a/packages/extra/external-dns/values.schema.json +++ /dev/null @@ -1,193 +0,0 @@ -{ - "title": "Chart Values", - "type": "object", - "properties": { - "provider": { - "description": "DNS provider name.", - "type": "string", - "enum": [ - "cloudflare", - "aws", - "azure", - "google", - "digitalocean", - "linode", - "ovh", - "exoscale", - "godaddy", - "inmemory" - ] - }, - "domainFilters": { - "description": "List of domains this external-dns instance can manage.", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, - "policy": { - "description": "How DNS records are synchronized.", - "type": "string", - "default": "upsert-only", - "enum": [ - "create-only", - "sync", - "upsert-only" - ] - }, - "extraArgs": { - "description": "Extra arguments for external-dns.", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, - "gatewayAPI": { - "description": "Enable Gateway API HTTPRoute as a source for DNS records.", - "type": "boolean", - "default": false - }, - "annotationPrefix": { - "description": "Custom annotation prefix for external-dns (useful for running multiple instances).", - "type": "string", - "default": "" - }, - "cloudflare": { - "description": "Cloudflare provider credentials.", - "type": "object", - "default": { - "apiEmail": "", - "apiKey": "", - "apiToken": "", - "proxied": false - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "aws": { - "description": "AWS Route53 provider credentials.", - "type": "object", - "default": { - "accessKeyId": "", - "region": "", - "secretAccessKey": "", - "zoneType": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "azure": { - "description": "Azure DNS provider credentials.", - "type": "object", - "default": { - "aadClientId": "", - "aadClientSecret": "", - "resourceGroup": "", - "subscriptionId": "", - "tenantId": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "google": { - "description": "Google Cloud DNS provider credentials.", - "type": "object", - "default": { - "project": "", - "serviceAccountKey": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "digitalocean": { - "description": "DigitalOcean DNS provider credentials.", - "type": "object", - "default": { - "token": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "linode": { - "description": "Linode DNS provider credentials.", - "type": "object", - "default": { - "token": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "ovh": { - "description": "OVH DNS provider credentials.", - "type": "object", - "default": { - "applicationKey": "", - "applicationSecret": "", - "consumerKey": "", - "endpoint": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "exoscale": { - "description": "Exoscale DNS provider credentials.", - "type": "object", - "default": { - "apiKey": "", - "apiSecret": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "godaddy": { - "description": "GoDaddy DNS provider credentials.", - "type": "object", - "default": { - "apiKey": "", - "apiSecret": "" - }, - "x-kubernetes-preserve-unknown-fields": true - }, - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory (RAM) available to each replica.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "nano", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - } - } -} diff --git a/packages/extra/external-dns/values.yaml b/packages/extra/external-dns/values.yaml deleted file mode 100644 index c40d2dff..00000000 --- a/packages/extra/external-dns/values.yaml +++ /dev/null @@ -1,149 +0,0 @@ -## -## @section Common parameters -## - -## @enum {string} Provider - DNS provider. -## @value cloudflare -## @value aws -## @value azure -## @value google -## @value digitalocean -## @value linode -## @value ovh -## @value exoscale -## @value godaddy -## @value inmemory - -## @param {Provider} provider - DNS provider name. -# provider: - -## @param {[]string} domainFilters - List of domains this external-dns instance can manage. -domainFilters: [] - -## @enum {string} Policy - How DNS records are synchronized. -## @value create-only -## @value sync -## @value upsert-only - -## @param {Policy} policy="upsert-only" - How DNS records are synchronized. -policy: "upsert-only" - -## @param {[]string} extraArgs - Extra arguments for external-dns. -extraArgs: [] - -## @param {bool} gatewayAPI=false - Enable Gateway API HTTPRoute as a source for DNS records. -gatewayAPI: false - -## @param {string} [annotationPrefix] - Custom annotation prefix for external-dns (useful for running multiple instances). -annotationPrefix: "" - -## -## @section Cloudflare -## - -## @param {object} cloudflare - Cloudflare provider credentials. -cloudflare: - apiToken: "" - apiKey: "" - apiEmail: "" - proxied: false - -## -## @section AWS -## - -## @param {object} aws - AWS Route53 provider credentials. -aws: - accessKeyId: "" - secretAccessKey: "" - region: "" - zoneType: "" - -## -## @section Azure -## - -## @param {object} azure - Azure DNS provider credentials. -azure: - tenantId: "" - subscriptionId: "" - resourceGroup: "" - aadClientId: "" - aadClientSecret: "" - -## -## @section Google -## - -## @param {object} google - Google Cloud DNS provider credentials. -google: - project: "" - serviceAccountKey: "" - -## -## @section DigitalOcean -## - -## @param {object} digitalocean - DigitalOcean DNS provider credentials. -digitalocean: - token: "" - -## -## @section Linode -## - -## @param {object} linode - Linode DNS provider credentials. -linode: - token: "" - -## -## @section OVH -## - -## @param {object} ovh - OVH DNS provider credentials. -ovh: - endpoint: "" - applicationKey: "" - applicationSecret: "" - consumerKey: "" - -## -## @section Exoscale -## - -## @param {object} exoscale - Exoscale DNS provider credentials. -exoscale: - apiKey: "" - apiSecret: "" - -## -## @section GoDaddy -## - -## @param {object} godaddy - GoDaddy DNS provider credentials. -godaddy: - apiKey: "" - apiSecret: "" - -## -## @section Resources -## - -## @typedef {struct} Resources - Explicit CPU and memory configuration. -## @field {quantity} [cpu] - CPU available to each replica. -## @field {quantity} [memory] - Memory (RAM) available to each replica. - -## @enum {string} ResourcesPreset - Default sizing preset. -## @value nano -## @value micro -## @value small -## @value medium -## @value large -## @value xlarge -## @value 2xlarge - -## @param {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. -resources: {} - -## @param {ResourcesPreset} resourcesPreset="nano" - Default sizing preset used when `resources` is omitted. -resourcesPreset: "nano" diff --git a/packages/extra/ingress/Makefile b/packages/extra/ingress/Makefile index 65b53c03..958ce484 100644 --- a/packages/extra/ingress/Makefile +++ b/packages/extra/ingress/Makefile @@ -10,6 +10,3 @@ get-cloudflare-ips: generate: cozyvalues-gen -v values.yaml -s values.schema.json -r README.md ../../../hack/update-crd.sh - -test: - helm unittest . diff --git a/packages/extra/ingress/README.md b/packages/extra/ingress/README.md index c541d8e9..0e786dfb 100644 --- a/packages/extra/ingress/README.md +++ b/packages/extra/ingress/README.md @@ -14,17 +14,3 @@ | `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` | | `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `micro` | - -## Exposure mode - -The ingress Service type is driven by the cluster-wide `publishing.exposure` value in the platform chart, not by any key in this package. Two modes exist: - -- `externalIPs` (default) has three rendered shapes: - - Release namespace matches `publishing.ingressName` AND `publishing.externalIPs` is non-empty → Service is `ClusterIP` with `Service.spec.externalIPs` set from that list and `externalTrafficPolicy: Cluster`. - - Release namespace matches `publishing.ingressName` but `publishing.externalIPs` is empty → Service falls back to `type: LoadBalancer` with `externalTrafficPolicy: Local`. - - Release namespace does not match `publishing.ingressName` (non-root tenants) → Service is `type: LoadBalancer` with `externalTrafficPolicy: Local`. - `Service.spec.externalIPs` is deprecated upstream in Kubernetes v1.36 (KEP-5707); plan migration before v1.40. -- `loadBalancer` — Service is `type: LoadBalancer` with `externalTrafficPolicy: Local`, and a `CiliumLoadBalancerIPPool` makes the addresses in `publishing.externalIPs` allocatable via Cilium LB IPAM. Requires `publishing.externalIPs` to contain at least one non-empty address (render fails otherwise) and assumes the addresses are already routed to a cluster node (floating IP / upstream router). See the inline comment on `publishing.exposure` in the platform chart for full caveats, including the note that switching the value on a running cluster causes the ingress Service to be recreated. - -This setting only migrates ingress-nginx away from `Service.spec.externalIPs`. Other cozystack components that use the same deprecated field (e.g. the `vpn` app) must be migrated separately before Kubernetes v1.40 flips the `AllowServiceExternalIPs` feature gate off. - diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index 8e1f00fb..ca50d276 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -1,19 +1,5 @@ {{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} {{- $exposeExternalIPs := (index .Values._cluster "expose-external-ips") | default "" | nospace }} -{{- $exposeMode := (index .Values._cluster "expose-mode") | default "externalIPs" }} -{{- $exposeIPsList := list }} -{{- range splitList "," $exposeExternalIPs }} - {{- $ip := . | trim }} - {{- if $ip }} - {{- $exposeIPsList = append $exposeIPsList $ip }} - {{- end }} -{{- end }} -{{- if not (has $exposeMode (list "externalIPs" "loadBalancer")) }} -{{- fail (printf "unknown publishing.exposure mode %q: must be \"externalIPs\" or \"loadBalancer\"" $exposeMode) }} -{{- end }} -{{- if and (eq $exposeMode "loadBalancer") (eq $exposeIngress .Release.Namespace) (not $exposeIPsList) }} -{{- fail "publishing.exposure=loadBalancer requires publishing.externalIPs to contain at least one non-empty address: the CiliumLoadBalancerIPPool has nothing to advertise and the Service would stay in ." }} -{{- end }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -55,12 +41,9 @@ spec: enabled: false {{- end }} service: - {{- if and (eq $exposeIngress .Release.Namespace) (eq $exposeMode "loadBalancer") }} - type: LoadBalancer - externalTrafficPolicy: Local - {{- else if and (eq $exposeIngress .Release.Namespace) $exposeIPsList }} + {{- if and (eq $exposeIngress .Release.Namespace) $exposeExternalIPs }} externalIPs: - {{- toYaml $exposeIPsList | nindent 12 }} + {{- toYaml (splitList "," $exposeExternalIPs) | nindent 12 }} type: ClusterIP externalTrafficPolicy: Cluster {{- else }} diff --git a/packages/extra/ingress/tests/exposure_test.yaml b/packages/extra/ingress/tests/exposure_test.yaml deleted file mode 100644 index 1c76b3da..00000000 --- a/packages/extra/ingress/tests/exposure_test.yaml +++ /dev/null @@ -1,165 +0,0 @@ -suite: ingress exposure modes -templates: - - templates/nginx-ingress.yaml - -release: - name: ingress - namespace: tenant-root - -tests: - - it: default exposure (externalIPs) renders ClusterIP Service with spec.externalIPs - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: ClusterIP - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Cluster - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalIPs - value: - - 192.0.2.10 - - 192.0.2.11 - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.labels - - - it: legacy config without expose-mode falls back to externalIPs behavior - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: ClusterIP - - - it: externalIPs mode in a namespace other than publishing.ingressName renders LoadBalancer fallback without externalIPs - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - release: - namespace: tenant-other - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: LoadBalancer - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Local - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.externalIPs - - - it: loadBalancer mode renders LoadBalancer Service without externalIPs on the Service - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10,192.0.2.11" - expose-mode: loadBalancer - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: LoadBalancer - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Local - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.labels - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.externalIPs - - - it: loadBalancer mode without externalIPs fails chart render with explicit message - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "" - expose-mode: loadBalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "publishing.exposure=loadBalancer requires publishing.externalIPs to contain at least one non-empty address: the CiliumLoadBalancerIPPool has nothing to advertise and the Service would stay in ." - - - it: unknown exposure mode is rejected with a clear error (case-sensitive enum) - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: LoadBalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "unknown publishing.exposure mode \"LoadBalancer\": must be \"externalIPs\" or \"loadBalancer\"" - - - it: another typo in exposure mode also fails - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadbalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "unknown publishing.exposure mode \"loadbalancer\": must be \"externalIPs\" or \"loadBalancer\"" - - - it: loadBalancer mode in a namespace other than publishing.ingressName falls back to LoadBalancer Service without pool - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10" - expose-mode: loadBalancer - release: - namespace: tenant-other - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.type - value: LoadBalancer - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalTrafficPolicy - value: Local - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.labels - - template: templates/nginx-ingress.yaml - notExists: - path: spec.values.ingress-nginx.controller.service.externalIPs - - - it: loadBalancer mode with only-empty externalIPs fails chart render (comma-only input) - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: ",," - expose-mode: loadBalancer - asserts: - - template: templates/nginx-ingress.yaml - failedTemplate: - errorMessage: "publishing.exposure=loadBalancer requires publishing.externalIPs to contain at least one non-empty address: the CiliumLoadBalancerIPPool has nothing to advertise and the Service would stay in ." - - - it: externalIPs mode also filters out empty entries (trailing comma) - set: - _cluster: - expose-ingress: tenant-root - expose-external-ips: "192.0.2.10," - asserts: - - template: templates/nginx-ingress.yaml - equal: - path: spec.values.ingress-nginx.controller.service.externalIPs - value: - - 192.0.2.10 diff --git a/packages/extra/ingress/values.schema.json b/packages/extra/ingress/values.schema.json index 7a53a197..650a5824 100644 --- a/packages/extra/ingress/values.schema.json +++ b/packages/extra/ingress/values.schema.json @@ -2,24 +2,16 @@ "title": "Chart Values", "type": "object", "properties": { - "replicas": { - "description": "Number of ingress-nginx replicas.", - "type": "integer", - "default": 2 - }, - "whitelist": { - "description": "List of client networks.", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, "cloudflareProxy": { "description": "Restoring original visitor IPs when Cloudflare proxied is enabled.", "type": "boolean", "default": false }, + "replicas": { + "description": "Number of ingress-nginx replicas.", + "type": "integer", + "default": 2 + }, "resources": { "description": "Explicit CPU and memory configuration for each ingress-nginx replica. When omitted, the preset defined in `resourcesPreset` is applied.", "type": "object", @@ -66,6 +58,14 @@ "xlarge", "2xlarge" ] + }, + "whitelist": { + "description": "List of client networks.", + "type": "array", + "default": [], + "items": { + "type": "string" + } } } -} +} \ No newline at end of file diff --git a/packages/apps/qdrant/.helmignore b/packages/extra/monitoring/.helmignore similarity index 82% rename from packages/apps/qdrant/.helmignore rename to packages/extra/monitoring/.helmignore index 3de7d4a5..1ea0ae84 100644 --- a/packages/apps/qdrant/.helmignore +++ b/packages/extra/monitoring/.helmignore @@ -1,4 +1,3 @@ .helmignore /logos /Makefile -/hack diff --git a/packages/system/monitoring/dashboards-infra.list b/packages/extra/monitoring/dashboards.list similarity index 76% rename from packages/system/monitoring/dashboards-infra.list rename to packages/extra/monitoring/dashboards.list index 4c7e494d..1f4b2eea 100644 --- a/packages/system/monitoring/dashboards-infra.list +++ b/packages/extra/monitoring/dashboards.list @@ -1,3 +1,23 @@ +dotdc/k8s-views-global +dotdc/k8s-views-namespaces +dotdc/k8s-system-coredns +dotdc/k8s-views-pods +cache/nginx-vts-stats +victoria-metrics/vmalert +victoria-metrics/vmagent +victoria-metrics/victoriametrics-cluster +victoria-metrics/backupmanager +victoria-metrics/victoriametrics +victoria-metrics/operator +ingress/controller-detail +ingress/controllers +ingress/namespaces +ingress/vhosts +ingress/vhost-detail +ingress/namespace-detail +db/cloudnativepg +db/maria-db +db/redis main/controller main/namespaces main/capacity-planning @@ -11,29 +31,15 @@ control-plane/control-plane-status control-plane/deprecated-resources control-plane/dns-coredns control-plane/kube-etcd -victoria-metrics/vmalert -victoria-metrics/vmagent -victoria-metrics/victoriametrics-cluster -victoria-metrics/backupmanager -victoria-metrics/victoriametrics -victoria-metrics/operator -dotdc/k8s-views-global -dotdc/k8s-views-namespaces -dotdc/k8s-system-coredns -dotdc/k8s-views-pods +kubevirt/kubevirt-control-plane flux/flux-control-plane flux/flux-stats -kubevirt/kubevirt-control-plane +kafka/strimzi-kafka goldpinger/goldpinger -cache/nginx-vts-stats +clickhouse/altinity-clickhouse-operator-dashboard storage/linstor seaweedfs/seaweedfs hubble/overview hubble/dns-namespace hubble/l7-http-metrics hubble/network-overview -gpu/gpu-performance -gpu/gpu-efficiency -gpu/gpu-quotas -gpu/gpu-fleet -gpu/gpu-tenants diff --git a/packages/extra/monitoring/images/grafana.tag b/packages/extra/monitoring/images/grafana.tag new file mode 100644 index 00000000..06fa403d --- /dev/null +++ b/packages/extra/monitoring/images/grafana.tag @@ -0,0 +1 @@ +ghcr.io/cozystack/cozystack/grafana:0.0.0@sha256:8ce0cd90c8f614cdabf5a41f8aa50b7dfbd02b31b9a0bd7897927e7f89968e07 diff --git a/packages/system/monitoring/images/grafana/Dockerfile b/packages/extra/monitoring/images/grafana/Dockerfile similarity index 84% rename from packages/system/monitoring/images/grafana/Dockerfile rename to packages/extra/monitoring/images/grafana/Dockerfile index cc65c9d3..f8597a5c 100644 --- a/packages/system/monitoring/images/grafana/Dockerfile +++ b/packages/extra/monitoring/images/grafana/Dockerfile @@ -13,4 +13,3 @@ RUN curl -L https://github.com/VictoriaMetrics/victorialogs-datasource/releases/ RUN grafana-cli --pluginsDir /var/lib/grafana-plugins plugins install natel-discrete-panel RUN grafana-cli --pluginsDir /var/lib/grafana-plugins plugins install grafana-worldmap-panel -RUN grafana-cli --pluginsDir /var/lib/grafana-plugins plugins install marcusolsson-dynamictext-panel diff --git a/packages/system/monitoring/patches/1.diff b/packages/extra/monitoring/patches/1.diff similarity index 100% rename from packages/system/monitoring/patches/1.diff rename to packages/extra/monitoring/patches/1.diff diff --git a/packages/system/monitoring/templates/alerta/alerta-db.yaml b/packages/extra/monitoring/templates/alerta/alerta-db.yaml similarity index 65% rename from packages/system/monitoring/templates/alerta/alerta-db.yaml rename to packages/extra/monitoring/templates/alerta/alerta-db.yaml index af9dc72c..845cd8ba 100644 --- a/packages/system/monitoring/templates/alerta/alerta-db.yaml +++ b/packages/extra/monitoring/templates/alerta/alerta-db.yaml @@ -5,9 +5,6 @@ metadata: name: alerta-db spec: instances: 2 - {{- $existingCluster := lookup "postgresql.cnpg.io/v1" "Cluster" .Release.Namespace "alerta-db" }} - {{- $image := dig "spec" "imageName" "ghcr.io/cloudnative-pg/postgresql:17.7-standard-trixie" $existingCluster }} - imageName: {{ if regexMatch ":17\\." $image }}ghcr.io/cloudnative-pg/postgresql:17.7-standard-trixie{{ else if regexMatch ":[0-9]+\\.[0-9]+$" $image }}{{ printf "%s-standard-trixie" $image }}{{ else }}{{ $image }}{{ end }} {{- if .Values._cluster.scheduling }} {{- $rawConstraints := get .Values._cluster.scheduling "globalAppTopologySpreadConstraints" }} {{- if $rawConstraints }} @@ -36,3 +33,17 @@ spec: inheritedMetadata: labels: policy.cozystack.io/allow-to-apiserver: "true" +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: alerta-db +spec: + replicas: 2 + minReplicas: 1 + kind: monitoring + type: postgres + selector: + cnpg.io/cluster: alerta-db + cnpg.io/podRole: instance + version: {{ $.Chart.Version }} diff --git a/packages/system/monitoring/templates/alerta/alerta.yaml b/packages/extra/monitoring/templates/alerta/alerta.yaml similarity index 89% rename from packages/system/monitoring/templates/alerta/alerta.yaml rename to packages/extra/monitoring/templates/alerta/alerta.yaml index d30e698d..76b7a02b 100644 --- a/packages/system/monitoring/templates/alerta/alerta.yaml +++ b/packages/extra/monitoring/templates/alerta/alerta.yaml @@ -1,5 +1,4 @@ -{{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} {{- $ingress := .Values._namespace.ingress }} {{- $host := .Values._namespace.host }} @@ -140,14 +139,6 @@ spec: - name: SLACK_SEVERITY_FILTER value: {{ .Values.alerta.alerts.slack.disabledSeverity | toJson | quote }} {{- end }} - {{- if .Values.alerta.alerts.slack.dashboardUrl }} - - name: DASHBOARD_URL - value: {{ .Values.alerta.alerts.slack.dashboardUrl | quote }} - {{- end }} - {{- if .Values.alerta.alerts.slack.summaryFmt }} - - name: SLACK_SUMMARY_FMT - value: {{ .Values.alerta.alerts.slack.summaryFmt | quote }} - {{- end }} {{- end }} ports: @@ -180,10 +171,10 @@ metadata: labels: app: alerta annotations: - {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + {{- if ne $issuerType "cloudflare" }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} - cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + cert-manager.io/cluster-issuer: letsencrypt-prod spec: ingressClassName: {{ $ingress }} tls: @@ -202,6 +193,20 @@ spec: port: name: http --- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: alerta +spec: + replicas: 1 + minReplicas: 1 + kind: monitoring + type: alerta + selector: + app: alerta + release: alerta + version: {{ $.Chart.Version }} +--- apiVersion: v1 kind: Secret metadata: @@ -254,3 +259,17 @@ spec: podMetadata: labels: policy.cozystack.io/allow-to-apiserver: "true" +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: alertmanager +spec: + replicas: 3 + minReplicas: 2 + kind: monitoring + type: alertmanager + selector: + app.kubernetes.io/instance: alertmanager + app.kubernetes.io/name: vmalertmanager + version: {{ $.Chart.Version }} diff --git a/packages/extra/monitoring/templates/dashboard-resourcemap.yaml b/packages/extra/monitoring/templates/dashboard-resourcemap.yaml index 5a5a3def..894a11d4 100644 --- a/packages/extra/monitoring/templates/dashboard-resourcemap.yaml +++ b/packages/extra/monitoring/templates/dashboard-resourcemap.yaml @@ -42,9 +42,7 @@ rules: - {{ .name }}-vminsert {{- end }} {{- range .Values.logsStorages }} - - {{ .name }}-vlstorage - - {{ .name }}-vlselect - - {{ .name }}-vlinsert + - {{ $.Release.Name }}-vlogs-{{ .name }} {{- end }} {{- range .Values.metricsStorages }} - vmalert-{{ .name }} diff --git a/packages/extra/monitoring/templates/dashboards.yaml b/packages/extra/monitoring/templates/dashboards.yaml new file mode 100644 index 00000000..3872f9b7 --- /dev/null +++ b/packages/extra/monitoring/templates/dashboards.yaml @@ -0,0 +1,16 @@ +{{- range (split "\n" (.Files.Get "dashboards.list")) }} +{{- $parts := split "/" . }} +{{- if eq (len $parts) 2 }} +--- +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaDashboard +metadata: + name: {{ $parts._0 }}-{{ $parts._1 }} +spec: + folder: {{ $parts._0 }} + instanceSelector: + matchLabels: + dashboards: grafana + url: http://grafana-dashboards.cozy-grafana-operator.svc/{{ . }}.json +{{- end }} +{{- end }} diff --git a/packages/system/monitoring/templates/grafana/db.yaml b/packages/extra/monitoring/templates/grafana/db.yaml similarity index 61% rename from packages/system/monitoring/templates/grafana/db.yaml rename to packages/extra/monitoring/templates/grafana/db.yaml index afc2d0d7..662f5cf4 100644 --- a/packages/system/monitoring/templates/grafana/db.yaml +++ b/packages/extra/monitoring/templates/grafana/db.yaml @@ -4,9 +4,6 @@ metadata: name: grafana-db spec: instances: 2 - {{- $existingCluster := lookup "postgresql.cnpg.io/v1" "Cluster" .Release.Namespace "grafana-db" }} - {{- $image := dig "spec" "imageName" "ghcr.io/cloudnative-pg/postgresql:17.7-standard-trixie" $existingCluster }} - imageName: {{ if regexMatch ":17\\." $image }}ghcr.io/cloudnative-pg/postgresql:17.7-standard-trixie{{ else if regexMatch ":[0-9]+\\.[0-9]+$" $image }}{{ printf "%s-standard-trixie" $image }}{{ else }}{{ $image }}{{ end }} storage: size: {{ .Values.grafana.db.size }} {{- if .Values._cluster.scheduling }} @@ -30,3 +27,17 @@ spec: inheritedMetadata: labels: policy.cozystack.io/allow-to-apiserver: "true" +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: grafana-db +spec: + replicas: 2 + minReplicas: 1 + kind: monitoring + type: postgres + selector: + cnpg.io/cluster: grafana-db + cnpg.io/podRole: instance + version: {{ $.Chart.Version }} diff --git a/packages/system/monitoring/templates/grafana/grafana.yaml b/packages/extra/monitoring/templates/grafana/grafana.yaml similarity index 86% rename from packages/system/monitoring/templates/grafana/grafana.yaml rename to packages/extra/monitoring/templates/grafana/grafana.yaml index d65a7dc4..1eadda9e 100644 --- a/packages/system/monitoring/templates/grafana/grafana.yaml +++ b/packages/extra/monitoring/templates/grafana/grafana.yaml @@ -1,5 +1,4 @@ -{{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} {{- $ingress := .Values._namespace.ingress }} {{- $host := .Values._namespace.host }} --- @@ -73,10 +72,10 @@ spec: ingress: metadata: annotations: - {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: "{{ $ingress }}" + {{- if ne $issuerType "cloudflare" }} + acme.cert-manager.io/http01-ingress-class: "{{ $ingress }}" {{- end }} - cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + cert-manager.io/cluster-issuer: letsencrypt-prod spec: ingressClassName: "{{ $ingress }}" rules: @@ -94,3 +93,16 @@ spec: - hosts: - "{{ printf "grafana.%s" (.Values.host | default $host) }}" secretName: grafana-ingress-tls +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: grafana +spec: + replicas: 2 + minReplicas: 1 + kind: monitoring + type: grafana + selector: + app: grafana + version: {{ $.Chart.Version }} diff --git a/packages/system/monitoring/templates/grafana/secret.yaml b/packages/extra/monitoring/templates/grafana/secret.yaml similarity index 100% rename from packages/system/monitoring/templates/grafana/secret.yaml rename to packages/extra/monitoring/templates/grafana/secret.yaml diff --git a/packages/extra/monitoring/templates/helmrelease.yaml b/packages/extra/monitoring/templates/helmrelease.yaml deleted file mode 100644 index 0c3c2377..00000000 --- a/packages/extra/monitoring/templates/helmrelease.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: {{ .Release.Name }}-system - labels: - sharding.fluxcd.io/key: tenants -spec: - chartRef: - kind: ExternalArtifact - name: cozystack-monitoring-application-default-monitoring-system - namespace: cozy-system - interval: 5m - timeout: 10m - install: - remediation: - retries: -1 - upgrade: - force: true - remediation: - retries: -1 - valuesFrom: - - kind: Secret - name: cozystack-values - values: {{- .Values | toYaml | nindent 4 }} diff --git a/packages/system/monitoring/templates/vlogs/grafana-datasource.yaml b/packages/extra/monitoring/templates/vlogs/grafana-datasource.yaml similarity index 81% rename from packages/system/monitoring/templates/vlogs/grafana-datasource.yaml rename to packages/extra/monitoring/templates/vlogs/grafana-datasource.yaml index 72755c6f..0fa41288 100644 --- a/packages/system/monitoring/templates/vlogs/grafana-datasource.yaml +++ b/packages/extra/monitoring/templates/vlogs/grafana-datasource.yaml @@ -8,7 +8,7 @@ spec: access: proxy type: victoriametrics-logs-datasource name: vlogs-{{ .name }} - url: http://vlselect-{{ .name }}.{{ $.Release.Namespace }}.svc:9471 + url: http://vlogs-{{ .name }}.{{ $.Release.Namespace }}.svc:9428 instanceSelector: matchLabels: dashboards: grafana diff --git a/packages/extra/monitoring/templates/vlogs/vlogs.yaml b/packages/extra/monitoring/templates/vlogs/vlogs.yaml new file mode 100644 index 00000000..a82bca00 --- /dev/null +++ b/packages/extra/monitoring/templates/vlogs/vlogs.yaml @@ -0,0 +1,37 @@ +{{- range .Values.logsStorages }} +apiVersion: operator.victoriametrics.com/v1beta1 +kind: VLogs +metadata: + name: {{ .name }} +spec: + managedMetadata: + labels: + apps.cozystack.io/application.group: apps.cozystack.io + apps.cozystack.io/application.kind: Monitoring + apps.cozystack.io/application.name: {{ $.Release.Name }} + image: + tag: v1.17.0-victorialogs + storage: + resources: + requests: + storage: {{ .storage }} + storageClassName: {{ .storageClassName }} + accessModes: [ReadWriteOnce] + retentionPeriod: "{{ .retentionPeriod }}" + removePvcAfterDelete: true +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: vlogs-{{ .name }} +spec: + replicas: 1 + minReplicas: 1 + kind: monitoring + type: vlogs + selector: + app.kubernetes.io/component: monitoring + app.kubernetes.io/instance: {{ .name }} + app.kubernetes.io/name: vlogs + version: {{ $.Chart.Version }} +{{- end }} diff --git a/packages/system/monitoring/templates/vm/grafana-datasource.yaml b/packages/extra/monitoring/templates/vm/grafana-datasource.yaml similarity index 100% rename from packages/system/monitoring/templates/vm/grafana-datasource.yaml rename to packages/extra/monitoring/templates/vm/grafana-datasource.yaml diff --git a/packages/system/monitoring/templates/vm/vmagent.yaml b/packages/extra/monitoring/templates/vm/vmagent.yaml similarity index 69% rename from packages/system/monitoring/templates/vm/vmagent.yaml rename to packages/extra/monitoring/templates/vm/vmagent.yaml index 98bff1e1..2c6c391a 100644 --- a/packages/system/monitoring/templates/vm/vmagent.yaml +++ b/packages/extra/monitoring/templates/vm/vmagent.yaml @@ -1,4 +1,4 @@ -{{- if and (ne .Release.Namespace "tenant-root") (ne .Release.Namespace "cozy-monitoring") }} +{{- if ne .Release.Namespace "tenant-root" }} apiVersion: operator.victoriametrics.com/v1beta1 kind: VMAgent metadata: @@ -11,9 +11,6 @@ spec: externalLabels: cluster: {{ .Values.vmagent.externalLabels.cluster }} tenant: {{ .Release.Namespace }} - {{- if .Values.vmagent.externalLabels.environment }} - environment: {{ .Values.vmagent.externalLabels.environment | quote }} - {{- end }} extraArgs: promscrape.maxScrapeSize: "32MB" promscrape.streamParse: "true" @@ -24,10 +21,6 @@ spec: scrapeInterval: 30s selectAllByDefault: false - {{- with .Values.vmagent.inlineScrapeConfig }} - inlineScrapeConfig: | - {{- . | nindent 4 }} - {{- end }} podScrapeNamespaceSelector: matchLabels: namespace.cozystack.io/monitoring: {{ .Release.Namespace }} diff --git a/packages/system/monitoring/templates/vm/vmalert-scrape.yaml b/packages/extra/monitoring/templates/vm/vmalert-scrape.yaml similarity index 100% rename from packages/system/monitoring/templates/vm/vmalert-scrape.yaml rename to packages/extra/monitoring/templates/vm/vmalert-scrape.yaml diff --git a/packages/system/monitoring/templates/vm/vmalert.yaml b/packages/extra/monitoring/templates/vm/vmalert.yaml similarity index 75% rename from packages/system/monitoring/templates/vm/vmalert.yaml rename to packages/extra/monitoring/templates/vm/vmalert.yaml index 8da03e15..d66fc42c 100644 --- a/packages/system/monitoring/templates/vm/vmalert.yaml +++ b/packages/extra/monitoring/templates/vm/vmalert.yaml @@ -23,5 +23,19 @@ spec: url: http://vminsert-{{ .name }}.{{ $.Release.Namespace }}.svc:8480/insert/0/prometheus/api/v1/write resources: {} selectAllByDefault: true +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: vmalert-{{ .name }} +spec: + replicas: 1 + minReplicas: 1 + kind: monitoring + type: vmalert + selector: + app.kubernetes.io/instance: vmalert-{{ .name }} + app.kubernetes.io/name: vmalert + version: {{ $.Chart.Version }} {{- break }} {{- end }} diff --git a/packages/system/monitoring/templates/vm/vmcluster-scrape.yaml b/packages/extra/monitoring/templates/vm/vmcluster-scrape.yaml similarity index 100% rename from packages/system/monitoring/templates/vm/vmcluster-scrape.yaml rename to packages/extra/monitoring/templates/vm/vmcluster-scrape.yaml diff --git a/packages/system/monitoring/templates/vm/vmcluster.yaml b/packages/extra/monitoring/templates/vm/vmcluster.yaml similarity index 58% rename from packages/system/monitoring/templates/vm/vmcluster.yaml rename to packages/extra/monitoring/templates/vm/vmcluster.yaml index 1bc39923..5f86afa3 100644 --- a/packages/system/monitoring/templates/vm/vmcluster.yaml +++ b/packages/extra/monitoring/templates/vm/vmcluster.yaml @@ -49,4 +49,49 @@ spec: requests: storage: {{ .storage }} storageDataPath: /vm-data +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: {{ .name }}-vmstorage +spec: + replicas: 2 + minReplicas: 1 + kind: monitoring + type: vmstorage + selector: + app.kubernetes.io/component: monitoring + app.kubernetes.io/instance: {{ .name }} + app.kubernetes.io/name: vmstorage + version: {{ $.Chart.Version }} +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: {{ .name }}-vmselect +spec: + replicas: 2 + minReplicas: 1 + kind: monitoring + type: vmselect + selector: + app.kubernetes.io/component: monitoring + app.kubernetes.io/instance: {{ .name }} + app.kubernetes.io/name: vmselect + version: {{ $.Chart.Version }} +--- +apiVersion: cozystack.io/v1alpha1 +kind: WorkloadMonitor +metadata: + name: {{ .name }}-vminsert +spec: + replicas: 2 + minReplicas: 1 + kind: monitoring + type: vminsert + selector: + app.kubernetes.io/component: monitoring + app.kubernetes.io/instance: {{ .name }} + app.kubernetes.io/name: vminsert + version: {{ $.Chart.Version }} {{- end }} diff --git a/packages/system/monitoring/templates/vpa.yaml b/packages/extra/monitoring/templates/vpa.yaml similarity index 50% rename from packages/system/monitoring/templates/vpa.yaml rename to packages/extra/monitoring/templates/vpa.yaml index 551f8310..8b90c0ba 100644 --- a/packages/system/monitoring/templates/vpa.yaml +++ b/packages/extra/monitoring/templates/vpa.yaml @@ -87,92 +87,3 @@ spec: memory: 8Gi {{- end }} {{- end }} -{{- range .Values.logsStorages }} ---- -apiVersion: autoscaling.k8s.io/v1 -kind: VerticalPodAutoscaler -metadata: - name: vpa-vlinsert-{{ .name }} -spec: - targetRef: - apiVersion: apps/v1 - kind: Deployment - name: vlinsert-{{ .name }} - updatePolicy: - updateMode: Auto - resourcePolicy: - containerPolicies: - - containerName: vlinsert - minAllowed: - {{- if and .vlinsert .vlinsert.minAllowed }} - {{- toYaml .vlinsert.minAllowed | nindent 10 }} - {{- else }} - cpu: 25m - memory: 64Mi - {{- end }} - maxAllowed: - {{- if and .vlinsert .vlinsert.maxAllowed }} - {{- toYaml .vlinsert.maxAllowed | nindent 10 }} - {{- else }} - cpu: 2000m - memory: 4Gi - {{- end }} ---- -apiVersion: autoscaling.k8s.io/v1 -kind: VerticalPodAutoscaler -metadata: - name: vpa-vlselect-{{ .name }} -spec: - targetRef: - apiVersion: apps/v1 - kind: Deployment - name: vlselect-{{ .name }} - updatePolicy: - updateMode: Auto - resourcePolicy: - containerPolicies: - - containerName: vlselect - minAllowed: - {{- if and .vlselect .vlselect.minAllowed }} - {{- toYaml .vlselect.minAllowed | nindent 10 }} - {{- else }} - cpu: 25m - memory: 64Mi - {{- end }} - maxAllowed: - {{- if and .vlselect .vlselect.maxAllowed }} - {{- toYaml .vlselect.maxAllowed | nindent 10 }} - {{- else }} - cpu: 4000m - memory: 8Gi - {{- end }} ---- -apiVersion: autoscaling.k8s.io/v1 -kind: VerticalPodAutoscaler -metadata: - name: vpa-vlstorage-{{ .name }} -spec: - targetRef: - apiVersion: apps/v1 - kind: StatefulSet - name: vlstorage-{{ .name }} - updatePolicy: - updateMode: Auto - resourcePolicy: - containerPolicies: - - containerName: vlstorage - minAllowed: - {{- if and .vlstorage .vlstorage.minAllowed }} - {{- toYaml .vlstorage.minAllowed | nindent 10 }} - {{- else }} - cpu: 25m - memory: 64Mi - {{- end }} - maxAllowed: - {{- if and .vlstorage .vlstorage.maxAllowed }} - {{- toYaml .vlstorage.maxAllowed | nindent 10 }} - {{- else }} - cpu: 4000m - memory: 8Gi - {{- end }} -{{- end }} diff --git a/packages/extra/monitoring/templates/workloadmonitors.yaml b/packages/extra/monitoring/templates/workloadmonitors.yaml deleted file mode 100644 index 5d803351..00000000 --- a/packages/extra/monitoring/templates/workloadmonitors.yaml +++ /dev/null @@ -1,180 +0,0 @@ -{{- range .Values.metricsStorages }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .name }}-vmstorage -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: vmstorage - selector: - app.kubernetes.io/component: monitoring - app.kubernetes.io/instance: {{ .name }} - app.kubernetes.io/name: vmstorage - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .name }}-vmselect -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: vmselect - selector: - app.kubernetes.io/component: monitoring - app.kubernetes.io/instance: {{ .name }} - app.kubernetes.io/name: vmselect - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .name }}-vminsert -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: vminsert - selector: - app.kubernetes.io/component: monitoring - app.kubernetes.io/instance: {{ .name }} - app.kubernetes.io/name: vminsert - version: {{ $.Chart.Version }} -{{- end }} -{{- range .Values.metricsStorages }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: vmalert-{{ .name }} -spec: - replicas: 1 - minReplicas: 1 - kind: monitoring - type: vmalert - selector: - app.kubernetes.io/instance: vmalert-{{ .name }} - app.kubernetes.io/name: vmalert - version: {{ $.Chart.Version }} -{{- break }} -{{- end }} -{{- range .Values.logsStorages }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .name }}-vlstorage -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: vlstorage - selector: - app.kubernetes.io/component: monitoring - app.kubernetes.io/instance: {{ .name }} - app.kubernetes.io/name: vlstorage - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .name }}-vlselect -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: vlselect - selector: - app.kubernetes.io/component: monitoring - app.kubernetes.io/instance: {{ .name }} - app.kubernetes.io/name: vlselect - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ .name }}-vlinsert -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: vlinsert - selector: - app.kubernetes.io/component: monitoring - app.kubernetes.io/instance: {{ .name }} - app.kubernetes.io/name: vlinsert - version: {{ $.Chart.Version }} -{{- end }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: grafana -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: grafana - selector: - app: grafana - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: grafana-db -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: postgres - selector: - cnpg.io/cluster: grafana-db - cnpg.io/podRole: instance - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: alerta-db -spec: - replicas: 2 - minReplicas: 1 - kind: monitoring - type: postgres - selector: - cnpg.io/cluster: alerta-db - cnpg.io/podRole: instance - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: alerta -spec: - replicas: 1 - minReplicas: 1 - kind: monitoring - type: alerta - selector: - app: alerta - release: alerta - version: {{ $.Chart.Version }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: alertmanager -spec: - replicas: 3 - minReplicas: 2 - kind: monitoring - type: alertmanager - selector: - app.kubernetes.io/instance: alertmanager - app.kubernetes.io/name: vmalertmanager - version: {{ $.Chart.Version }} diff --git a/packages/extra/monitoring/values.schema.json b/packages/extra/monitoring/values.schema.json index 4bc6906e..0a6f0e64 100644 --- a/packages/extra/monitoring/values.schema.json +++ b/packages/extra/monitoring/values.schema.json @@ -2,11 +2,302 @@ "title": "Chart Values", "type": "object", "properties": { + "alerta": { + "description": "Configuration for the Alerta service.", + "type": "object", + "default": {}, + "properties": { + "alerts": { + "description": "Alert routing configuration.", + "type": "object", + "default": {}, + "properties": { + "slack": { + "description": "Configuration for Slack alerts.", + "type": "object", + "default": {}, + "required": [ + "url" + ], + "properties": { + "disabledSeverity": { + "description": "List of severities without alerts (e.g. [\"informational\",\"warning\"]).", + "type": "array", + "default": [], + "items": { + "type": "string" + } + }, + "url": { + "description": "Configuration uri for Slack alerts.", + "type": "string", + "default": "" + } + } + }, + "telegram": { + "description": "Configuration for Telegram alerts.", + "type": "object", + "default": {}, + "required": [ + "chatID", + "token" + ], + "properties": { + "chatID": { + "description": "Telegram chat ID(s), separated by commas.", + "type": "string", + "default": "" + }, + "disabledSeverity": { + "description": "List of severities without alerts (e.g. [\"informational\",\"warning\"]).", + "type": "array", + "default": [], + "items": { + "type": "string" + } + }, + "token": { + "description": "Telegram bot token.", + "type": "string", + "default": "" + } + } + } + } + }, + "resources": { + "description": "Resource configuration.", + "type": "object", + "default": {}, + "properties": { + "limits": { + "description": "Resource limits.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU limit.", + "default": 1, + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory limit.", + "default": "1Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "requests": { + "description": "Resource requests.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU request.", + "default": "100m", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory request.", + "default": "256Mi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + } + } + }, + "storage": { + "description": "Persistent volume size for the database.", + "type": "string", + "default": "10Gi" + }, + "storageClassName": { + "description": "StorageClass used for the database.", + "type": "string", + "default": "" + } + } + }, + "grafana": { + "description": "Configuration for Grafana.", + "type": "object", + "default": {}, + "properties": { + "db": { + "description": "Database configuration.", + "type": "object", + "default": {}, + "properties": { + "size": { + "description": "Persistent volume size for the database.", + "type": "string", + "default": "10Gi" + } + } + }, + "resources": { + "description": "Resource configuration.", + "type": "object", + "default": {}, + "properties": { + "limits": { + "description": "Resource limits.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU limit.", + "default": 1, + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory limit.", + "default": "1Gi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "requests": { + "description": "Resource requests.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "CPU request.", + "default": "100m", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Memory request.", + "default": "256Mi", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + } + } + } + } + }, "host": { "description": "The hostname used to access Grafana externally (defaults to 'grafana' subdomain for the tenant host).", "type": "string", "default": "" }, + "logsStorages": { + "description": "Configuration of logs storage instances.", + "type": "array", + "default": [ + { + "name": "generic", + "retentionPeriod": "1", + "storage": "10Gi", + "storageClassName": "replicated" + } + ], + "items": { + "type": "object", + "required": [ + "name", + "retentionPeriod", + "storage", + "storageClassName" + ], + "properties": { + "name": { + "description": "Name of the storage instance.", + "type": "string" + }, + "retentionPeriod": { + "description": "Retention period for logs.", + "type": "string", + "default": "1" + }, + "storage": { + "description": "Persistent volume size.", + "type": "string", + "default": "10Gi" + }, + "storageClassName": { + "description": "StorageClass used to store the data.", + "type": "string", + "default": "replicated" + } + } + } + }, "metricsStorages": { "description": "Configuration of metrics storage instances.", "type": "array", @@ -281,297 +572,6 @@ } } }, - "logsStorages": { - "description": "Configuration of logs storage instances.", - "type": "array", - "default": [ - { - "name": "generic", - "retentionPeriod": "1", - "storage": "10Gi", - "storageClassName": "replicated" - } - ], - "items": { - "type": "object", - "required": [ - "name", - "retentionPeriod", - "storage", - "storageClassName" - ], - "properties": { - "name": { - "description": "Name of the storage instance.", - "type": "string" - }, - "retentionPeriod": { - "description": "Retention period for logs.", - "type": "string", - "default": "1" - }, - "storage": { - "description": "Persistent volume size.", - "type": "string", - "default": "10Gi" - }, - "storageClassName": { - "description": "StorageClass used to store the data.", - "type": "string", - "default": "replicated" - } - } - } - }, - "alerta": { - "description": "Configuration for the Alerta service.", - "type": "object", - "default": {}, - "properties": { - "alerts": { - "description": "Alert routing configuration.", - "type": "object", - "default": {}, - "properties": { - "slack": { - "description": "Configuration for Slack alerts.", - "type": "object", - "default": {}, - "required": [ - "url" - ], - "properties": { - "disabledSeverity": { - "description": "List of severities without alerts (e.g. [\"informational\",\"warning\"]).", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, - "url": { - "description": "Configuration uri for Slack alerts.", - "type": "string", - "default": "" - } - } - }, - "telegram": { - "description": "Configuration for Telegram alerts.", - "type": "object", - "default": {}, - "required": [ - "chatID", - "token" - ], - "properties": { - "chatID": { - "description": "Telegram chat ID(s), separated by commas.", - "type": "string", - "default": "" - }, - "disabledSeverity": { - "description": "List of severities without alerts (e.g. [\"informational\",\"warning\"]).", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, - "token": { - "description": "Telegram bot token.", - "type": "string", - "default": "" - } - } - } - } - }, - "resources": { - "description": "Resource configuration.", - "type": "object", - "default": {}, - "properties": { - "limits": { - "description": "Resource limits.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU limit.", - "default": 1, - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory limit.", - "default": "1Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "requests": { - "description": "Resource requests.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU request.", - "default": "100m", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory request.", - "default": "256Mi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - } - } - }, - "storage": { - "description": "Persistent volume size for the database.", - "type": "string", - "default": "10Gi" - }, - "storageClassName": { - "description": "StorageClass used for the database.", - "type": "string", - "default": "" - } - } - }, - "grafana": { - "description": "Configuration for Grafana.", - "type": "object", - "default": {}, - "properties": { - "db": { - "description": "Database configuration.", - "type": "object", - "default": {}, - "properties": { - "size": { - "description": "Persistent volume size for the database.", - "type": "string", - "default": "10Gi" - } - } - }, - "resources": { - "description": "Resource configuration.", - "type": "object", - "default": {}, - "properties": { - "limits": { - "description": "Resource limits.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU limit.", - "default": 1, - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory limit.", - "default": "1Gi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "requests": { - "description": "Resource requests.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "CPU request.", - "default": "100m", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Memory request.", - "default": "256Mi", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - } - } - } - } - }, "vmagent": { "description": "Configuration for VictoriaMetrics Agent.", "type": "object", @@ -579,14 +579,12 @@ "properties": { "externalLabels": { "description": "External labels applied to all metrics.", - "type": "object", "default": { "cluster": "cozystack" } }, "remoteWrite": { "description": "Remote write configuration.", - "type": "object", "default": { "urls": [ "http://vminsert-shortterm:8480/insert/0/prometheus", @@ -597,4 +595,4 @@ } } } -} +} \ No newline at end of file diff --git a/packages/extra/monitoring/values.yaml b/packages/extra/monitoring/values.yaml index c521f389..ab32b1b2 100644 --- a/packages/extra/monitoring/values.yaml +++ b/packages/extra/monitoring/values.yaml @@ -178,7 +178,3 @@ vmagent: urls: - http://vminsert-shortterm:8480/insert/0/prometheus - http://vminsert-longterm:8480/insert/0/prometheus - ## inlineScrapeConfig: | - ## - job_name: "custom" - ## static_configs: - ## - targets: ["my-service:9090"] diff --git a/packages/extra/seaweedfs/README.md b/packages/extra/seaweedfs/README.md index 62bb9bf2..a6ad408f 100644 --- a/packages/extra/seaweedfs/README.md +++ b/packages/extra/seaweedfs/README.md @@ -1,4 +1,4 @@ -# Managed SeaweedFS Service +# Managed NATS Service ## Parameters @@ -13,68 +13,46 @@ ### SeaweedFS Components Configuration -| Name | Description | Type | Value | -| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------- | ------- | -| `db` | Database configuration. | `object` | `{}` | -| `db.replicas` | Number of database replicas. | `int` | `2` | -| `db.size` | Persistent Volume size. | `quantity` | `10Gi` | -| `db.storageClass` | StorageClass used to store the data. | `string` | `""` | -| `db.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `db.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `db.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `db.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `master` | Master service configuration. | `object` | `{}` | -| `master.replicas` | Number of master replicas. | `int` | `3` | -| `master.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `master.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `master.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `master.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `filer` | Filer service configuration. | `object` | `{}` | -| `filer.replicas` | Number of filer replicas. | `int` | `2` | -| `filer.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `filer.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `filer.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `filer.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `filer.grpcHost` | The hostname used to expose or access the filer service externally. | `string` | `""` | -| `filer.grpcPort` | The port used to access the filer service externally. | `int` | `443` | -| `filer.whitelist` | A list of IP addresses or CIDR ranges that are allowed to access the filer service. | `[]string` | `[]` | -| `volume` | Volume service configuration. | `object` | `{}` | -| `volume.replicas` | Number of volume replicas. | `int` | `2` | -| `volume.size` | Persistent Volume size. | `quantity` | `10Gi` | -| `volume.storageClass` | StorageClass used to store the data. | `string` | `""` | -| `volume.diskType` | SeaweedFS disk type tag for the default volume servers (e.g., "hdd", "ssd"). | `string` | `""` | -| `volume.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `volume.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `volume.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `volume.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | -| `volume.zones` | A map of zones for MultiZone topology. Each zone can have its own number of replicas and size. | `map[string]object` | `{}` | -| `volume.zones[name].replicas` | Number of replicas in the zone. | `int` | `0` | -| `volume.zones[name].size` | Zone storage size. | `quantity` | `""` | -| `volume.zones[name].dataCenter` | SeaweedFS data center name for this zone. Defaults to the zone name. | `string` | `""` | -| `volume.zones[name].nodeSelector` | YAML nodeSelector for this zone (default: topology.kubernetes.io/zone: ). | `string` | `""` | -| `volume.zones[name].storageClass` | StorageClass used to store zone data. Defaults to volume.storageClass. | `string` | `""` | -| `volume.zones[name].pools` | A map of storage pools for this zone. Each pool creates a separate Volume StatefulSet per zone. | `map[string]object` | `{}` | -| `volume.zones[name].pools[name].diskType` | SeaweedFS disk type tag (e.g., "ssd", "hdd", "nvme"). | `string` | `""` | -| `volume.zones[name].pools[name].replicas` | Number of volume replicas. Defaults to volume.replicas (Simple) or zone.replicas/volume.replicas (MultiZone). | `int` | `0` | -| `volume.zones[name].pools[name].size` | Persistent Volume size. Defaults to volume.size (Simple) or zone.size/volume.size (MultiZone). | `quantity` | `""` | -| `volume.zones[name].pools[name].storageClass` | Kubernetes StorageClass for the pool. Defaults to volume.storageClass. | `string` | `""` | -| `volume.zones[name].pools[name].resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `volume.zones[name].pools[name].resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `volume.zones[name].pools[name].resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `volume.zones[name].pools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `{}` | -| `volume.pools` | A map of storage pools. Each pool creates a separate Volume StatefulSet with its own disk type. | `map[string]object` | `{}` | -| `volume.pools[name].diskType` | SeaweedFS disk type tag (e.g., "ssd", "hdd", "nvme"). | `string` | `""` | -| `volume.pools[name].replicas` | Number of volume replicas. Defaults to volume.replicas (Simple) or zone.replicas/volume.replicas (MultiZone). | `int` | `0` | -| `volume.pools[name].size` | Persistent Volume size. Defaults to volume.size (Simple) or zone.size/volume.size (MultiZone). | `quantity` | `""` | -| `volume.pools[name].storageClass` | Kubernetes StorageClass for the pool. Defaults to volume.storageClass. | `string` | `""` | -| `volume.pools[name].resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `volume.pools[name].resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `volume.pools[name].resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `volume.pools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `{}` | -| `s3` | S3 service configuration. | `object` | `{}` | -| `s3.replicas` | Number of S3 replicas. | `int` | `2` | -| `s3.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | -| `s3.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | -| `s3.resources.memory` | Amount of memory allocated. | `quantity` | `""` | -| `s3.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | +| Name | Description | Type | Value | +| ----------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------- | ------- | +| `db` | Database configuration. | `object` | `{}` | +| `db.replicas` | Number of database replicas. | `int` | `2` | +| `db.size` | Persistent Volume size. | `quantity` | `10Gi` | +| `db.storageClass` | StorageClass used to store the data. | `string` | `""` | +| `db.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | +| `db.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `db.resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `db.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | +| `master` | Master service configuration. | `object` | `{}` | +| `master.replicas` | Number of master replicas. | `int` | `3` | +| `master.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | +| `master.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `master.resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `master.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | +| `filer` | Filer service configuration. | `object` | `{}` | +| `filer.replicas` | Number of filer replicas. | `int` | `2` | +| `filer.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | +| `filer.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `filer.resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `filer.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | +| `filer.grpcHost` | The hostname used to expose or access the filer service externally. | `string` | `""` | +| `filer.grpcPort` | The port used to access the filer service externally. | `int` | `443` | +| `filer.whitelist` | A list of IP addresses or CIDR ranges that are allowed to access the filer service. | `[]string` | `[]` | +| `volume` | Volume service configuration. | `object` | `{}` | +| `volume.replicas` | Number of volume replicas. | `int` | `2` | +| `volume.size` | Persistent Volume size. | `quantity` | `10Gi` | +| `volume.storageClass` | StorageClass used to store the data. | `string` | `""` | +| `volume.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | +| `volume.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `volume.resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `volume.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | +| `volume.zones` | A map of zones for MultiZone topology. Each zone can have its own number of replicas and size. | `map[string]object` | `{}` | +| `volume.zones[name].replicas` | Number of replicas in the zone. | `int` | `0` | +| `volume.zones[name].size` | Zone storage size. | `quantity` | `""` | +| `s3` | S3 service configuration. | `object` | `{}` | +| `s3.replicas` | Number of S3 replicas. | `int` | `2` | +| `s3.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` | +| `s3.resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` | +| `s3.resources.memory` | Amount of memory allocated. | `quantity` | `""` | +| `s3.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` | diff --git a/packages/extra/seaweedfs/images/objectstorage-sidecar.tag b/packages/extra/seaweedfs/images/objectstorage-sidecar.tag index 9b413da5..1db178ca 100644 --- a/packages/extra/seaweedfs/images/objectstorage-sidecar.tag +++ b/packages/extra/seaweedfs/images/objectstorage-sidecar.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.3.0@sha256:5bcccbdb13979a16cee535eb5fbcdf0d87973689010a10b7b25e55c5be3edaa6 +ghcr.io/cozystack/cozystack/objectstorage-sidecar:v1.0.0-beta.2@sha256:ea035d4eff4a05d9d83f487d00438504cc27a95c0ee78c534d6eed53f4b2f04e diff --git a/packages/extra/seaweedfs/images/seaweedfs-cosi-driver.tag b/packages/extra/seaweedfs/images/seaweedfs-cosi-driver.tag index 52494779..f07c125d 100644 --- a/packages/extra/seaweedfs/images/seaweedfs-cosi-driver.tag +++ b/packages/extra/seaweedfs/images/seaweedfs-cosi-driver.tag @@ -1 +1 @@ -ghcr.io/seaweedfs/seaweedfs-cosi-driver:v0.3.0 +ghcr.io/seaweedfs/seaweedfs-cosi-driver:v0.2.0 diff --git a/packages/extra/seaweedfs/templates/client/cosi-bucket-class.yaml b/packages/extra/seaweedfs/templates/client/cosi-bucket-class.yaml index ce049b31..76eda0dc 100644 --- a/packages/extra/seaweedfs/templates/client/cosi-bucket-class.yaml +++ b/packages/extra/seaweedfs/templates/client/cosi-bucket-class.yaml @@ -7,32 +7,10 @@ metadata: driverName: {{ .Release.Namespace }}.seaweedfs.objectstorage.k8s.io deletionPolicy: Delete --- -kind: BucketClass -apiVersion: objectstorage.k8s.io/v1alpha1 -metadata: - name: {{ .Release.Namespace }}-lock -driverName: {{ .Release.Namespace }}.seaweedfs.objectstorage.k8s.io -deletionPolicy: Retain -parameters: - objectLockEnabled: "true" - objectLockRetentionMode: "COMPLIANCE" - objectLockRetentionDays: "365" ---- kind: BucketAccessClass apiVersion: objectstorage.k8s.io/v1alpha1 metadata: name: {{ .Release.Namespace }} driverName: {{ .Release.Namespace }}.seaweedfs.objectstorage.k8s.io authenticationType: KEY -parameters: - accessPolicy: readwrite ---- -kind: BucketAccessClass -apiVersion: objectstorage.k8s.io/v1alpha1 -metadata: - name: {{ .Release.Namespace }}-readonly -driverName: {{ .Release.Namespace }}.seaweedfs.objectstorage.k8s.io -authenticationType: KEY -parameters: - accessPolicy: readonly {{- end }} diff --git a/packages/extra/seaweedfs/templates/dashboard-resourcemap.yaml b/packages/extra/seaweedfs/templates/dashboard-resourcemap.yaml index dfd408da..ec8860b7 100644 --- a/packages/extra/seaweedfs/templates/dashboard-resourcemap.yaml +++ b/packages/extra/seaweedfs/templates/dashboard-resourcemap.yaml @@ -25,21 +25,8 @@ rules: resourceNames: - {{ $.Release.Name }}-master - {{ $.Release.Name }}-filer - - {{ $.Release.Name }}-db - - {{ $.Release.Name }}-s3 - {{- if eq .Values.topology "Simple" }} - {{ $.Release.Name }}-volume - {{- range $poolName, $pool := .Values.volume.pools }} - - {{ $.Release.Name }}-volume-{{ $poolName }} - {{- end }} - {{- else if eq .Values.topology "MultiZone" }} - {{- range $zoneName, $zone := .Values.volume.zones }} - - {{ $.Release.Name }}-volume-{{ $zoneName }} - {{- range $poolName, $pool := (dig "pools" dict $zone) }} - - {{ $.Release.Name }}-volume-{{ $zoneName }}-{{ $poolName }} - {{- end }} - {{- end }} - {{- end }} + - {{ $.Release.Name }}-db verbs: ["get", "list", "watch"] {{- end }} diff --git a/packages/extra/seaweedfs/templates/seaweedfs.yaml b/packages/extra/seaweedfs/templates/seaweedfs.yaml index 2f5720ca..b04318bb 100644 --- a/packages/extra/seaweedfs/templates/seaweedfs.yaml +++ b/packages/extra/seaweedfs/templates/seaweedfs.yaml @@ -16,65 +16,6 @@ {{- fail "replicationFactor must be less than or equal to the number of zones defined in .Values.volume.zones." }} {{- end }} {{- end }} -{{- if and (eq .Values.topology "Client") (gt (len .Values.volume.pools) 0) }} -{{- fail "volume.pools is not supported with Client topology." }} -{{- end }} -{{- if and (eq .Values.topology "MultiZone") (gt (len .Values.volume.pools) 0) }} -{{- fail "volume.pools is not supported with MultiZone topology. Use volume.zones[name].pools instead." }} -{{- end }} -{{- if and .Values.volume.diskType (not (regexMatch "^[a-z0-9]+$" .Values.volume.diskType)) }} -{{- fail (printf "volume.diskType must be lowercase alphanumeric (got: %s)." .Values.volume.diskType) }} -{{- end }} - -{{- /* Collect and validate all pools from volume.pools and zones[].pools */ -}} -{{- $allPools := dict }} -{{- range $poolName, $pool := .Values.volume.pools }} -{{- if not (regexMatch "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$" $poolName) }} -{{- fail (printf "volume.pools key '%s' must be a valid DNS label (lowercase alphanumeric and hyphens, no dots)." $poolName) }} -{{- end }} -{{- if or (hasSuffix "-lock" $poolName) (hasSuffix "-readonly" $poolName) }} -{{- fail (printf "volume.pools key '%s' must not end with '-lock' or '-readonly' (reserved suffixes for COSI resources)." $poolName) }} -{{- end }} -{{- if not $pool.diskType }} -{{- fail (printf "volume.pools.%s.diskType is required." $poolName) }} -{{- end }} -{{- if not (regexMatch "^[a-z0-9]+$" $pool.diskType) }} -{{- fail (printf "volume.pools.%s.diskType must be lowercase alphanumeric (got: %s)." $poolName $pool.diskType) }} -{{- end }} -{{- if and $.Values.volume.diskType (eq $pool.diskType $.Values.volume.diskType) }} -{{- fail (printf "volume.pools.%s.diskType '%s' must differ from volume.diskType." $poolName $pool.diskType) }} -{{- end }} -{{- $_ := set $allPools $poolName $pool.diskType }} -{{- end }} -{{- if eq .Values.topology "MultiZone" }} -{{- range $zoneName, $zone := .Values.volume.zones }} -{{- range $poolName, $pool := (dig "pools" dict $zone) }} -{{- if not (regexMatch "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$" $poolName) }} -{{- fail (printf "volume.zones.%s.pools key '%s' must be a valid DNS label." $zoneName $poolName) }} -{{- end }} -{{- if or (hasSuffix "-lock" $poolName) (hasSuffix "-readonly" $poolName) }} -{{- fail (printf "volume.zones.%s.pools key '%s' must not end with '-lock' or '-readonly' (reserved suffixes for COSI resources)." $zoneName $poolName) }} -{{- end }} -{{- if not $pool.diskType }} -{{- fail (printf "volume.zones.%s.pools.%s.diskType is required." $zoneName $poolName) }} -{{- end }} -{{- if not (regexMatch "^[a-z0-9]+$" $pool.diskType) }} -{{- fail (printf "volume.zones.%s.pools.%s.diskType must be lowercase alphanumeric (got: %s)." $zoneName $poolName $pool.diskType) }} -{{- end }} -{{- if and $.Values.volume.diskType (eq $pool.diskType $.Values.volume.diskType) }} -{{- fail (printf "volume.zones.%s.pools.%s.diskType '%s' must differ from volume.diskType." $zoneName $poolName $pool.diskType) }} -{{- end }} -{{- if and (hasKey $allPools $poolName) (ne (get $allPools $poolName) $pool.diskType) }} -{{- fail (printf "Pool '%s' has inconsistent diskType across zones (expected '%s', got '%s' in zone '%s')." $poolName (get $allPools $poolName) $pool.diskType $zoneName) }} -{{- end }} -{{- $_ := set $allPools $poolName $pool.diskType }} -{{- $composedName := printf "%s-%s" $zoneName $poolName }} -{{- if hasKey $.Values.volume.zones $composedName }} -{{- fail (printf "Composed volume name '%s' (from zone '%s' and pool '%s') collides with an existing zone name." $composedName $zoneName $poolName) }} -{{- end }} -{{- end }} -{{- end }} -{{- end }} {{- $detectedTopology := "Unknown" }} {{- $configMap := lookup "v1" "ConfigMap" .Release.Namespace (printf "%s-deployed-topology" .Release.Name) }} @@ -95,8 +36,6 @@ {{- if not (eq .Values.topology "Client") }} {{- $ingress := .Values._namespace.ingress }} {{- $host := .Values._namespace.host }} -{{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }} apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: @@ -153,77 +92,30 @@ spec: storageClass: {{ . }} {{- end }} maxVolumes: 0 - {{- if .Values.volume.diskType }} - extraArgs: - - "-disk={{ .Values.volume.diskType }}" - {{- end }} - {{- if or (and (eq .Values.topology "Simple") (gt (len .Values.volume.pools) 0)) (eq .Values.topology "MultiZone") }} + {{ if eq .Values.topology "MultiZone" }} volumes: - {{- if eq .Values.topology "Simple" }} - {{- range $poolName, $pool := .Values.volume.pools }} - {{ $poolName }}: - replicas: {{ ternary $pool.replicas $.Values.volume.replicas (hasKey $pool "replicas") }} - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list ($pool.resourcesPreset | default $.Values.volume.resourcesPreset) (default dict $pool.resources) $) | nindent 12 }} - dataDirs: - - name: data1 - type: "persistentVolumeClaim" - size: "{{ $pool.size | default $.Values.volume.size }}" - {{- with ($pool.storageClass | default $.Values.volume.storageClass) }} - storageClass: "{{ . }}" - {{- end }} - maxVolumes: 0 - extraArgs: - - "-disk={{ $pool.diskType }}" - {{- end }} - {{- else if eq .Values.topology "MultiZone" }} {{- range $zoneName, $zone := .Values.volume.zones }} {{ $zoneName }}: - replicas: {{ ternary $zone.replicas $.Values.volume.replicas (hasKey $zone "replicas") }} - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list $.Values.volume.resourcesPreset $.Values.volume.resources $) | nindent 12 }} - dataDirs: - - name: data1 - type: "persistentVolumeClaim" - size: "{{ $zone.size | default $.Values.volume.size }}" - {{- with ($zone.storageClass | default $.Values.volume.storageClass) }} - storageClass: "{{ . }}" - {{- end }} - maxVolumes: 0 - nodeSelector: | - {{- with $zone.nodeSelector }} -{{ . | indent 12 }} - {{- else }} - topology.kubernetes.io/zone: {{ $zoneName }} - {{- end }} - dataCenter: {{ $zone.dataCenter | default $zoneName }} - {{- if $.Values.volume.diskType }} - extraArgs: - - "-disk={{ $.Values.volume.diskType }}" + {{ with $zone.replicas }} + replicas: {{ . }} {{- end }} - {{- end }} - {{- range $zoneName, $zone := .Values.volume.zones }} - {{- range $poolName, $pool := (dig "pools" dict $zone) }} - {{ $zoneName }}-{{ $poolName }}: - replicas: {{ ternary $pool.replicas (ternary $zone.replicas $.Values.volume.replicas (hasKey $zone "replicas")) (hasKey $pool "replicas") }} - resources: {{- include "cozy-lib.resources.defaultingSanitize" (list ($pool.resourcesPreset | default $.Values.volume.resourcesPreset) (default dict $pool.resources) $) | nindent 12 }} dataDirs: - name: data1 type: "persistentVolumeClaim" - size: "{{ $pool.size | default $zone.size | default $.Values.volume.size }}" - {{- with ($pool.storageClass | default $zone.storageClass | default $.Values.volume.storageClass) }} - storageClass: "{{ . }}" + {{- if $zone.size }} + size: "{{ $zone.size }}" + {{- else }} + size: "{{ $.Values.volume.size }}" + {{- end }} + {{- if $zone.storageClass }} + storageClass: {{ $zone.storageClass }} + {{- else if $.Values.volume.storageClass }} + storageClass: {{ $.Values.volume.storageClass }} {{- end }} maxVolumes: 0 nodeSelector: | - {{- with $zone.nodeSelector }} -{{ . | indent 12 }} - {{- else }} topology.kubernetes.io/zone: {{ $zoneName }} - {{- end }} dataCenter: {{ $zone.dataCenter | default $zoneName }} - extraArgs: - - "-disk={{ $pool.diskType }}" - {{- end }} - {{- end }} {{- end }} {{- end }} filer: @@ -242,10 +134,8 @@ spec: annotations: nginx.ingress.kubernetes.io/proxy-body-size: "0" nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} - {{- end }} - cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} + cert-manager.io/cluster-issuer: letsencrypt-prod tls: - hosts: - {{ .Values.host | default (printf "s3.%s" $host) }} @@ -305,22 +195,6 @@ spec: app.kubernetes.io/component: volume app.kubernetes.io/name: seaweedfs version: {{ $.Chart.Version }} -{{- range $poolName, $pool := .Values.volume.pools }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ $.Release.Name }}-volume-{{ $poolName }} -spec: - replicas: {{ ternary $pool.replicas $.Values.volume.replicas (hasKey $pool "replicas") }} - minReplicas: 1 - kind: seaweedfs - type: volume - selector: - app.kubernetes.io/component: volume-{{ $poolName }} - app.kubernetes.io/name: seaweedfs - version: {{ $.Chart.Version }} -{{- end }} {{- else if eq .Values.topology "MultiZone" }} {{- range $zoneName, $zoneSpec := .Values.volume.zones }} --- @@ -329,7 +203,7 @@ kind: WorkloadMonitor metadata: name: {{ $.Release.Name }}-volume-{{ $zoneName }} spec: - replicas: {{ ternary $zoneSpec.replicas $.Values.volume.replicas (hasKey $zoneSpec "replicas") }} + replicas: {{ default $.Values.volume.replicas $zoneSpec.replicas }} minReplicas: 1 kind: seaweedfs type: volume @@ -337,22 +211,6 @@ spec: app.kubernetes.io/component: volume-{{ $zoneName }} app.kubernetes.io/name: seaweedfs version: {{ $.Chart.Version }} -{{- range $poolName, $pool := (dig "pools" dict $zoneSpec) }} ---- -apiVersion: cozystack.io/v1alpha1 -kind: WorkloadMonitor -metadata: - name: {{ $.Release.Name }}-volume-{{ $zoneName }}-{{ $poolName }} -spec: - replicas: {{ ternary $pool.replicas (ternary $zoneSpec.replicas $.Values.volume.replicas (hasKey $zoneSpec "replicas")) (hasKey $pool "replicas") }} - minReplicas: 1 - kind: seaweedfs - type: volume - selector: - app.kubernetes.io/component: volume-{{ $zoneName }}-{{ $poolName }} - app.kubernetes.io/name: seaweedfs - version: {{ $.Chart.Version }} -{{- end }} {{- end }} {{- end }} --- diff --git a/packages/extra/seaweedfs/templates/storage-pool-bucket-classes.yaml b/packages/extra/seaweedfs/templates/storage-pool-bucket-classes.yaml deleted file mode 100644 index bf58340a..00000000 --- a/packages/extra/seaweedfs/templates/storage-pool-bucket-classes.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if ne .Values.topology "Client" }} -{{- /* Collect unique pools from volume.pools and zones[].pools */ -}} -{{- $uniquePools := dict }} -{{- range $poolName, $pool := .Values.volume.pools }} -{{- $_ := set $uniquePools $poolName $pool.diskType }} -{{- end }} -{{- if eq .Values.topology "MultiZone" }} -{{- range $zoneName, $zone := .Values.volume.zones }} -{{- range $poolName, $pool := (dig "pools" dict $zone) }} -{{- $_ := set $uniquePools $poolName $pool.diskType }} -{{- end }} -{{- end }} -{{- end }} -{{- range $poolName, $diskType := $uniquePools }} ---- -kind: BucketClass -apiVersion: objectstorage.k8s.io/v1alpha1 -metadata: - name: {{ $.Release.Namespace }}-{{ $poolName }} -driverName: {{ $.Release.Namespace }}.seaweedfs.objectstorage.k8s.io -deletionPolicy: Delete -parameters: - disk: {{ $diskType }} ---- -kind: BucketClass -apiVersion: objectstorage.k8s.io/v1alpha1 -metadata: - name: {{ $.Release.Namespace }}-{{ $poolName }}-lock -driverName: {{ $.Release.Namespace }}.seaweedfs.objectstorage.k8s.io -deletionPolicy: Retain -parameters: - disk: {{ $diskType }} - objectLockEnabled: "true" - objectLockRetentionMode: "COMPLIANCE" - objectLockRetentionDays: "365" ---- -kind: BucketAccessClass -apiVersion: objectstorage.k8s.io/v1alpha1 -metadata: - name: {{ $.Release.Namespace }}-{{ $poolName }} -driverName: {{ $.Release.Namespace }}.seaweedfs.objectstorage.k8s.io -authenticationType: KEY -parameters: - accessPolicy: readwrite ---- -kind: BucketAccessClass -apiVersion: objectstorage.k8s.io/v1alpha1 -metadata: - name: {{ $.Release.Namespace }}-{{ $poolName }}-readonly -driverName: {{ $.Release.Namespace }}.seaweedfs.objectstorage.k8s.io -authenticationType: KEY -parameters: - accessPolicy: readonly -{{- end }} -{{- end }} diff --git a/packages/extra/seaweedfs/values.schema.json b/packages/extra/seaweedfs/values.schema.json index 9b48043d..4003df9e 100644 --- a/packages/extra/seaweedfs/values.schema.json +++ b/packages/extra/seaweedfs/values.schema.json @@ -2,26 +2,6 @@ "title": "Chart Values", "type": "object", "properties": { - "host": { - "description": "The hostname used to access SeaweedFS externally (defaults to 's3' subdomain for the tenant host).", - "type": "string", - "default": "" - }, - "topology": { - "description": "The topology of the SeaweedFS cluster.", - "type": "string", - "default": "Simple", - "enum": [ - "Simple", - "MultiZone", - "Client" - ] - }, - "replicationFactor": { - "description": "Replication factor: number of replicas for each volume in the SeaweedFS cluster.", - "type": "integer", - "default": 2 - }, "db": { "description": "Database configuration.", "type": "object", @@ -100,65 +80,6 @@ } } }, - "master": { - "description": "Master service configuration.", - "type": "object", - "default": {}, - "properties": { - "replicas": { - "description": "Number of master replicas.", - "type": "integer", - "default": 3 - }, - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "small", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - } - } - }, "filer": { "description": "Filer service configuration.", "type": "object", @@ -236,99 +157,149 @@ } } }, + "host": { + "description": "The hostname used to access SeaweedFS externally (defaults to 's3' subdomain for the tenant host).", + "type": "string", + "default": "" + }, + "master": { + "description": "Master service configuration.", + "type": "object", + "default": {}, + "properties": { + "replicas": { + "description": "Number of master replicas.", + "type": "integer", + "default": 3 + }, + "resources": { + "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "Number of CPU cores allocated.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Amount of memory allocated.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "resourcesPreset": { + "description": "Default sizing preset used when `resources` is omitted.", + "type": "string", + "default": "small", + "enum": [ + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + } + } + }, + "replicationFactor": { + "description": "Replication factor: number of replicas for each volume in the SeaweedFS cluster.", + "type": "integer", + "default": 2 + }, + "s3": { + "description": "S3 service configuration.", + "type": "object", + "default": {}, + "properties": { + "replicas": { + "description": "Number of S3 replicas.", + "type": "integer", + "default": 2 + }, + "resources": { + "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", + "type": "object", + "default": {}, + "properties": { + "cpu": { + "description": "Number of CPU cores allocated.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + }, + "memory": { + "description": "Amount of memory allocated.", + "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "x-kubernetes-int-or-string": true + } + } + }, + "resourcesPreset": { + "description": "Default sizing preset used when `resources` is omitted.", + "type": "string", + "default": "small", + "enum": [ + "nano", + "micro", + "small", + "medium", + "large", + "xlarge", + "2xlarge" + ] + } + } + }, + "topology": { + "description": "The topology of the SeaweedFS cluster.", + "type": "string", + "default": "Simple", + "enum": [ + "Simple", + "MultiZone", + "Client" + ] + }, "volume": { "description": "Volume service configuration.", "type": "object", "default": {}, "properties": { - "diskType": { - "description": "SeaweedFS disk type tag for the default volume servers (e.g., \"hdd\", \"ssd\").", - "type": "string", - "default": "" - }, - "pools": { - "description": "A map of storage pools. Each pool creates a separate Volume StatefulSet with its own disk type.", - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "required": [ - "diskType" - ], - "properties": { - "diskType": { - "description": "SeaweedFS disk type tag (e.g., \"ssd\", \"hdd\", \"nvme\").", - "type": "string" - }, - "replicas": { - "description": "Number of volume replicas. Defaults to volume.replicas (Simple) or zone.replicas/volume.replicas (MultiZone).", - "type": "integer" - }, - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset.", - "type": "string", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, - "size": { - "description": "Persistent Volume size. Defaults to volume.size (Simple) or zone.size/volume.size (MultiZone).", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "Kubernetes StorageClass for the pool. Defaults to volume.storageClass.", - "type": "string" - } - } - } - }, "replicas": { "description": "Number of volume replicas.", "type": "integer", @@ -407,96 +378,6 @@ "additionalProperties": { "type": "object", "properties": { - "dataCenter": { - "description": "SeaweedFS data center name for this zone. Defaults to the zone name.", - "type": "string" - }, - "nodeSelector": { - "description": "YAML nodeSelector for this zone (default: topology.kubernetes.io/zone: \u003czoneName\u003e).", - "type": "string" - }, - "pools": { - "description": "A map of storage pools for this zone. Each pool creates a separate Volume StatefulSet per zone.", - "type": "object", - "additionalProperties": { - "type": "object", - "required": [ - "diskType" - ], - "properties": { - "diskType": { - "description": "SeaweedFS disk type tag (e.g., \"ssd\", \"hdd\", \"nvme\").", - "type": "string" - }, - "replicas": { - "description": "Number of volume replicas. Defaults to volume.replicas (Simple) or zone.replicas/volume.replicas (MultiZone).", - "type": "integer" - }, - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset.", - "type": "string", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - }, - "size": { - "description": "Persistent Volume size. Defaults to volume.size (Simple) or zone.size/volume.size (MultiZone).", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "Kubernetes StorageClass for the pool. Defaults to volume.storageClass.", - "type": "string" - } - } - } - }, "replicas": { "description": "Number of replicas in the zone.", "type": "integer" @@ -513,74 +394,11 @@ } ], "x-kubernetes-int-or-string": true - }, - "storageClass": { - "description": "StorageClass used to store zone data. Defaults to volume.storageClass.", - "type": "string" } } } } } - }, - "s3": { - "description": "S3 service configuration.", - "type": "object", - "default": {}, - "properties": { - "replicas": { - "description": "Number of S3 replicas.", - "type": "integer", - "default": 2 - }, - "resources": { - "description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.", - "type": "object", - "default": {}, - "properties": { - "cpu": { - "description": "Number of CPU cores allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - }, - "memory": { - "description": "Amount of memory allocated.", - "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$", - "anyOf": [ - { - "type": "integer" - }, - { - "type": "string" - } - ], - "x-kubernetes-int-or-string": true - } - } - }, - "resourcesPreset": { - "description": "Default sizing preset used when `resources` is omitted.", - "type": "string", - "default": "small", - "enum": [ - "nano", - "micro", - "small", - "medium", - "large", - "xlarge", - "2xlarge" - ] - } - } } } -} +} \ No newline at end of file diff --git a/packages/extra/seaweedfs/values.yaml b/packages/extra/seaweedfs/values.yaml index 9965d5d0..e2fc02fd 100644 --- a/packages/extra/seaweedfs/values.yaml +++ b/packages/extra/seaweedfs/values.yaml @@ -76,49 +76,26 @@ filer: grpcPort: 443 whitelist: [] -## @typedef {struct} StoragePool - Storage pool configuration for separating buckets by disk type. -## @field {string} diskType - SeaweedFS disk type tag (e.g., "ssd", "hdd", "nvme"). -## @field {int} [replicas] - Number of volume replicas. Defaults to volume.replicas (Simple) or zone.replicas/volume.replicas (MultiZone). -## @field {quantity} [size] - Persistent Volume size. Defaults to volume.size (Simple) or zone.size/volume.size (MultiZone). -## @field {string} [storageClass] - Kubernetes StorageClass for the pool. Defaults to volume.storageClass. -## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. -## @field {ResourcesPreset} [resourcesPreset] - Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. - ## @typedef {struct} Zone - Zone configuration. ## @field {int} [replicas] - Number of replicas in the zone. ## @field {quantity} [size] - Zone storage size. -## @field {string} [dataCenter] - SeaweedFS data center name for this zone. Defaults to the zone name. -## @field {string} [nodeSelector] - YAML nodeSelector for this zone (default: topology.kubernetes.io/zone: ). -## @field {string} [storageClass] - StorageClass used to store zone data. Defaults to volume.storageClass. -## @field {map[string]StoragePool} [pools] - A map of storage pools for this zone. Each pool creates a separate Volume StatefulSet per zone. -## NOTE: Zone-level resources/resourcesPreset are inherited from volume.* settings. Pools within a zone can define their own resources. ## @typedef {struct} Volume - Volume service configuration. ## @field {int} [replicas] - Number of volume replicas. ## @field {quantity} [size] - Persistent Volume size. ## @field {string} [storageClass] - StorageClass used to store the data. -## @field {string} [diskType] - SeaweedFS disk type tag for the default volume servers (e.g., "hdd", "ssd"). ## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. ## @field {ResourcesPreset} [resourcesPreset] - Default sizing preset used when `resources` is omitted. ## @field {map[string]Zone} [zones] - A map of zones for MultiZone topology. Each zone can have its own number of replicas and size. -## @field {map[string]StoragePool} [pools] - A map of storage pools. Each pool creates a separate Volume StatefulSet with its own disk type. ## @param {Volume} [volume] - Volume service configuration. volume: replicas: 2 size: 10Gi storageClass: "" - diskType: "" resources: {} resourcesPreset: "small" zones: {} - pools: {} - #pools: - # fast: - # diskType: ssd - # replicas: 2 - # size: 50Gi - # storageClass: "local-nvme" ## @typedef {struct} S3 - S3 service configuration. ## @field {int} [replicas] - Number of S3 replicas. diff --git a/packages/library/cozy-lib/templates/_strings.tpl b/packages/library/cozy-lib/templates/_strings.tpl deleted file mode 100644 index 0ba8153f..00000000 --- a/packages/library/cozy-lib/templates/_strings.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{{- define "cozy-lib.strings.hexToInt" }} -{{- printf "num: 0x%s" . | fromYaml | dig "num" 0 }} -{{- end }} diff --git a/packages/system/backup-controller/Makefile b/packages/system/backup-controller/Makefile index 472a99ba..81a3c0fb 100644 --- a/packages/system/backup-controller/Makefile +++ b/packages/system/backup-controller/Makefile @@ -4,7 +4,7 @@ NAMESPACE=cozy-backup-controller include ../../../hack/common-envs.mk include ../../../hack/package.mk -image: image-backup-controller +image: image-backup-controller image-backupstrategy-controller image-backup-controller: docker buildx build -f images/backup-controller/Dockerfile ../../.. \ @@ -16,3 +16,14 @@ image-backup-controller: IMAGE="$(REGISTRY)/backup-controller:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/backup-controller.json -o json -r)" \ yq -i '.backupController.image = strenv(IMAGE)' values.yaml rm -f images/backup-controller.json + +image-backupstrategy-controller: + docker buildx build -f images/backupstrategy-controller/Dockerfile ../../.. \ + --tag $(REGISTRY)/backupstrategy-controller:$(call settag,$(TAG)) \ + --cache-from type=registry,ref=$(REGISTRY)/backupstrategy-controller:latest \ + --cache-to type=inline \ + --metadata-file images/backupstrategy-controller.json \ + $(BUILDX_ARGS) + IMAGE="$(REGISTRY)/backupstrategy-controller:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/backupstrategy-controller.json -o json -r)" \ + yq -i '.backupStrategyController.image = strenv(IMAGE)' values.yaml + rm -f images/backupstrategy-controller.json diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_backupclasses.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_backupclasses.yaml index 4af8cf7d..b0f0fec2 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_backupclasses.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_backupclasses.yaml @@ -60,7 +60,7 @@ spec: type: string kind: description: Kind is the kind of the application (e.g., - VirtualMachine, MariaDB). + VirtualMachine, MySQL). type: string required: - kind diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml index 7a0ed6f5..686c079f 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_backupjobs.yaml @@ -74,12 +74,7 @@ spec: BackupClassName references a BackupClass that contains strategy and storage configuration. The BackupClass will be resolved to determine the appropriate strategy and storage based on the ApplicationRef. - This field is immutable once the BackupJob is created. - minLength: 1 type: string - x-kubernetes-validations: - - message: backupClassName is immutable - rule: self == oldSelf planRef: description: |- PlanRef refers to the Plan that requested this backup run. diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml index d48df533..6d55cb84 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_backups.yaml @@ -205,14 +205,6 @@ spec: Phase is a simple, high-level summary of the backup's state. Typical values are: Pending, Ready, Failed. type: string - underlyingResources: - description: |- - UnderlyingResources holds application-specific resource metadata discovered - during backup (e.g., VM disks, network configuration). The payload is a - self-typed JSON object carrying an inlined TypeMeta (kind/apiVersion) so - the consuming controller can dispatch on the application kind. - type: object - x-kubernetes-preserve-unknown-fields: true type: object type: object selectableFields: diff --git a/packages/system/backup-controller/definitions/backups.cozystack.io_restorejobs.yaml b/packages/system/backup-controller/definitions/backups.cozystack.io_restorejobs.yaml index b9465994..607a69b2 100644 --- a/packages/system/backup-controller/definitions/backups.cozystack.io_restorejobs.yaml +++ b/packages/system/backup-controller/definitions/backups.cozystack.io_restorejobs.yaml @@ -14,11 +14,7 @@ spec: singular: restorejob scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .status.phase - name: Phase - type: string - name: v1alpha1 + - name: v1alpha1 schema: openAPIV3Schema: description: RestoreJob represents a single execution of a restore from a @@ -59,12 +55,6 @@ spec: type: string type: object x-kubernetes-map-type: atomic - options: - description: |- - Options is a driver-specific blob of restore options, typed based on - targetApplicationRef and the current controller implementation. - type: object - x-kubernetes-preserve-unknown-fields: true targetApplicationRef: description: |- TargetApplicationRef refers to the application into which the backup @@ -176,5 +166,3 @@ spec: type: object served: true storage: true - subresources: - status: {} diff --git a/packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_jobs.yaml b/packages/system/backup-controller/definitions/strategy.backups.cozystack.io_jobs.yaml similarity index 100% rename from packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_jobs.yaml rename to packages/system/backup-controller/definitions/strategy.backups.cozystack.io_jobs.yaml diff --git a/packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml b/packages/system/backup-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml similarity index 57% rename from packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml rename to packages/system/backup-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml index 34254aed..e817de23 100644 --- a/packages/system/backupstrategy-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml +++ b/packages/system/backup-controller/definitions/strategy.backups.cozystack.io_veleroes.yaml @@ -45,428 +45,6 @@ spec: VeleroTemplate describes the data a backup.velero.io should have when templated from a Velero backup strategy. properties: - restoreSpec: - description: RestoreSpec defines the specification for a Velero - restore. - properties: - backupName: - description: |- - BackupName is the unique name of the Velero backup to restore - from. - type: string - excludedNamespaces: - description: |- - ExcludedNamespaces contains a list of namespaces that are not - included in the restore. - items: - type: string - nullable: true - type: array - excludedResources: - description: |- - ExcludedResources is a slice of resource names that are not - included in the restore. - items: - type: string - nullable: true - type: array - existingResourcePolicy: - description: ExistingResourcePolicy specifies the restore - behavior for the Kubernetes resource to be restored - nullable: true - type: string - hooks: - description: Hooks represent custom behaviors that should - be executed during or post restore. - properties: - resources: - items: - description: |- - RestoreResourceHookSpec defines one or more RestoreResrouceHooks that should be executed based on - the rules defined for namespaces, resources, and label selector. - properties: - excludedNamespaces: - description: ExcludedNamespaces specifies the namespaces - to which this hook spec does not apply. - items: - type: string - nullable: true - type: array - excludedResources: - description: ExcludedResources specifies the resources - to which this hook spec does not apply. - items: - type: string - nullable: true - type: array - includedNamespaces: - description: |- - IncludedNamespaces specifies the namespaces to which this hook spec applies. If empty, it applies - to all namespaces. - items: - type: string - nullable: true - type: array - includedResources: - description: |- - IncludedResources specifies the resources to which this hook spec applies. If empty, it applies - to all resources. - items: - type: string - nullable: true - type: array - labelSelector: - description: LabelSelector, if specified, filters - the resources to which this hook spec applies. - nullable: true - 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 - name: - description: Name is the name of this hook. - type: string - postHooks: - description: PostHooks is a list of RestoreResourceHooks - to execute during and after restoring a resource. - items: - description: RestoreResourceHook defines a restore - hook for a resource. - properties: - exec: - description: Exec defines an exec restore - hook. - properties: - command: - description: Command is the command and - arguments to execute from within a container - after a pod has been restored. - items: - type: string - minItems: 1 - type: array - container: - description: |- - Container is the container in the pod where the command should be executed. If not specified, - the pod's first container is used. - type: string - execTimeout: - description: |- - ExecTimeout defines the maximum amount of time Velero should wait for the hook to complete before - considering the execution a failure. - type: string - onError: - description: OnError specifies how Velero - should behave if it encounters an error - executing this hook. - enum: - - Continue - - Fail - type: string - waitForReady: - description: WaitForReady ensures command - will be launched when container is Ready - instead of Running. - nullable: true - type: boolean - waitTimeout: - description: |- - WaitTimeout defines the maximum amount of time Velero should wait for the container to be Ready - before attempting to run the command. - type: string - required: - - command - type: object - init: - description: Init defines an init restore - hook. - properties: - initContainers: - description: InitContainers is list of - init containers to be added to a pod - during its restore. - items: - type: object - x-kubernetes-preserve-unknown-fields: true - type: array - x-kubernetes-preserve-unknown-fields: true - timeout: - description: Timeout defines the maximum - amount of time Velero should wait for - the initContainers to complete. - type: string - type: object - type: object - type: array - required: - - name - type: object - type: array - type: object - includeClusterResources: - description: |- - IncludeClusterResources specifies whether cluster-scoped resources - should be included for consideration in the restore. If null, defaults - to true. - nullable: true - type: boolean - includedNamespaces: - description: |- - IncludedNamespaces is a slice of namespace names to include objects - from. If empty, all namespaces are included. - items: - type: string - nullable: true - type: array - includedResources: - description: |- - IncludedResources is a slice of resource names to include - in the restore. If empty, all resources in the backup are included. - items: - type: string - nullable: true - type: array - itemOperationTimeout: - description: |- - ItemOperationTimeout specifies the time used to wait for RestoreItemAction operations - The default value is 4 hour. - type: string - labelSelector: - description: |- - LabelSelector is a metav1.LabelSelector to filter with - when restoring individual objects from the backup. If empty - or nil, all objects are included. Optional. - nullable: true - 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 - namespaceMapping: - additionalProperties: - type: string - description: |- - NamespaceMapping is a map of source namespace names - to target namespace names to restore into. Any source - namespaces not included in the map will be restored into - namespaces of the same name. - type: object - orLabelSelectors: - description: |- - OrLabelSelectors is list of metav1.LabelSelector to filter with - when restoring individual objects from the backup. If multiple provided - they will be joined by the OR operator. LabelSelector as well as - OrLabelSelectors cannot co-exist in restore request, only one of them - can be used - items: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - 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 - nullable: true - type: array - preserveNodePorts: - description: PreserveNodePorts specifies whether to restore - old nodePorts from backup. - nullable: true - type: boolean - resourceModifier: - description: ResourceModifier specifies the reference to JSON - resource patches that should be applied to resources before - restoration. - nullable: true - properties: - apiGroup: - description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - name: - description: Name is the name of resource being referenced - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - restorePVs: - description: |- - RestorePVs specifies whether to restore all included - PVs from snapshot - nullable: true - type: boolean - restoreStatus: - description: |- - RestoreStatus specifies which resources we should restore the status - field. If nil, no objects are included. Optional. - nullable: true - properties: - excludedResources: - description: ExcludedResources specifies the resources - to which will not restore the status. - items: - type: string - nullable: true - type: array - includedResources: - description: |- - IncludedResources specifies the resources to which will restore the status. - If empty, it applies to all resources. - items: - type: string - nullable: true - type: array - type: object - scheduleName: - description: |- - ScheduleName is the unique name of the Velero schedule to restore - from. If specified, and BackupName is empty, Velero will restore - from the most recent successful backup created from this schedule. - type: string - uploaderConfig: - description: UploaderConfig specifies the configuration for - the restore. - nullable: true - properties: - parallelFilesDownload: - description: ParallelFilesDownload is the concurrency - number setting for restore. - type: integer - writeSparseFiles: - description: WriteSparseFiles is a flag to indicate whether - write files sparsely or not. - nullable: true - type: boolean - type: object - type: object spec: description: BackupSpec defines the specification for a Velero backup. diff --git a/packages/system/backupstrategy-controller/images/backupstrategy-controller/Dockerfile b/packages/system/backup-controller/images/backupstrategy-controller/Dockerfile similarity index 100% rename from packages/system/backupstrategy-controller/images/backupstrategy-controller/Dockerfile rename to packages/system/backup-controller/images/backupstrategy-controller/Dockerfile diff --git a/packages/system/backupstrategy-controller/templates/deployment.yaml b/packages/system/backup-controller/templates/backupstrategy-deployment.yaml similarity index 100% rename from packages/system/backupstrategy-controller/templates/deployment.yaml rename to packages/system/backup-controller/templates/backupstrategy-deployment.yaml diff --git a/packages/system/backupstrategy-controller/templates/rbac-bind.yaml b/packages/system/backup-controller/templates/backupstrategy-rbac-bind.yaml similarity index 100% rename from packages/system/backupstrategy-controller/templates/rbac-bind.yaml rename to packages/system/backup-controller/templates/backupstrategy-rbac-bind.yaml diff --git a/packages/system/backup-controller/templates/backupstrategy-rbac.yaml b/packages/system/backup-controller/templates/backupstrategy-rbac.yaml new file mode 100644 index 00000000..85431a4b --- /dev/null +++ b/packages/system/backup-controller/templates/backupstrategy-rbac.yaml @@ -0,0 +1,11 @@ +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: backups.cozystack.io:strategy-controller +rules: +- apiGroups: ["strategy.backups.cozystack.io"] + resources: ["*"] + verbs: ["get", "list", "watch"] +- apiGroups: ["backups.cozystack.io"] + resources: ["backupjobs", "restorejobs"] + verbs: ["get", "list", "watch"] diff --git a/packages/system/backupstrategy-controller/templates/sa.yaml b/packages/system/backup-controller/templates/backupstrategy-sa.yaml similarity index 100% rename from packages/system/backupstrategy-controller/templates/sa.yaml rename to packages/system/backup-controller/templates/backupstrategy-sa.yaml diff --git a/packages/system/backup-controller/templates/rbac.yaml b/packages/system/backup-controller/templates/rbac.yaml index da2460c0..255398e8 100644 --- a/packages/system/backup-controller/templates/rbac.yaml +++ b/packages/system/backup-controller/templates/rbac.yaml @@ -3,21 +3,30 @@ apiVersion: rbac.authorization.k8s.io/v1 metadata: name: backups.cozystack.io:core-controller rules: -# Plan: reconcile schedule and update status - apiGroups: ["backups.cozystack.io"] resources: ["plans"] verbs: ["get", "list", "watch"] -- apiGroups: ["backups.cozystack.io"] - resources: ["plans/status"] - verbs: ["get", "update", "patch"] -# BackupJob: create when schedule fires (status is updated by backupstrategy-controller) - apiGroups: ["backups.cozystack.io"] resources: ["backupjobs"] + verbs: ["create", "get", "list", "watch", "update", "patch"] +- apiGroups: ["backups.cozystack.io"] + resources: ["backupjobs/status"] + verbs: ["get", "update", "patch"] +- apiGroups: ["backups.cozystack.io"] + resources: ["backups"] verbs: ["create", "get", "list", "watch"] -# Leader election (--leader-elect) -- apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["get", "list", "watch", "create", "update", "patch"] +- apiGroups: ["apps.cozystack.io"] + resources: ["buckets", "bucketaccesses", "virtualmachines"] + verbs: ["get", "list", "watch"] +- apiGroups: ["objectstorage.k8s.io"] + resources: ["buckets", "bucketaccesses"] + verbs: ["get", "list", "watch"] - apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] + resources: ["secrets"] + verbs: ["create", "get", "list", "watch", "update", "patch"] +- apiGroups: ["kubevirt.io"] + resources: ["virtualmachines"] + verbs: ["get", "list", "watch"] +- apiGroups: ["velero.io"] + resources: ["backups", "backupstoragelocations", "volumesnapshotlocations", "restores"] + verbs: ["create", "get", "list", "watch", "update", "patch"] diff --git a/packages/system/backup-controller/templates/strategy.yaml b/packages/system/backup-controller/templates/strategy.yaml new file mode 100644 index 00000000..a8396d66 --- /dev/null +++ b/packages/system/backup-controller/templates/strategy.yaml @@ -0,0 +1,10 @@ +apiVersion: strategy.backups.cozystack.io/v1alpha1 +kind: Velero +metadata: + name: velero-strategy-default +spec: + template: + spec: + ttl: 720h + includedNamespaces: + - "*" diff --git a/packages/system/backup-controller/templates/tenant-clusterroles.yaml b/packages/system/backup-controller/templates/tenant-clusterroles.yaml deleted file mode 100644 index 1e9eb775..00000000 --- a/packages/system/backup-controller/templates/tenant-clusterroles.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# == backup view cluster role == -# Aggregated into cozy-tenant-view (and consequently use, admin, super-admin) -# Provides read-only access to all backup resources -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:backups:view - labels: - rbac.cozystack.io/aggregate-to-tenant-view: "true" -rules: -- apiGroups: ["backups.cozystack.io"] - resources: - - plans - - backupjobs - - restorejobs - - backups - - backupclasses - verbs: - - get - - list - - watch ---- -# == backup admin cluster role == -# Aggregated into cozy-tenant-admin (and consequently super-admin) -# Provides write access to plans, backupjobs, restorejobs -# Backups and backupclasses remain read-only (inherited from view) -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:backups:admin - labels: - rbac.cozystack.io/aggregate-to-tenant-admin: "true" -rules: -- apiGroups: ["backups.cozystack.io"] - resources: - - plans - - backupjobs - - restorejobs - verbs: - - create - - update - - patch - - delete diff --git a/packages/system/backup-controller/values.yaml b/packages/system/backup-controller/values.yaml index 34e033ce..d58cdc54 100644 --- a/packages/system/backup-controller/values.yaml +++ b/packages/system/backup-controller/values.yaml @@ -1,5 +1,20 @@ backupController: - image: "ghcr.io/cozystack/cozystack/backup-controller:v1.3.0@sha256:e1a083dc92f26dfef004f47c1cd20a6357174aad835004f58e751c494b76649a" + image: "ghcr.io/cozystack/cozystack/backup-controller:v1.0.0-beta.2@sha256:556cc41e4ec24c173e01c1679cf96915c7ca8c0b532b7945d461bf3797c8afbc" + replicas: 2 + debug: false + metrics: + enabled: true + bindAddress: ":8443" + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 500m + memory: 128Mi + +backupStrategyController: + image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.0.0-beta.2@sha256:5cbc85679790aa14fb55568439c669a704e29f02236df179abbb3a25c56a2aa7" replicas: 2 debug: false metrics: diff --git a/packages/system/backupstrategy-controller/Chart.yaml b/packages/system/backupstrategy-controller/Chart.yaml deleted file mode 100644 index bf556f3b..00000000 --- a/packages/system/backupstrategy-controller/Chart.yaml +++ /dev/null @@ -1,3 +0,0 @@ -apiVersion: v2 -name: cozy-backupstrategy-controller -version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/backupstrategy-controller/Makefile b/packages/system/backupstrategy-controller/Makefile deleted file mode 100644 index e6f23ca7..00000000 --- a/packages/system/backupstrategy-controller/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -NAME=backupstrategy-controller -NAMESPACE=cozy-backup-controller - -include ../../../hack/common-envs.mk -include ../../../hack/package.mk - -image: image-backupstrategy-controller - -image-backupstrategy-controller: - docker buildx build -f images/backupstrategy-controller/Dockerfile ../../.. \ - --tag $(REGISTRY)/backupstrategy-controller:$(call settag,$(TAG)) \ - --cache-from type=registry,ref=$(REGISTRY)/backupstrategy-controller:latest \ - --cache-to type=inline \ - --metadata-file images/backupstrategy-controller.json \ - $(BUILDX_ARGS) - IMAGE="$(REGISTRY)/backupstrategy-controller:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/backupstrategy-controller.json -o json -r)" \ - yq -i '.backupStrategyController.image = strenv(IMAGE)' values.yaml - rm -f images/backupstrategy-controller.json diff --git a/packages/system/backupstrategy-controller/definitions/.gitattributes b/packages/system/backupstrategy-controller/definitions/.gitattributes deleted file mode 100644 index f581feca..00000000 --- a/packages/system/backupstrategy-controller/definitions/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.yaml linguist-generated diff --git a/packages/system/backupstrategy-controller/templates/rbac.yaml b/packages/system/backupstrategy-controller/templates/rbac.yaml deleted file mode 100644 index 634ea88b..00000000 --- a/packages/system/backupstrategy-controller/templates/rbac.yaml +++ /dev/null @@ -1,82 +0,0 @@ -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: backups.cozystack.io:strategy-controller -rules: -# Strategy types (Velero, Job) -- apiGroups: ["strategy.backups.cozystack.io"] - resources: ["*"] - verbs: ["get", "list", "watch"] -# BackupClass: resolve strategy per application -- apiGroups: ["backups.cozystack.io"] - resources: ["backupclasses"] - verbs: ["get", "list", "watch"] -# BackupJob / RestoreJob: reconcile; update for RestoreJob finalizers -- apiGroups: ["backups.cozystack.io"] - resources: ["backupjobs", "restorejobs"] - verbs: ["get", "list", "watch", "update", "patch"] -- apiGroups: ["backups.cozystack.io"] - resources: ["backupjobs/status", "restorejobs/status"] - verbs: ["get", "update", "patch"] -# Backup: create after Velero job completes; update/patch for BackupReconciler finalizers -- apiGroups: ["backups.cozystack.io"] - resources: ["backups"] - verbs: ["create", "get", "list", "watch", "update", "patch"] -# Pods: BackupJob lists virt-launcher pods by label (manager cache uses cluster-scoped list/watch) -- apiGroups: [""] - resources: ["pods"] - verbs: ["get", "list", "watch"] -# ConfigMaps: controller-runtime cache requires cluster-scoped list/watch; -# create/update/delete is scoped to cozy-velero via a Role shipped by the -# velero chart (packages/system/velero/templates/backupstrategy-controller-rbac.yaml) -# so it is only created when velero is installed. -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["get", "list", "watch"] -# Application refs (e.g. VMInstance) for backup/restore scope -- apiGroups: ["apps.cozystack.io"] - resources: ["*"] - verbs: ["get", "list", "watch"] -# KubeVirt: pre-restore halts VMs and checks VMI shutdown -- apiGroups: ["kubevirt.io"] - resources: ["virtualmachines"] - verbs: ["get", "update"] -- apiGroups: ["kubevirt.io"] - resources: ["virtualmachineinstances"] - verbs: ["get"] -# CDI DataVolumes: pre-restore deletes DVs so CDI doesn't recreate PVCs after rename -- apiGroups: ["cdi.kubevirt.io"] - resources: ["datavolumes"] - verbs: ["delete"] -# HelmReleases: pre-restore suspends HRs; post-restore rename creates new HR and deletes old -- apiGroups: ["helm.toolkit.fluxcd.io"] - resources: ["helmreleases"] - verbs: ["get", "create", "update", "delete"] -# PVCs and PVs: pre-restore renames PVCs (delete old, create new) and patches PV reclaim policy -- apiGroups: [""] - resources: ["persistentvolumeclaims"] - verbs: ["get", "list", "watch", "create", "delete"] -- apiGroups: [""] - resources: ["persistentvolumes"] - verbs: ["get", "list", "watch", "update"] -# Velero Backup/Restore/DataUpload in cozy-velero namespace (DataUpload: enrich BackupJob failure messages) -- apiGroups: ["velero.io"] - resources: ["backups", "restores", "datauploads"] - verbs: ["create", "get", "list", "watch", "update", "patch", "delete", "deletecollection"] -# Velero DeleteBackupRequest: used by BackupReconciler to delete Velero backups with their storage data -- apiGroups: ["velero.io"] - resources: ["deletebackuprequests"] - verbs: ["create", "get", "list", "watch"] -# Namespaces: validate target namespace exists for cross-namespace restore -# controller-runtime cache requires list/watch for any resource accessed via r.Get() -- apiGroups: [""] - resources: ["namespaces"] - verbs: ["get", "list", "watch"] -# Events from Recorder.Event() calls -- apiGroups: [""] - resources: ["events"] - verbs: ["create", "patch"] -# Leader election (--leader-elect) -- apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["get", "list", "watch", "create", "update", "patch"] diff --git a/packages/system/backupstrategy-controller/values.yaml b/packages/system/backupstrategy-controller/values.yaml deleted file mode 100644 index d6453124..00000000 --- a/packages/system/backupstrategy-controller/values.yaml +++ /dev/null @@ -1,14 +0,0 @@ -backupStrategyController: - image: "ghcr.io/cozystack/cozystack/backupstrategy-controller:v1.3.0@sha256:be0a9ec1f4307064b16388a24628aee46e06252738338add80b99ea1e04e62bf" - replicas: 2 - debug: false - metrics: - enabled: true - bindAddress: ":8443" - resources: - requests: - cpu: 10m - memory: 64Mi - limits: - cpu: 500m - memory: 128Mi diff --git a/packages/system/bootbox-rd/cozyrds/bootbox.yaml b/packages/system/bootbox-rd/cozyrds/bootbox.yaml index 667740e3..62e87931 100644 --- a/packages/system/bootbox-rd/cozyrds/bootbox.yaml +++ b/packages/system/bootbox-rd/cozyrds/bootbox.yaml @@ -8,7 +8,7 @@ spec: plural: bootboxes singular: bootbox openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"whitelistHTTP":{"description":"Secure HTTP by enabling client networks whitelisting.","type":"boolean","default":true},"whitelist":{"description":"List of client networks.","type":"array","default":[],"items":{"type":"string"}},"machines":{"description":"Configuration of physical machine instances.","type":"array","default":[],"items":{"type":"object","required":["arch","hostname","ip","leaseTime","uefi"],"properties":{"arch":{"description":"Architecture.","type":"string"},"hostname":{"description":"Hostname.","type":"string"},"ip":{"description":"IP address configuration.","type":"object","required":["address","gateway","netmask"],"properties":{"address":{"description":"IP address.","type":"string"},"gateway":{"description":"IP gateway.","type":"string"},"netmask":{"description":"Netmask.","type":"string"}}},"leaseTime":{"description":"Lease time.","type":"integer"},"mac":{"description":"MAC addresses.","type":"array","items":{"type":"string"}},"nameServers":{"description":"Name servers.","type":"array","items":{"type":"string"}},"timeServers":{"description":"Time servers.","type":"array","items":{"type":"string"}},"uefi":{"description":"UEFI.","type":"boolean"}}}}}} + {"title":"Chart Values","type":"object","properties":{"machines":{"description":"Configuration of physical machine instances.","type":"array","default":[],"items":{"type":"object","required":["arch","hostname","ip","leaseTime","uefi"],"properties":{"arch":{"description":"Architecture.","type":"string"},"hostname":{"description":"Hostname.","type":"string"},"ip":{"description":"IP address configuration.","type":"object","required":["address","gateway","netmask"],"properties":{"address":{"description":"IP address.","type":"string"},"gateway":{"description":"IP gateway.","type":"string"},"netmask":{"description":"Netmask.","type":"string"}}},"leaseTime":{"description":"Lease time.","type":"integer"},"mac":{"description":"MAC addresses.","type":"array","items":{"type":"string"}},"nameServers":{"description":"Name servers.","type":"array","items":{"type":"string"}},"timeServers":{"description":"Time servers.","type":"array","items":{"type":"string"}},"uefi":{"description":"UEFI.","type":"boolean"}}}},"whitelist":{"description":"List of client networks.","type":"array","default":[],"items":{"type":"string"}},"whitelistHTTP":{"description":"Secure HTTP by enabling client networks whitelisting.","type":"boolean","default":true}}} release: prefix: "" labels: diff --git a/packages/system/bucket-rd/cozyrds/bucket.yaml b/packages/system/bucket-rd/cozyrds/bucket.yaml index 7eab56b6..2a19f89e 100644 --- a/packages/system/bucket-rd/cozyrds/bucket.yaml +++ b/packages/system/bucket-rd/cozyrds/bucket.yaml @@ -8,7 +8,7 @@ spec: plural: buckets singular: bucket openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"locking":{"description":"Provisions bucket from the `-lock` BucketClass (with object lock enabled).","type":"boolean","default":false},"storagePool":{"description":"Selects a specific BucketClass by storage pool name.","type":"string","default":""},"users":{"description":"Users configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"readonly":{"description":"Whether the user has read-only access.","type":"boolean"}}}}}} + {"title":"Chart Values","type":"object","properties":{}} release: prefix: bucket- labels: @@ -26,14 +26,13 @@ spec: tags: - storage icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl82ODNfMzA5MSkiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03MiAzMC4xNjQxTDExNy45ODMgMzYuNzc4OVY0MC42NzM5QzExNy45ODMgNDYuNDY1MyA5Ny4zODYyIDUxLjEzMzIgNzEuOTgyNyA1MS4xMzMyQzQ2LjU3OTIgNTEuMTMzMiAyNiA0Ni40NjUzIDI2IDQwLjY3MzlWMzYuNDQzMUw3MiAzMC4xNjQxWk03MiA1OC4yNjc4QzkxLjIwODQgNTguMjY3OCAxMDcuNjU4IDU1LjU5ODYgMTE0LjU0NyA1MS44MDQ4TDExNi44MDMgNDguMTExTDExNy43MjMgNDQuNzUzVjQ4LjkxNzFMMTAyLjY3OSAxMTEuMDMzQzEwMi42NzkgMTE0Ljg5NSA4OC45NTMzIDExOCA3Mi4wMTcyIDExOEM1NS4wODEyIDExOCA0MS4zNzQzIDExNC44OTUgNDEuMzc0MyAxMTEuMDMzTDI2LjMzIDQ4LjkxNzFWNDQuODM2OUwyOS44MDA3IDUxLjkzODJDMzYuNzA2NSA1NS42NjUzIDUyLjk5OTcgNTguMjY3OCA3MiA1OC4yNjc4WiIgZmlsbD0iIzhDMzEyMyIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcyLjAwMDMgMjZDOTcuNDAzOCAyNiAxMTggMzAuNjgzOSAxMTggMzYuNDQyQzExOCA0Mi4yIDk3LjM4NjYgNDYuODUwNyA3Mi4wMDAzIDQ2Ljg1MDdDNDYuNjE0MSA0Ni44NTA3IDI2LjAxNzYgNDIuMjM0NSAyNi4wMTc2IDM2LjQ0MkMyNi4wMTc2IDMwLjY0OTQgNDYuNTk2OCAyNiA3Mi4wMDAzIDI2Wk03Mi4wMDAzIDU0LjEwMzdDOTUuNjg1NyA1NC4xMDM3IDExNS4xNzIgNTAuMDU4IDExNy43MDYgNDQuODE5N0wxMDIuNjYyIDEwNi45MzdDMTAyLjY2MiAxMTAuNzk5IDg4LjkzNjQgMTEzLjkwNSA3Mi4wMDAzIDExMy45MDVDNTUuMDY0MyAxMTMuOTA1IDQxLjMzOSAxMTAuODE2IDQxLjMzOSAxMDYuOTU0TDI2LjI5NTkgNDQuODM3QzI4Ljg0NjYgNTAuMDU4IDQ4LjMzMzMgNTQuMTAzNyA3Mi4wMDAzIDU0LjEwMzdaIiBmaWxsPSIjRTA1MjQzIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNjEuMTcyNSA2MC4wMjkzSDgxLjA5MjhWNzkuMTY3Nkg2MS4xNzI1VjYwLjAyOTNaTTQ1LjMzMDEgOTUuMzY4OEM0NS4zMzAxIDkwLjE0MiA0OS43MTA0IDg1LjkzNDIgNTUuMTUxMSA4NS45MzQyQzYwLjU5MTcgODUuOTM0MiA2NC45NzIxIDkwLjE0MiA2NC45NzIxIDk1LjM2ODhDNjQuOTcyMSAxMDAuNTk2IDYwLjU5MTcgMTA0LjgwMyA1NS4xNTExIDEwNC44MDNDNDkuNzEwNCAxMDQuODAzIDQ1LjMzMDEgMTAwLjU5NiA0NS4zMzAxIDk1LjM2ODhaTTk2LjQ0ODcgMTA0LjM2OEg3Ni43NzIyTDg2LjYxMDUgODYuNzczN0w5Ni40NDg3IDEwNC4zNjhaIiBmaWxsPSJ3aGl0ZSIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzY4M18zMDkxIiB4MT0iMCIgeTE9IjAiIHgyPSIxNTEiIHkyPSIxODAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRjBFRSIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNFQzg4N0QiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K - keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "locking"], ["spec", "storagePool"], ["spec", "users"]] + keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"]] secrets: exclude: [] include: - resourceNames: + - bucket-{{ .name }} - bucket-{{ .name }}-credentials - - matchLabels: - apps.cozystack.io/user-secret: "true" ingresses: exclude: [] include: diff --git a/packages/system/bucket/images/s3manager.tag b/packages/system/bucket/images/s3manager.tag index 889db0af..8ef294d1 100644 --- a/packages/system/bucket/images/s3manager.tag +++ b/packages/system/bucket/images/s3manager.tag @@ -1 +1 @@ -ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:fb65e734bbdbdaef2238769cc2ecfb54dbddaf1e0952ad438a9b3e26b9dbb4b5 +ghcr.io/cozystack/cozystack/s3manager:v0.5.0@sha256:3013e13ba967070948653cc5b913a920dea93a24370b10731fafcfd8fb6a21b0 diff --git a/packages/system/bucket/images/s3manager/Dockerfile b/packages/system/bucket/images/s3manager/Dockerfile index e97adf07..179acead 100644 --- a/packages/system/bucket/images/s3manager/Dockerfile +++ b/packages/system/bucket/images/s3manager/Dockerfile @@ -9,7 +9,6 @@ WORKDIR /usr/src/app RUN wget -O- https://github.com/cloudlena/s3manager/archive/9a7c8e446b422f8973b8c461990f39fdafee9c27.tar.gz | tar -xzf- --strip 1 ADD cozystack.patch / RUN git apply /cozystack.patch -RUN go mod tidy RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags="-s -w" -a -installsuffix cgo -o bin/s3manager FROM docker.io/library/alpine:latest diff --git a/packages/system/bucket/images/s3manager/cozystack.patch b/packages/system/bucket/images/s3manager/cozystack.patch index 2f569042..f631b144 100644 --- a/packages/system/bucket/images/s3manager/cozystack.patch +++ b/packages/system/bucket/images/s3manager/cozystack.patch @@ -1,235 +1,3 @@ -diff --git a/go.mod b/go.mod -index b5d8540..6ede8e8 100644 ---- a/go.mod -+++ b/go.mod -@@ -1,10 +1,11 @@ - module github.com/cloudlena/s3manager - --go 1.22.5 -+go 1.23 - - require ( - github.com/cloudlena/adapters v0.0.0-20240708203353-a39be02cc801 - github.com/gorilla/mux v1.8.1 -+ github.com/gorilla/sessions v1.4.0 - github.com/matryer/is v1.4.1 - github.com/minio/minio-go/v7 v7.0.74 - github.com/spf13/viper v1.19.0 -@@ -16,6 +17,7 @@ require ( - github.com/go-ini/ini v1.67.0 // indirect - github.com/goccy/go-json v0.10.3 // indirect - github.com/google/uuid v1.6.0 // indirect -+ github.com/gorilla/securecookie v1.1.2 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/klauspost/compress v1.17.9 // indirect - github.com/klauspost/cpuid/v2 v2.2.8 // indirect -diff --git a/go.sum b/go.sum -index 1ea1b16..d7866ce 100644 ---- a/go.sum -+++ b/go.sum -@@ -16,10 +16,16 @@ github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= - github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= - github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= - github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= - github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= - github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= - github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= - github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -+github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= -+github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= -+github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= -+github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= - github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= - github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= - github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -diff --git a/main.go b/main.go -index 2ffe8ab..723a1b8 100644 ---- a/main.go -+++ b/main.go -@@ -41,10 +41,12 @@ type configuration struct { - Timeout int32 - SseType string - SseKey string -+ LoginMode bool - } - - func parseConfiguration() configuration { - var accessKeyID, secretAccessKey, iamEndpoint string -+ var loginMode bool - - viper.AutomaticEnv() - -@@ -57,13 +59,10 @@ func parseConfiguration() configuration { - iamEndpoint = viper.GetString("IAM_ENDPOINT") - } else { - accessKeyID = viper.GetString("ACCESS_KEY_ID") -- if len(accessKeyID) == 0 { -- log.Fatal("please provide ACCESS_KEY_ID") -- } -- - secretAccessKey = viper.GetString("SECRET_ACCESS_KEY") -- if len(secretAccessKey) == 0 { -- log.Fatal("please provide SECRET_ACCESS_KEY") -+ if len(accessKeyID) == 0 || len(secretAccessKey) == 0 { -+ log.Println("ACCESS_KEY_ID or SECRET_ACCESS_KEY not set, starting in login mode") -+ loginMode = true - } - } - -@@ -115,6 +114,7 @@ func parseConfiguration() configuration { - Timeout: timeout, - SseType: sseType, - SseKey: sseKey, -+ LoginMode: loginMode, - } - } - -@@ -135,57 +135,96 @@ func main() { - log.Fatal(err) - } - -- // Set up S3 client -- opts := &minio.Options{ -- Secure: configuration.UseSSL, -- } -- if configuration.UseIam { -- opts.Creds = credentials.NewIAM(configuration.IamEndpoint) -- } else { -- var signatureType credentials.SignatureType -- -- switch configuration.SignatureType { -- case "V2": -- signatureType = credentials.SignatureV2 -- case "V4": -- signatureType = credentials.SignatureV4 -- case "V4Streaming": -- signatureType = credentials.SignatureV4Streaming -- case "Anonymous": -- signatureType = credentials.SignatureAnonymous -- default: -- log.Fatalf("Invalid SIGNATURE_TYPE: %s", configuration.SignatureType) -+ // Set up router -+ r := mux.NewRouter() -+ r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.FS(statics)))).Methods(http.MethodGet) -+ -+ if configuration.LoginMode { -+ // Login mode: no pre-configured S3 client, per-session credentials -+ sessionCfg := &s3manager.SessionConfig{ -+ Store: s3manager.NewSessionStore(), -+ Endpoint: configuration.Endpoint, -+ UseSSL: configuration.UseSSL, -+ SkipSSLVerify: configuration.SkipSSLVerification, -+ AllowDelete: configuration.AllowDelete, -+ ForceDownload: configuration.ForceDownload, -+ ListRecursive: configuration.ListRecursive, -+ SseInfo: sseType, -+ Templates: templates, - } - -- opts.Creds = credentials.NewStatic(configuration.AccessKeyID, configuration.SecretAccessKey, "", signatureType) -- } -+ // Public routes (no auth required) -+ r.Handle("/login", s3manager.HandleLoginView(templates)).Methods(http.MethodGet) -+ r.Handle("/login", s3manager.HandleLogin(sessionCfg)).Methods(http.MethodPost) -+ r.Handle("/logout", s3manager.HandleLogout(sessionCfg)).Methods(http.MethodPost) -+ -+ // Protected routes (auth required via middleware) -+ protected := mux.NewRouter() -+ protected.Handle("/", http.RedirectHandler("/buckets", http.StatusPermanentRedirect)).Methods(http.MethodGet) -+ protected.Handle("/buckets", s3manager.HandleBucketsViewDynamic(templates, configuration.AllowDelete)).Methods(http.MethodGet) -+ protected.PathPrefix("/buckets/").Handler(s3manager.HandleBucketViewDynamic(templates, configuration.AllowDelete, configuration.ListRecursive)).Methods(http.MethodGet) -+ protected.Handle("/api/buckets", s3manager.HandleCreateBucketDynamic()).Methods(http.MethodPost) -+ if configuration.AllowDelete { -+ protected.Handle("/api/buckets/{bucketName}", s3manager.HandleDeleteBucketDynamic()).Methods(http.MethodDelete) -+ } -+ protected.Handle("/api/buckets/{bucketName}/objects", s3manager.HandleCreateObjectDynamic(sseType)).Methods(http.MethodPost) -+ protected.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}/url", s3manager.HandleGenerateUrlDynamic()).Methods(http.MethodGet) -+ protected.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}", s3manager.HandleGetObjectDynamic(configuration.ForceDownload)).Methods(http.MethodGet) -+ if configuration.AllowDelete { -+ protected.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}", s3manager.HandleDeleteObjectDynamic()).Methods(http.MethodDelete) -+ } - -- if configuration.Region != "" { -- opts.Region = configuration.Region -- } -- if configuration.UseSSL && configuration.SkipSSLVerification { -- opts.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} //nolint:gosec -- } -- s3, err := minio.New(configuration.Endpoint, opts) -- if err != nil { -- log.Fatalln(fmt.Errorf("error creating s3 client: %w", err)) -- } -+ r.PathPrefix("/").Handler(s3manager.RequireAuth(sessionCfg, protected)) -+ } else { -+ // Pre-configured mode: existing behavior with static S3 client -+ opts := &minio.Options{ -+ Secure: configuration.UseSSL, -+ } -+ if configuration.UseIam { -+ opts.Creds = credentials.NewIAM(configuration.IamEndpoint) -+ } else { -+ var signatureType credentials.SignatureType -+ -+ switch configuration.SignatureType { -+ case "V2": -+ signatureType = credentials.SignatureV2 -+ case "V4": -+ signatureType = credentials.SignatureV4 -+ case "V4Streaming": -+ signatureType = credentials.SignatureV4Streaming -+ case "Anonymous": -+ signatureType = credentials.SignatureAnonymous -+ default: -+ log.Fatalf("Invalid SIGNATURE_TYPE: %s", configuration.SignatureType) -+ } -+ -+ opts.Creds = credentials.NewStatic(configuration.AccessKeyID, configuration.SecretAccessKey, "", signatureType) -+ } - -- // Set up router -- r := mux.NewRouter() -- r.Handle("/", http.RedirectHandler("/buckets", http.StatusPermanentRedirect)).Methods(http.MethodGet) -- r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.FS(statics)))).Methods(http.MethodGet) -- r.Handle("/buckets", s3manager.HandleBucketsView(s3, templates, configuration.AllowDelete)).Methods(http.MethodGet) -- r.PathPrefix("/buckets/").Handler(s3manager.HandleBucketView(s3, templates, configuration.AllowDelete, configuration.ListRecursive)).Methods(http.MethodGet) -- r.Handle("/api/buckets", s3manager.HandleCreateBucket(s3)).Methods(http.MethodPost) -- if configuration.AllowDelete { -- r.Handle("/api/buckets/{bucketName}", s3manager.HandleDeleteBucket(s3)).Methods(http.MethodDelete) -- } -- r.Handle("/api/buckets/{bucketName}/objects", s3manager.HandleCreateObject(s3, sseType)).Methods(http.MethodPost) -- r.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}/url", s3manager.HandleGenerateUrl(s3)).Methods(http.MethodGet) -- r.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}", s3manager.HandleGetObject(s3, configuration.ForceDownload)).Methods(http.MethodGet) -- if configuration.AllowDelete { -- r.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}", s3manager.HandleDeleteObject(s3)).Methods(http.MethodDelete) -+ if configuration.Region != "" { -+ opts.Region = configuration.Region -+ } -+ if configuration.UseSSL && configuration.SkipSSLVerification { -+ opts.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} //nolint:gosec -+ } -+ s3, err := minio.New(configuration.Endpoint, opts) -+ if err != nil { -+ log.Fatalln(fmt.Errorf("error creating s3 client: %w", err)) -+ } -+ -+ r.Handle("/", http.RedirectHandler("/buckets", http.StatusPermanentRedirect)).Methods(http.MethodGet) -+ r.Handle("/buckets", s3manager.HandleBucketsView(s3, templates, configuration.AllowDelete)).Methods(http.MethodGet) -+ r.PathPrefix("/buckets/").Handler(s3manager.HandleBucketView(s3, templates, configuration.AllowDelete, configuration.ListRecursive)).Methods(http.MethodGet) -+ r.Handle("/api/buckets", s3manager.HandleCreateBucket(s3)).Methods(http.MethodPost) -+ if configuration.AllowDelete { -+ r.Handle("/api/buckets/{bucketName}", s3manager.HandleDeleteBucket(s3)).Methods(http.MethodDelete) -+ } -+ r.Handle("/api/buckets/{bucketName}/objects", s3manager.HandleCreateObject(s3, sseType)).Methods(http.MethodPost) -+ r.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}/url", s3manager.HandleGenerateUrl(s3)).Methods(http.MethodGet) -+ r.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}", s3manager.HandleGetObject(s3, configuration.ForceDownload)).Methods(http.MethodGet) -+ if configuration.AllowDelete { -+ r.Handle("/api/buckets/{bucketName}/objects/{objectName:.*}", s3manager.HandleDeleteObject(s3)).Methods(http.MethodDelete) -+ } - } - - lr := logging.Handler(os.Stdout)(r) diff --git a/web/template/bucket.html.tmpl b/web/template/bucket.html.tmpl index e2f8d28..87add13 100644 --- a/web/template/bucket.html.tmpl @@ -256,298 +24,3 @@ index c7ea184..fb1dce7 100644 -diff --git a/internal/app/s3manager/auth.go b/internal/app/s3manager/auth.go -new file mode 100644 -index 0000000..58589e2 ---- /dev/null -+++ b/internal/app/s3manager/auth.go -@@ -0,0 +1,237 @@ -+package s3manager -+ -+import ( -+ "context" -+ "crypto/rand" -+ "crypto/tls" -+ "fmt" -+ "html/template" -+ "io/fs" -+ "log" -+ "net/http" -+ -+ "github.com/gorilla/sessions" -+ "github.com/minio/minio-go/v7" -+ "github.com/minio/minio-go/v7/pkg/credentials" -+) -+ -+type contextKey string -+ -+const s3ContextKey contextKey = "s3client" -+ -+// SessionConfig holds session store and S3 connection settings for login mode. -+type SessionConfig struct { -+ Store *sessions.CookieStore -+ Endpoint string -+ UseSSL bool -+ SkipSSLVerify bool -+ AllowDelete bool -+ ForceDownload bool -+ ListRecursive bool -+ SseInfo SSEType -+ Templates fs.FS -+} -+ -+// NewSessionStore creates a CookieStore with a random encryption key. -+func NewSessionStore() *sessions.CookieStore { -+ key := make([]byte, 32) -+ if _, err := rand.Read(key); err != nil { -+ log.Fatal("failed to generate session key:", err) -+ } -+ store := sessions.NewCookieStore(key) -+ store.Options = &sessions.Options{ -+ Path: "/", -+ MaxAge: 86400, -+ HttpOnly: true, -+ Secure: true, -+ SameSite: http.SameSiteLaxMode, -+ } -+ return store -+} -+ -+// NewS3Client creates a minio client from user-provided credentials. -+func NewS3Client(endpoint, accessKey, secretKey string, useSSL, skipSSLVerify bool) (*minio.Client, error) { -+ opts := &minio.Options{ -+ Creds: credentials.NewStaticV4(accessKey, secretKey, ""), -+ Secure: useSSL, -+ } -+ if useSSL && skipSSLVerify { -+ opts.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} //nolint:gosec -+ } -+ return minio.New(endpoint, opts) -+} -+ -+// S3FromContext retrieves the S3 client stored in request context. -+func S3FromContext(ctx context.Context) S3 { -+ if s3, ok := ctx.Value(s3ContextKey).(S3); ok { -+ return s3 -+ } -+ return nil -+} -+ -+func contextWithS3(ctx context.Context, s3 S3) context.Context { -+ return context.WithValue(ctx, s3ContextKey, s3) -+} -+ -+// RequireAuth is middleware that validates session credentials and injects -+// an S3 client into the request context. Redirects to /login if no session. -+func RequireAuth(cfg *SessionConfig, next http.Handler) http.Handler { -+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ session, _ := cfg.Store.Get(r, "s3session") -+ accessKey, ok1 := session.Values["accessKey"].(string) -+ secretKey, ok2 := session.Values["secretKey"].(string) -+ if !ok1 || !ok2 || accessKey == "" || secretKey == "" { -+ http.Redirect(w, r, "/login", http.StatusFound) -+ return -+ } -+ -+ s3, err := NewS3Client(cfg.Endpoint, accessKey, secretKey, cfg.UseSSL, cfg.SkipSSLVerify) -+ if err != nil { -+ // Session has bad credentials — clear and redirect to login -+ session.Options.MaxAge = -1 -+ _ = session.Save(r, w) -+ http.Redirect(w, r, "/login", http.StatusFound) -+ return -+ } -+ -+ ctx := contextWithS3(r.Context(), s3) -+ next.ServeHTTP(w, r.WithContext(ctx)) -+ }) -+} -+ -+// HandleLoginView renders the login page. -+func HandleLoginView(templates fs.FS) http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ errorMsg := r.URL.Query().Get("error") -+ -+ data := struct { -+ Error string -+ }{ -+ Error: errorMsg, -+ } -+ -+ t, err := template.ParseFS(templates, "layout.html.tmpl", "login.html.tmpl") -+ if err != nil { -+ handleHTTPError(w, fmt.Errorf("error parsing login template: %w", err)) -+ return -+ } -+ err = t.ExecuteTemplate(w, "layout", data) -+ if err != nil { -+ handleHTTPError(w, fmt.Errorf("error executing login template: %w", err)) -+ return -+ } -+ } -+} -+ -+// HandleLogin processes the login form POST. -+func HandleLogin(cfg *SessionConfig) http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ accessKey := r.FormValue("accessKey") -+ secretKey := r.FormValue("secretKey") -+ -+ if accessKey == "" || secretKey == "" { -+ http.Redirect(w, r, "/login?error=credentials+required", http.StatusFound) -+ return -+ } -+ -+ // Validate credentials by attempting ListBuckets -+ s3, err := NewS3Client(cfg.Endpoint, accessKey, secretKey, cfg.UseSSL, cfg.SkipSSLVerify) -+ if err != nil { -+ http.Redirect(w, r, "/login?error=connection+failed", http.StatusFound) -+ return -+ } -+ _, err = s3.ListBuckets(r.Context()) -+ if err != nil { -+ http.Redirect(w, r, "/login?error=invalid+credentials", http.StatusFound) -+ return -+ } -+ -+ // Save credentials to session -+ session, _ := cfg.Store.Get(r, "s3session") -+ session.Values["accessKey"] = accessKey -+ session.Values["secretKey"] = secretKey -+ err = session.Save(r, w) -+ if err != nil { -+ handleHTTPError(w, fmt.Errorf("error saving session: %w", err)) -+ return -+ } -+ -+ http.Redirect(w, r, "/buckets", http.StatusFound) -+ } -+} -+ -+// HandleLogout destroys the session and redirects to login. -+func HandleLogout(cfg *SessionConfig) http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ session, _ := cfg.Store.Get(r, "s3session") -+ session.Options.MaxAge = -1 -+ _ = session.Save(r, w) -+ http.Redirect(w, r, "/login", http.StatusFound) -+ } -+} -+ -+// Dynamic handler wrappers — extract S3 from context, delegate to original handlers. -+ -+// HandleBucketsViewDynamic wraps HandleBucketsView for login mode. -+func HandleBucketsViewDynamic(templates fs.FS, allowDelete bool) http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleBucketsView(s3, templates, allowDelete).ServeHTTP(w, r) -+ } -+} -+ -+// HandleBucketViewDynamic wraps HandleBucketView for login mode. -+func HandleBucketViewDynamic(templates fs.FS, allowDelete bool, listRecursive bool) http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleBucketView(s3, templates, allowDelete, listRecursive).ServeHTTP(w, r) -+ } -+} -+ -+// HandleCreateBucketDynamic wraps HandleCreateBucket for login mode. -+func HandleCreateBucketDynamic() http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleCreateBucket(s3).ServeHTTP(w, r) -+ } -+} -+ -+// HandleDeleteBucketDynamic wraps HandleDeleteBucket for login mode. -+func HandleDeleteBucketDynamic() http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleDeleteBucket(s3).ServeHTTP(w, r) -+ } -+} -+ -+// HandleCreateObjectDynamic wraps HandleCreateObject for login mode. -+func HandleCreateObjectDynamic(sseInfo SSEType) http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleCreateObject(s3, sseInfo).ServeHTTP(w, r) -+ } -+} -+ -+// HandleGenerateUrlDynamic wraps HandleGenerateUrl for login mode. -+func HandleGenerateUrlDynamic() http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleGenerateUrl(s3).ServeHTTP(w, r) -+ } -+} -+ -+// HandleGetObjectDynamic wraps HandleGetObject for login mode. -+func HandleGetObjectDynamic(forceDownload bool) http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleGetObject(s3, forceDownload).ServeHTTP(w, r) -+ } -+} -+ -+// HandleDeleteObjectDynamic wraps HandleDeleteObject for login mode. -+func HandleDeleteObjectDynamic() http.HandlerFunc { -+ return func(w http.ResponseWriter, r *http.Request) { -+ s3 := S3FromContext(r.Context()) -+ HandleDeleteObject(s3).ServeHTTP(w, r) -+ } -+} -diff --git a/web/template/login.html.tmpl b/web/template/login.html.tmpl -new file mode 100644 -index 0000000..f153018 ---- /dev/null -+++ b/web/template/login.html.tmpl -@@ -0,0 +1,46 @@ -+{{ define "content" }} -+ -+ -+
-+
-+
-+
-+
-+
-+ Sign In -+

Enter your S3 credentials to access the bucket manager.

-+
-+ -+ {{ if .Error }} -+
-+ error {{ .Error }} -+
-+ {{ end }} -+ -+
-+
-+ vpn_key -+ -+ -+
-+
-+ lock -+ -+ -+
-+
-+ -+ -+
-+
-+
-+
-+
-+
-+{{ end }} diff --git a/packages/system/bucket/templates/deployment.yaml b/packages/system/bucket/templates/deployment.yaml index 5c13cb2d..7e115de0 100644 --- a/packages/system/bucket/templates/deployment.yaml +++ b/packages/system/bucket/templates/deployment.yaml @@ -1,12 +1,3 @@ -{{- $endpoint := printf "s3.%s" .Values._namespace.host }} -{{- range $name, $user := .Values.users }} - {{- $secretName := printf "%s-%s" $.Values.bucketName $name }} - {{- $existingSecret := lookup "v1" "Secret" $.Release.Namespace $secretName }} - {{- if $existingSecret }} - {{- $bucketInfo := fromJson (b64dec (index $existingSecret.data "BucketInfo")) }} - {{- $endpoint = trimPrefix "https://" (index $bucketInfo.spec.secretS3 "endpoint") }} - {{- end }} -{{- end }} apiVersion: apps/v1 kind: Deployment metadata: @@ -26,6 +17,19 @@ spec: image: "{{ $.Files.Get "images/s3manager.tag" | trim }}" env: - name: ENDPOINT - value: {{ $endpoint | quote }} + valueFrom: + secretKeyRef: + name: {{ .Values.bucketName }}-credentials + key: endpoint - name: SKIP_SSL_VERIFICATION value: "true" + - name: ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .Values.bucketName }}-credentials + key: accessKey + - name: SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.bucketName }}-credentials + key: secretKey diff --git a/packages/system/bucket/templates/ingress.yaml b/packages/system/bucket/templates/ingress.yaml index b7ffaf8b..f7b4eed4 100644 --- a/packages/system/bucket/templates/ingress.yaml +++ b/packages/system/bucket/templates/ingress.yaml @@ -1,20 +1,22 @@ {{- $host := .Values._namespace.host }} {{- $ingress := .Values._namespace.ingress }} -{{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $clusterIssuer := (index .Values._cluster "issuer-name") | default "letsencrypt-prod" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ .Values.bucketName }}-ui annotations: + nginx.ingress.kubernetes.io/auth-type: "basic" + nginx.ingress.kubernetes.io/auth-secret: "{{ .Values.bucketName }}-ui-auth" + nginx.ingress.kubernetes.io/auth-realm: "Authentication Required" nginx.ingress.kubernetes.io/proxy-body-size: "0" nginx.ingress.kubernetes.io/proxy-read-timeout: "99999" nginx.ingress.kubernetes.io/proxy-send-timeout: "99999" - {{- if eq $solver "http01" }} - acme.cert-manager.io/http01-ingress-ingressclassname: {{ $ingress }} + {{- if ne $issuerType "cloudflare" }} + acme.cert-manager.io/http01-ingress-class: {{ $ingress }} {{- end }} - cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + cert-manager.io/cluster-issuer: letsencrypt-prod spec: ingressClassName: {{ $ingress }} tls: diff --git a/packages/system/bucket/templates/secret.yaml b/packages/system/bucket/templates/secret.yaml index 683a0972..15474569 100644 --- a/packages/system/bucket/templates/secret.yaml +++ b/packages/system/bucket/templates/secret.yaml @@ -1,2 +1,24 @@ -{{/* Secrets previously used for s3manager credential injection and nginx basic auth */}} -{{/* are no longer needed — s3manager now handles authentication via its own login page */}} +{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace .Values.bucketName }} +{{- $bucketInfo := fromJson (b64dec (index $existingSecret.data "BucketInfo")) }} +{{- $accessKeyID := index $bucketInfo.spec.secretS3 "accessKeyID" }} +{{- $accessSecretKey := index $bucketInfo.spec.secretS3 "accessSecretKey" }} +{{- $endpoint := index $bucketInfo.spec.secretS3 "endpoint" }} +{{- $bucketName := index $bucketInfo.spec "bucketName" }} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.bucketName }}-credentials +type: Opaque +stringData: + accessKey: {{ $accessKeyID | quote }} + secretKey: {{ $accessSecretKey | quote }} + endpoint: {{ trimPrefix "https://" $endpoint }} + bucketName: {{ $bucketName | quote }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.bucketName }}-ui-auth +data: + auth: {{ htpasswd $accessKeyID $accessSecretKey | b64enc | quote }} diff --git a/packages/system/bucket/templates/user-credentials.yaml b/packages/system/bucket/templates/user-credentials.yaml deleted file mode 100644 index 7ccdd731..00000000 --- a/packages/system/bucket/templates/user-credentials.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- range $name, $user := .Values.users }} -{{- $secretName := printf "%s-%s" $.Values.bucketName $name }} -{{- $existingSecret := lookup "v1" "Secret" $.Release.Namespace $secretName }} -{{- if $existingSecret }} -{{- $bucketInfo := fromJson (b64dec (index $existingSecret.data "BucketInfo")) }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ $secretName }}-credentials - labels: - apps.cozystack.io/user-secret: "true" -type: Opaque -stringData: - accessKey: {{ index $bucketInfo.spec.secretS3 "accessKeyID" | quote }} - secretKey: {{ index $bucketInfo.spec.secretS3 "accessSecretKey" | quote }} - endpoint: {{ trimPrefix "https://" (index $bucketInfo.spec.secretS3 "endpoint") }} - bucketName: {{ index $bucketInfo.spec "bucketName" | quote }} -{{- end }} -{{- end }} diff --git a/packages/system/bucket/values.yaml b/packages/system/bucket/values.yaml index 739c4977..e1499c6e 100644 --- a/packages/system/bucket/values.yaml +++ b/packages/system/bucket/values.yaml @@ -1,2 +1 @@ bucketName: "cozystack" -users: {} diff --git a/packages/system/capi-providers-cpprovider/files/components.gz b/packages/system/capi-providers-cpprovider/files/components.gz index 930a26af..60ac302a 100644 Binary files a/packages/system/capi-providers-cpprovider/files/components.gz and b/packages/system/capi-providers-cpprovider/files/components.gz differ diff --git a/packages/system/capi-providers-cpprovider/files/control-plane-components.yaml b/packages/system/capi-providers-cpprovider/files/control-plane-components.yaml index 64fc7d6d..d30e7373 100644 --- a/packages/system/capi-providers-cpprovider/files/control-plane-components.yaml +++ b/packages/system/capi-providers-cpprovider/files/control-plane-components.yaml @@ -109,7 +109,7 @@ spec: agent: default: image: registry.k8s.io/kas-network-proxy/proxy-agent - mode: DaemonSet + version: v0.28.6 properties: extraArgs: description: |- @@ -120,31 +120,10 @@ spec: items: type: string type: array - hostNetwork: - default: false - description: |- - HostNetwork enables the konnectivity agent to use the Host network namespace. - By enabling this mode, the Agent doesn't need to wait for the CNI initialisation, - enabling a sort of out-of-band access to nodes for troubleshooting scenarios, - or when the agent needs direct access to the host network. - type: boolean image: default: registry.k8s.io/kas-network-proxy/proxy-agent description: AgentImage defines the container image for Konnectivity's agent. type: string - mode: - default: DaemonSet - description: 'Mode allows specifying the Agent deployment mode: Deployment, or DaemonSet (default).' - enum: - - DaemonSet - - Deployment - type: string - replicas: - description: |- - Replicas defines the number of replicas when Mode is Deployment. - Must be 0 if Mode is DaemonSet. - format: int32 - type: integer tolerations: default: - key: CriticalAddonsOnly @@ -190,20 +169,15 @@ spec: type: object type: array version: - description: |- - Version for Konnectivity agent. - If left empty, Kamaji will automatically inflect the version from the deployed Tenant Control Plane. - - WARNING: for last cut-off releases, the container image could be not available. + default: v0.28.6 + description: Version for Konnectivity agent. type: string type: object - x-kubernetes-validations: - - message: replicas must be 0 when mode is DaemonSet, and greater than 0 when mode is Deployment - rule: '!(self.mode == ''DaemonSet'' && has(self.replicas) && self.replicas != 0) && !(self.mode == ''Deployment'' && self.replicas == 0)' server: default: image: registry.k8s.io/kas-network-proxy/proxy-server port: 8132 + version: v0.28.6 properties: extraArgs: description: |- @@ -230,7 +204,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -282,11 +256,8 @@ spec: type: object type: object version: - description: |- - Container image version of the Konnectivity server. - If left empty, Kamaji will automatically inflect the version from the deployed Tenant Control Plane. - - WARNING: for last cut-off releases, the container image could be not available. + default: v0.28.6 + description: Container image version of the Konnectivity server. type: string required: - port @@ -439,7 +410,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -589,7 +560,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -649,16 +620,6 @@ spec: dataStoreSchema: description: DataStoreSchema allows to specify the name of the database (for relational DataStores) or the key prefix (for etcd) type: string - dataStoreUsername: - description: |- - DataStoreUsername allows to specify the username of the database (for relational DataStores). This - value is optional and immutable. Note that Kamaji currently doesn't ensure that DataStoreUsername values are unique. It's up - to the user to avoid clashes between different TenantControlPlanes. If not set upon creation, Kamaji will default the - DataStoreUsername by concatenating the namespace and name of the TenantControlPlane. - type: string - x-kubernetes-validations: - - message: changing the dataStoreUsername is not supported - rule: self == oldSelf deployment: description: Configure how the TenantControlPlane Deployment object should be configured. properties: @@ -942,6 +903,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -956,6 +918,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1116,6 +1079,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1130,6 +1094,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1218,8 +1183,8 @@ spec: 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 + 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) @@ -1283,6 +1248,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1297,6 +1263,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1457,6 +1424,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1471,6 +1439,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1618,9 +1587,7 @@ spec: description: EnvVar represents an environment variable present in a Container. properties: name: - description: |- - Name of the environment variable. - May consist of any printable ASCII characters except '='. + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: |- @@ -1674,42 +1641,6 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic - fileKeyRef: - description: |- - FileKeyRef selects a key of the env file. - Requires the EnvFiles feature gate to be enabled. - properties: - key: - description: |- - The key within the env file. An invalid key will prevent the pod from starting. - The keys defined within a source may consist of any printable ASCII characters except '='. - During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. - type: string - optional: - default: false - description: |- - Specify whether the file or its key must be defined. If the file or key - does not exist, then the env var is not published. - If optional is set to true and the specified key does not exist, - the environment variable will not be set in the Pod's containers. - - If optional is set to false and the specified key does not exist, - an error will be returned during Pod creation. - type: boolean - path: - description: |- - The path within the volume from which to select the file. - Must be relative and may not contain the '..' path or start with '..'. - type: string - volumeName: - description: The name of the volume mount containing the env file. - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1765,13 +1696,13 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source may consist of any printable ASCII characters except '='. - When a key exists in multiple + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: - description: EnvFromSource represents the source of a set of ConfigMaps or Secrets + description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: The ConfigMap to select from @@ -1791,9 +1722,7 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: |- - Optional text to prepend to the name of each environment variable. - May consist of any printable ASCII characters except '='. + description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -2042,12 +1971,6 @@ spec: - port type: object type: object - stopSignal: - description: |- - StopSignal defines which signal will be sent to a container when it is being stopped. - If not specified, the default is defined by the container runtime in use. - StopSignal can only be set for Pods with a non-empty .spec.os.name - type: string type: object livenessProbe: description: |- @@ -2438,7 +2361,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2492,10 +2415,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This overrides the pod-level restart policy. When this field is not specified, + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Additionally, setting the RestartPolicy as "Always" for the init container will - have the following effect: + Setting the RestartPolicy as "Always" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -2507,57 +2430,6 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string - restartPolicyRules: - description: |- - Represents a list of rules to be checked to determine if the - container should be restarted on exit. The rules are evaluated in - order. Once a rule matches a container exit condition, the remaining - rules are ignored. If no rule matches the container exit condition, - the Container-level restart policy determines the whether the container - is restarted or not. Constraints on the rules: - - At most 20 rules are allowed. - - Rules can have the same action. - - Identical rules are not forbidden in validations. - When rules are specified, container MUST set RestartPolicy explicitly - even it if matches the Pod's RestartPolicy. - items: - description: ContainerRestartRule describes how a container exit is handled. - properties: - action: - description: |- - Specifies the action taken on a container exit if the requirements - are satisfied. The only possible value is "Restart" to restart the - container. - type: string - exitCodes: - description: Represents the exit codes to check on container exits. - properties: - operator: - description: |- - Represents the relationship between the container exit code(s) and the - specified values. Possible values are: - - In: the requirement is satisfied if the container exit code is in the - set of specified values. - - NotIn: the requirement is satisfied if the container exit code is - not in the set of specified values. - type: string - values: - description: |- - Specifies the set of values to check for container exit codes. - At most 255 elements are allowed. - 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: description: |- SecurityContext defines the security options the container should be run with. @@ -3079,9 +2951,7 @@ spec: description: EnvVar represents an environment variable present in a Container. properties: name: - description: |- - Name of the environment variable. - May consist of any printable ASCII characters except '='. + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: |- @@ -3135,42 +3005,6 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic - fileKeyRef: - description: |- - FileKeyRef selects a key of the env file. - Requires the EnvFiles feature gate to be enabled. - properties: - key: - description: |- - The key within the env file. An invalid key will prevent the pod from starting. - The keys defined within a source may consist of any printable ASCII characters except '='. - During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. - type: string - optional: - default: false - description: |- - Specify whether the file or its key must be defined. If the file or key - does not exist, then the env var is not published. - If optional is set to true and the specified key does not exist, - the environment variable will not be set in the Pod's containers. - - If optional is set to false and the specified key does not exist, - an error will be returned during Pod creation. - type: boolean - path: - description: |- - The path within the volume from which to select the file. - Must be relative and may not contain the '..' path or start with '..'. - type: string - volumeName: - description: The name of the volume mount containing the env file. - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -3226,13 +3060,13 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source may consist of any printable ASCII characters except '='. - When a key exists in multiple + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: - description: EnvFromSource represents the source of a set of ConfigMaps or Secrets + description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: The ConfigMap to select from @@ -3252,9 +3086,7 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: |- - Optional text to prepend to the name of each environment variable. - May consist of any printable ASCII characters except '='. + description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -3503,12 +3335,6 @@ spec: - port type: object type: object - stopSignal: - description: |- - StopSignal defines which signal will be sent to a container when it is being stopped. - If not specified, the default is defined by the container runtime in use. - StopSignal can only be set for Pods with a non-empty .spec.os.name - type: string type: object livenessProbe: description: |- @@ -3899,7 +3725,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3953,10 +3779,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This overrides the pod-level restart policy. When this field is not specified, + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Additionally, setting the RestartPolicy as "Always" for the init container will - have the following effect: + Setting the RestartPolicy as "Always" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -3968,57 +3794,6 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string - restartPolicyRules: - description: |- - Represents a list of rules to be checked to determine if the - container should be restarted on exit. The rules are evaluated in - order. Once a rule matches a container exit condition, the remaining - rules are ignored. If no rule matches the container exit condition, - the Container-level restart policy determines the whether the container - is restarted or not. Constraints on the rules: - - At most 20 rules are allowed. - - Rules can have the same action. - - Identical rules are not forbidden in validations. - When rules are specified, container MUST set RestartPolicy explicitly - even it if matches the Pod's RestartPolicy. - items: - description: ContainerRestartRule describes how a container exit is handled. - properties: - action: - description: |- - Specifies the action taken on a container exit if the requirements - are satisfied. The only possible value is "Restart" to restart the - container. - type: string - exitCodes: - description: Represents the exit codes to check on container exits. - properties: - operator: - description: |- - Represents the relationship between the container exit code(s) and the - specified values. Possible values are: - - In: the requirement is satisfied if the container exit code is in the - set of specified values. - - NotIn: the requirement is satisfied if the container exit code is - not in the set of specified values. - type: string - values: - description: |- - Specifies the set of values to check for container exit codes. - At most 255 elements are allowed. - 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: description: |- SecurityContext defines the security options the container should be run with. @@ -5140,13 +4915,15 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string or nil value indicates that no - VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, - this field can be reset to its previous value (including nil) to cancel the modification. + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -5320,9 +5097,12 @@ spec: description: |- glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. + More info: https://examples.k8s.io/volumes/glusterfs/README.md properties: endpoints: - description: endpoints is the endpoint name that details Glusterfs topology. + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod type: string path: description: |- @@ -5376,7 +5156,7 @@ spec: The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). - Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. + Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: pullPolicy: @@ -5401,7 +5181,7 @@ spec: description: |- iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi + More info: https://examples.k8s.io/volumes/iscsi/README.md properties: chapAuthDiscovery: description: chapAuthDiscovery defines whether support iSCSI Discovery CHAP authentication @@ -5791,110 +5571,6 @@ spec: type: array x-kubernetes-list-type: atomic type: object - podCertificate: - description: |- - Projects an auto-rotating credential bundle (private key and certificate - chain) that the pod can use either as a TLS client or server. - - Kubelet generates a private key and uses it to send a - PodCertificateRequest to the named signer. Once the signer approves the - request and issues a certificate chain, Kubelet writes the key and - certificate chain to the pod filesystem. The pod does not start until - certificates have been issued for each podCertificate projected volume - source in its spec. - - Kubelet will begin trying to rotate the certificate at the time indicated - by the signer using the PodCertificateRequest.Status.BeginRefreshAt - timestamp. - - Kubelet can write a single file, indicated by the credentialBundlePath - field, or separate files, indicated by the keyPath and - certificateChainPath fields. - - The credential bundle is a single file in PEM format. The first PEM - entry is the private key (in PKCS#8 format), and the remaining PEM - entries are the certificate chain issued by the signer (typically, - signers will return their certificate chain in leaf-to-root order). - - Prefer using the credential bundle format, since your application code - can read it atomically. If you use keyPath and certificateChainPath, - your application must make two separate file reads. If these coincide - with a certificate rotation, it is possible that the private key and leaf - certificate you read may not correspond to each other. Your application - will need to check for this condition, and re-read until they are - consistent. - - The named signer controls chooses the format of the certificate it - issues; consult the signer implementation's documentation to learn how to - use the certificates it issues. - properties: - certificateChainPath: - description: |- - Write the certificate chain at this path in the projected volume. - - Most applications should use credentialBundlePath. When using keyPath - and certificateChainPath, your application needs to check that the key - and leaf certificate are consistent, because it is possible to read the - files mid-rotation. - type: string - credentialBundlePath: - description: |- - Write the credential bundle at this path in the projected volume. - - The credential bundle is a single file that contains multiple PEM blocks. - The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private - key. - - The remaining blocks are CERTIFICATE blocks, containing the issued - certificate chain from the signer (leaf and any intermediates). - - Using credentialBundlePath lets your Pod's application code make a single - atomic read that retrieves a consistent key and certificate chain. If you - project them to separate files, your application code will need to - additionally check that the leaf certificate was issued to the key. - type: string - keyPath: - description: |- - Write the key at this path in the projected volume. - - Most applications should use credentialBundlePath. When using keyPath - and certificateChainPath, your application needs to check that the key - and leaf certificate are consistent, because it is possible to read the - files mid-rotation. - type: string - keyType: - description: |- - The type of keypair Kubelet will generate for the pod. - - Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", - "ECDSAP521", and "ED25519". - type: string - maxExpirationSeconds: - description: |- - maxExpirationSeconds is the maximum lifetime permitted for the - certificate. - - Kubelet copies this value verbatim into the PodCertificateRequests it - generates for this projection. - - If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver - will reject values shorter than 3600 (1 hour). The maximum allowable - value is 7862400 (91 days). - - The signer implementation is then free to issue a certificate with any - lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 - seconds (1 hour). This constraint is enforced by kube-apiserver. - `kubernetes.io` signers will never issue certificates with a lifetime - longer than 24 hours. - format: int32 - type: integer - signerName: - description: Kubelet's generated CSRs will be addressed to this signer. - type: string - required: - - keyType - - signerName - type: object secret: description: secret information about the secret data to project properties: @@ -6024,6 +5700,7 @@ spec: description: |- rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. + More info: https://examples.k8s.io/volumes/rbd/README.md properties: fsType: description: |- @@ -6522,6 +6199,7 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -6532,6 +6210,7 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -6591,7 +6270,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6647,14 +6326,14 @@ spec: default: cgroupfs: systemd preferredAddressTypes: + - Hostname - InternalIP - ExternalIP - - Hostname description: Configure the Kubelet options, such as the preferred address types, or the expected cgroupfs. properties: cgroupfs: description: |- - CGroupFS defines the cgroup driver for Kubelet + CGroupFS defines the cgroup driver for Kubelet https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/ enum: - systemd @@ -6662,12 +6341,12 @@ spec: type: string preferredAddressTypes: default: + - Hostname - InternalIP - ExternalIP - - Hostname description: |- Ordered list of the preferred NodeAddressTypes to use for kubelet connections. - Default to InternalIP, ExternalIP, Hostname. + Default to Hostname, InternalIP, ExternalIP. items: enum: - Hostname @@ -6678,7 +6357,6 @@ spec: type: string minItems: 1 type: array - x-kubernetes-list-type: set type: object network: default: @@ -6879,7 +6557,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7166,7 +6844,7 @@ spec: agent: default: image: registry.k8s.io/kas-network-proxy/proxy-agent - mode: DaemonSet + version: v0.28.6 properties: extraArgs: description: |- @@ -7177,31 +6855,10 @@ spec: items: type: string type: array - hostNetwork: - default: false - description: |- - HostNetwork enables the konnectivity agent to use the Host network namespace. - By enabling this mode, the Agent doesn't need to wait for the CNI initialisation, - enabling a sort of out-of-band access to nodes for troubleshooting scenarios, - or when the agent needs direct access to the host network. - type: boolean image: default: registry.k8s.io/kas-network-proxy/proxy-agent description: AgentImage defines the container image for Konnectivity's agent. type: string - mode: - default: DaemonSet - description: 'Mode allows specifying the Agent deployment mode: Deployment, or DaemonSet (default).' - enum: - - DaemonSet - - Deployment - type: string - replicas: - description: |- - Replicas defines the number of replicas when Mode is Deployment. - Must be 0 if Mode is DaemonSet. - format: int32 - type: integer tolerations: default: - key: CriticalAddonsOnly @@ -7247,20 +6904,15 @@ spec: type: object type: array version: - description: |- - Version for Konnectivity agent. - If left empty, Kamaji will automatically inflect the version from the deployed Tenant Control Plane. - - WARNING: for last cut-off releases, the container image could be not available. + default: v0.28.6 + description: Version for Konnectivity agent. type: string type: object - x-kubernetes-validations: - - message: replicas must be 0 when mode is DaemonSet, and greater than 0 when mode is Deployment - rule: '!(self.mode == ''DaemonSet'' && has(self.replicas) && self.replicas != 0) && !(self.mode == ''Deployment'' && self.replicas == 0)' server: default: image: registry.k8s.io/kas-network-proxy/proxy-server port: 8132 + version: v0.28.6 properties: extraArgs: description: |- @@ -7287,7 +6939,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7339,11 +6991,8 @@ spec: type: object type: object version: - description: |- - Container image version of the Konnectivity server. - If left empty, Kamaji will automatically inflect the version from the deployed Tenant Control Plane. - - WARNING: for last cut-off releases, the container image could be not available. + default: v0.28.6 + description: Container image version of the Konnectivity server. type: string required: - port @@ -7496,7 +7145,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7631,7 +7280,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7691,16 +7340,6 @@ spec: dataStoreSchema: description: DataStoreSchema allows to specify the name of the database (for relational DataStores) or the key prefix (for etcd) type: string - dataStoreUsername: - description: |- - DataStoreUsername allows to specify the username of the database (for relational DataStores). This - value is optional and immutable. Note that Kamaji currently doesn't ensure that DataStoreUsername values are unique. It's up - to the user to avoid clashes between different TenantControlPlanes. If not set upon creation, Kamaji will default the - DataStoreUsername by concatenating the namespace and name of the TenantControlPlane. - type: string - x-kubernetes-validations: - - message: changing the dataStoreUsername is not supported - rule: self == oldSelf deployment: description: Configure how the TenantControlPlane Deployment object should be configured. properties: @@ -7984,6 +7623,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7998,6 +7638,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8158,6 +7799,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8172,6 +7814,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8260,8 +7903,8 @@ spec: 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 + 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) @@ -8325,6 +7968,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8339,6 +7983,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8499,6 +8144,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8513,6 +8159,7 @@ spec: 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8660,9 +8307,7 @@ spec: description: EnvVar represents an environment variable present in a Container. properties: name: - description: |- - Name of the environment variable. - May consist of any printable ASCII characters except '='. + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: |- @@ -8716,42 +8361,6 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic - fileKeyRef: - description: |- - FileKeyRef selects a key of the env file. - Requires the EnvFiles feature gate to be enabled. - properties: - key: - description: |- - The key within the env file. An invalid key will prevent the pod from starting. - The keys defined within a source may consist of any printable ASCII characters except '='. - During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. - type: string - optional: - default: false - description: |- - Specify whether the file or its key must be defined. If the file or key - does not exist, then the env var is not published. - If optional is set to true and the specified key does not exist, - the environment variable will not be set in the Pod's containers. - - If optional is set to false and the specified key does not exist, - an error will be returned during Pod creation. - type: boolean - path: - description: |- - The path within the volume from which to select the file. - Must be relative and may not contain the '..' path or start with '..'. - type: string - volumeName: - description: The name of the volume mount containing the env file. - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -8807,13 +8416,13 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source may consist of any printable ASCII characters except '='. - When a key exists in multiple + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: - description: EnvFromSource represents the source of a set of ConfigMaps or Secrets + description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: The ConfigMap to select from @@ -8833,9 +8442,7 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: |- - Optional text to prepend to the name of each environment variable. - May consist of any printable ASCII characters except '='. + description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -9084,12 +8691,6 @@ spec: - port type: object type: object - stopSignal: - description: |- - StopSignal defines which signal will be sent to a container when it is being stopped. - If not specified, the default is defined by the container runtime in use. - StopSignal can only be set for Pods with a non-empty .spec.os.name - type: string type: object livenessProbe: description: |- @@ -9480,7 +9081,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9534,10 +9135,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This overrides the pod-level restart policy. When this field is not specified, + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Additionally, setting the RestartPolicy as "Always" for the init container will - have the following effect: + Setting the RestartPolicy as "Always" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -9549,57 +9150,6 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string - restartPolicyRules: - description: |- - Represents a list of rules to be checked to determine if the - container should be restarted on exit. The rules are evaluated in - order. Once a rule matches a container exit condition, the remaining - rules are ignored. If no rule matches the container exit condition, - the Container-level restart policy determines the whether the container - is restarted or not. Constraints on the rules: - - At most 20 rules are allowed. - - Rules can have the same action. - - Identical rules are not forbidden in validations. - When rules are specified, container MUST set RestartPolicy explicitly - even it if matches the Pod's RestartPolicy. - items: - description: ContainerRestartRule describes how a container exit is handled. - properties: - action: - description: |- - Specifies the action taken on a container exit if the requirements - are satisfied. The only possible value is "Restart" to restart the - container. - type: string - exitCodes: - description: Represents the exit codes to check on container exits. - properties: - operator: - description: |- - Represents the relationship between the container exit code(s) and the - specified values. Possible values are: - - In: the requirement is satisfied if the container exit code is in the - set of specified values. - - NotIn: the requirement is satisfied if the container exit code is - not in the set of specified values. - type: string - values: - description: |- - Specifies the set of values to check for container exit codes. - At most 255 elements are allowed. - 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: description: |- SecurityContext defines the security options the container should be run with. @@ -10121,9 +9671,7 @@ spec: description: EnvVar represents an environment variable present in a Container. properties: name: - description: |- - Name of the environment variable. - May consist of any printable ASCII characters except '='. + description: Name of the environment variable. Must be a C_IDENTIFIER. type: string value: description: |- @@ -10177,42 +9725,6 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic - fileKeyRef: - description: |- - FileKeyRef selects a key of the env file. - Requires the EnvFiles feature gate to be enabled. - properties: - key: - description: |- - The key within the env file. An invalid key will prevent the pod from starting. - The keys defined within a source may consist of any printable ASCII characters except '='. - During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. - type: string - optional: - default: false - description: |- - Specify whether the file or its key must be defined. If the file or key - does not exist, then the env var is not published. - If optional is set to true and the specified key does not exist, - the environment variable will not be set in the Pod's containers. - - If optional is set to false and the specified key does not exist, - an error will be returned during Pod creation. - type: boolean - path: - description: |- - The path within the volume from which to select the file. - Must be relative and may not contain the '..' path or start with '..'. - type: string - volumeName: - description: The name of the volume mount containing the env file. - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -10268,13 +9780,13 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source may consist of any printable ASCII characters except '='. - When a key exists in multiple + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. items: - description: EnvFromSource represents the source of a set of ConfigMaps or Secrets + description: EnvFromSource represents the source of a set of ConfigMaps properties: configMapRef: description: The ConfigMap to select from @@ -10294,9 +9806,7 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: |- - Optional text to prepend to the name of each environment variable. - May consist of any printable ASCII characters except '='. + description: An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10545,12 +10055,6 @@ spec: - port type: object type: object - stopSignal: - description: |- - StopSignal defines which signal will be sent to a container when it is being stopped. - If not specified, the default is defined by the container runtime in use. - StopSignal can only be set for Pods with a non-empty .spec.os.name - type: string type: object livenessProbe: description: |- @@ -10941,7 +10445,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10995,10 +10499,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This overrides the pod-level restart policy. When this field is not specified, + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Additionally, setting the RestartPolicy as "Always" for the init container will - have the following effect: + Setting the RestartPolicy as "Always" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -11010,57 +10514,6 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string - restartPolicyRules: - description: |- - Represents a list of rules to be checked to determine if the - container should be restarted on exit. The rules are evaluated in - order. Once a rule matches a container exit condition, the remaining - rules are ignored. If no rule matches the container exit condition, - the Container-level restart policy determines the whether the container - is restarted or not. Constraints on the rules: - - At most 20 rules are allowed. - - Rules can have the same action. - - Identical rules are not forbidden in validations. - When rules are specified, container MUST set RestartPolicy explicitly - even it if matches the Pod's RestartPolicy. - items: - description: ContainerRestartRule describes how a container exit is handled. - properties: - action: - description: |- - Specifies the action taken on a container exit if the requirements - are satisfied. The only possible value is "Restart" to restart the - container. - type: string - exitCodes: - description: Represents the exit codes to check on container exits. - properties: - operator: - description: |- - Represents the relationship between the container exit code(s) and the - specified values. Possible values are: - - In: the requirement is satisfied if the container exit code is in the - set of specified values. - - NotIn: the requirement is satisfied if the container exit code is - not in the set of specified values. - type: string - values: - description: |- - Specifies the set of values to check for container exit codes. - At most 255 elements are allowed. - 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: description: |- SecurityContext defines the security options the container should be run with. @@ -12182,13 +11635,15 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string or nil value indicates that no - VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, - this field can be reset to its previous value (including nil) to cancel the modification. + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -12362,9 +11817,12 @@ spec: description: |- glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. + More info: https://examples.k8s.io/volumes/glusterfs/README.md properties: endpoints: - description: endpoints is the endpoint name that details Glusterfs topology. + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod type: string path: description: |- @@ -12418,7 +11876,7 @@ spec: The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. The volume will be mounted read-only (ro) and non-executable files (noexec). - Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. + Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: pullPolicy: @@ -12443,7 +11901,7 @@ spec: description: |- iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. - More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi + More info: https://examples.k8s.io/volumes/iscsi/README.md properties: chapAuthDiscovery: description: chapAuthDiscovery defines whether support iSCSI Discovery CHAP authentication @@ -12833,110 +12291,6 @@ spec: type: array x-kubernetes-list-type: atomic type: object - podCertificate: - description: |- - Projects an auto-rotating credential bundle (private key and certificate - chain) that the pod can use either as a TLS client or server. - - Kubelet generates a private key and uses it to send a - PodCertificateRequest to the named signer. Once the signer approves the - request and issues a certificate chain, Kubelet writes the key and - certificate chain to the pod filesystem. The pod does not start until - certificates have been issued for each podCertificate projected volume - source in its spec. - - Kubelet will begin trying to rotate the certificate at the time indicated - by the signer using the PodCertificateRequest.Status.BeginRefreshAt - timestamp. - - Kubelet can write a single file, indicated by the credentialBundlePath - field, or separate files, indicated by the keyPath and - certificateChainPath fields. - - The credential bundle is a single file in PEM format. The first PEM - entry is the private key (in PKCS#8 format), and the remaining PEM - entries are the certificate chain issued by the signer (typically, - signers will return their certificate chain in leaf-to-root order). - - Prefer using the credential bundle format, since your application code - can read it atomically. If you use keyPath and certificateChainPath, - your application must make two separate file reads. If these coincide - with a certificate rotation, it is possible that the private key and leaf - certificate you read may not correspond to each other. Your application - will need to check for this condition, and re-read until they are - consistent. - - The named signer controls chooses the format of the certificate it - issues; consult the signer implementation's documentation to learn how to - use the certificates it issues. - properties: - certificateChainPath: - description: |- - Write the certificate chain at this path in the projected volume. - - Most applications should use credentialBundlePath. When using keyPath - and certificateChainPath, your application needs to check that the key - and leaf certificate are consistent, because it is possible to read the - files mid-rotation. - type: string - credentialBundlePath: - description: |- - Write the credential bundle at this path in the projected volume. - - The credential bundle is a single file that contains multiple PEM blocks. - The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private - key. - - The remaining blocks are CERTIFICATE blocks, containing the issued - certificate chain from the signer (leaf and any intermediates). - - Using credentialBundlePath lets your Pod's application code make a single - atomic read that retrieves a consistent key and certificate chain. If you - project them to separate files, your application code will need to - additionally check that the leaf certificate was issued to the key. - type: string - keyPath: - description: |- - Write the key at this path in the projected volume. - - Most applications should use credentialBundlePath. When using keyPath - and certificateChainPath, your application needs to check that the key - and leaf certificate are consistent, because it is possible to read the - files mid-rotation. - type: string - keyType: - description: |- - The type of keypair Kubelet will generate for the pod. - - Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", - "ECDSAP521", and "ED25519". - type: string - maxExpirationSeconds: - description: |- - maxExpirationSeconds is the maximum lifetime permitted for the - certificate. - - Kubelet copies this value verbatim into the PodCertificateRequests it - generates for this projection. - - If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver - will reject values shorter than 3600 (1 hour). The maximum allowable - value is 7862400 (91 days). - - The signer implementation is then free to issue a certificate with any - lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 - seconds (1 hour). This constraint is enforced by kube-apiserver. - `kubernetes.io` signers will never issue certificates with a lifetime - longer than 24 hours. - format: int32 - type: integer - signerName: - description: Kubelet's generated CSRs will be addressed to this signer. - type: string - required: - - keyType - - signerName - type: object secret: description: secret information about the secret data to project properties: @@ -13066,6 +12420,7 @@ spec: description: |- rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. + More info: https://examples.k8s.io/volumes/rbd/README.md properties: fsType: description: |- @@ -13564,6 +12919,7 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -13574,6 +12930,7 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -13633,7 +12990,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13689,14 +13046,14 @@ spec: default: cgroupfs: systemd preferredAddressTypes: + - Hostname - InternalIP - ExternalIP - - Hostname description: Configure the Kubelet options, such as the preferred address types, or the expected cgroupfs. properties: cgroupfs: description: |- - CGroupFS defines the cgroup driver for Kubelet + CGroupFS defines the cgroup driver for Kubelet https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/ enum: - systemd @@ -13704,12 +13061,12 @@ spec: type: string preferredAddressTypes: default: + - Hostname - InternalIP - ExternalIP - - Hostname description: |- Ordered list of the preferred NodeAddressTypes to use for kubelet connections. - Default to InternalIP, ExternalIP, Hostname. + Default to Hostname, InternalIP, ExternalIP. items: enum: - Hostname @@ -13720,7 +13077,6 @@ spec: type: string minItems: 1 type: array - x-kubernetes-list-type: set type: object network: default: @@ -13914,7 +13270,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This field depends on the + This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14160,8 +13516,6 @@ rules: - metal3clusters verbs: - get - - list - - watch - apiGroups: - kamaji.clastix.io resources: @@ -14272,14 +13626,14 @@ spec: - --dynamic-infrastructure-clusters=${CACPPK_INFRASTRUCTURE_CLUSTERS:= } command: - /manager - image: docker.io/clastix/cluster-api-control-plane-provider-kamaji:v0.16.0 + image: docker.io/clastix/cluster-api-control-plane-provider-kamaji:v0.15.0 livenessProbe: httpGet: path: /healthz port: 8081 initialDelaySeconds: 15 periodSeconds: 20 - name: controller + name: manager readinessProbe: httpGet: path: /readyz diff --git a/packages/system/capi-providers-cpprovider/files/metadata.yaml b/packages/system/capi-providers-cpprovider/files/metadata.yaml index d22c9ab0..b282734a 100644 --- a/packages/system/capi-providers-cpprovider/files/metadata.yaml +++ b/packages/system/capi-providers-cpprovider/files/metadata.yaml @@ -5,9 +5,6 @@ # update this file only when a new major or minor version is released apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 releaseSeries: - - major: 0 - minor: 16 - contract: v1beta1 - major: 0 minor: 15 contract: v1beta1 diff --git a/packages/system/capi-providers-cpprovider/templates/configmaps.yaml b/packages/system/capi-providers-cpprovider/templates/configmaps.yaml index 736c06a5..d69ab12b 100644 --- a/packages/system/capi-providers-cpprovider/templates/configmaps.yaml +++ b/packages/system/capi-providers-cpprovider/templates/configmaps.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: ConfigMap metadata: - name: v0.16.0-cp + name: v0.15.1-cp labels: cp-components: cozy annotations: diff --git a/packages/system/capi-providers-cpprovider/templates/providers.yaml b/packages/system/capi-providers-cpprovider/templates/providers.yaml index 125a82c7..b173be14 100644 --- a/packages/system/capi-providers-cpprovider/templates/providers.yaml +++ b/packages/system/capi-providers-cpprovider/templates/providers.yaml @@ -4,7 +4,7 @@ metadata: name: kamaji spec: # https://github.com/clastix/cluster-api-control-plane-provider-kamaji - version: v0.16.0-cp + version: v0.15.1-cp fetchConfig: selector: matchLabels: diff --git a/packages/system/cert-manager-crds/Makefile b/packages/system/cert-manager-crds/Makefile index 7e7370ac..48e5644c 100644 --- a/packages/system/cert-manager-crds/Makefile +++ b/packages/system/cert-manager-crds/Makefile @@ -1,5 +1,8 @@ -export NAME=cert-manager-crds -export NAMESPACE=cozy-cert-manager - include ../../../hack/package.mk +update: + rm -rf charts + helm repo add jetstack https://charts.jetstack.io + helm repo update jetstack + helm pull jetstack/cert-manager --untar --untardir charts + rm -f -- `find charts/cert-manager/templates -maxdepth 1 -mindepth 1 | grep -v 'crds.yaml\|_helpers.tpl'` diff --git a/packages/system/cert-manager-crds/charts/cert-manager/Chart.yaml b/packages/system/cert-manager-crds/charts/cert-manager/Chart.yaml new file mode 100644 index 00000000..300db669 --- /dev/null +++ b/packages/system/cert-manager-crds/charts/cert-manager/Chart.yaml @@ -0,0 +1,26 @@ +annotations: + artifacthub.io/category: security + artifacthub.io/license: Apache-2.0 + artifacthub.io/prerelease: "false" + artifacthub.io/signKey: | + fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E + url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg +apiVersion: v2 +appVersion: v1.16.3 +description: A Helm chart for cert-manager +home: https://cert-manager.io +icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png +keywords: +- cert-manager +- kube-lego +- letsencrypt +- tls +kubeVersion: '>= 1.22.0-0' +maintainers: +- email: cert-manager-maintainers@googlegroups.com + name: cert-manager-maintainers + url: https://cert-manager.io +name: cert-manager +sources: +- https://github.com/cert-manager/cert-manager +version: v1.16.3 diff --git a/packages/system/cert-manager-crds/charts/cert-manager/README.md b/packages/system/cert-manager-crds/charts/cert-manager/README.md new file mode 100644 index 00000000..6fa25cc9 --- /dev/null +++ b/packages/system/cert-manager-crds/charts/cert-manager/README.md @@ -0,0 +1,1994 @@ +# cert-manager + +cert-manager is a Kubernetes addon to automate the management and issuance of +TLS certificates from various issuing sources. + +It will ensure certificates are valid and up to date periodically, and attempt +to renew certificates at an appropriate time before expiry. + +## Prerequisites + +- Kubernetes 1.22+ + +## Installing the Chart + +Full installation instructions, including details on how to configure extra +functionality in cert-manager can be found in the [installation docs](https://cert-manager.io/docs/installation/kubernetes/). + +Before installing the chart, you must first install the cert-manager CustomResourceDefinition resources. +This is performed in a separate step to allow you to easily uninstall and reinstall cert-manager without deleting your installed custom resources. + +```bash +$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.crds.yaml +``` + +To install the chart with the release name `cert-manager`: + +```console +## Add the Jetstack Helm repository +$ helm repo add jetstack https://charts.jetstack.io --force-update + +## Install the cert-manager helm chart +$ helm install cert-manager --namespace cert-manager --version v1.16.3 jetstack/cert-manager +``` + +In order to begin issuing certificates, you will need to set up a ClusterIssuer +or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). + +More information on the different types of issuers and how to configure them +can be found in [our documentation](https://cert-manager.io/docs/configuration/). + +For information on how to configure cert-manager to automatically provision +Certificates for Ingress resources, take a look at the +[Securing Ingresses documentation](https://cert-manager.io/docs/usage/ingress/). + +> **Tip**: List all releases using `helm list` + +## Upgrading the Chart + +Special considerations may be required when upgrading the Helm chart, and these +are documented in our full [upgrading guide](https://cert-manager.io/docs/installation/upgrading/). + +**Please check here before performing upgrades!** + +## Uninstalling the Chart + +To uninstall/delete the `cert-manager` deployment: + +```console +$ helm delete cert-manager --namespace cert-manager +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +If you want to completely uninstall cert-manager from your cluster, you will also need to +delete the previously installed CustomResourceDefinition resources: + +```console +$ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.crds.yaml +``` + +## Configuration + + +### Global + +#### **global.imagePullSecrets** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Reference to one or more secrets to be used when pulling images. For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). + +For example: + +```yaml +imagePullSecrets: + - name: "image-pull-secret" +``` +#### **global.commonLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Labels to apply to all resources. +Please note that this does not add labels to the resources created dynamically by the controllers. For these resources, you have to add the labels in the template in the cert-manager custom resource: For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress. For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress). +For example, secretTemplate in CertificateSpec +For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec). +#### **global.revisionHistoryLimit** ~ `number` + +The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10). + +#### **global.priorityClassName** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +The optional priority class to be used for the cert-manager pods. +#### **global.rbac.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Create required ClusterRoles and ClusterRoleBindings for cert-manager. +#### **global.rbac.aggregateClusterRoles** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Aggregate ClusterRoles to Kubernetes default user-facing roles. For more information, see [User-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) +#### **global.podSecurityPolicy.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create PodSecurityPolicy for cert-manager. + +Note that PodSecurityPolicy was deprecated in Kubernetes 1.21 and removed in Kubernetes 1.25. +#### **global.podSecurityPolicy.useAppArmor** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Configure the PodSecurityPolicy to use AppArmor. +#### **global.logLevel** ~ `number` +> Default value: +> ```yaml +> 2 +> ``` + +Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose. +#### **global.leaderElection.namespace** ~ `string` +> Default value: +> ```yaml +> kube-system +> ``` + +Override the namespace used for the leader election lease. +#### **global.leaderElection.leaseDuration** ~ `string` + +The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate. + +#### **global.leaderElection.renewDeadline** ~ `string` + +The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration. + +#### **global.leaderElection.retryPeriod** ~ `string` + +The duration the clients should wait between attempting acquisition and renewal of a leadership. + +#### **installCRDs** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +This option is equivalent to setting crds.enabled=true and crds.keep=true. Deprecated: use crds.enabled and crds.keep instead. +#### **crds.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +This option decides if the CRDs should be installed as part of the Helm installation. +#### **crds.keep** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +This option makes it so that the "helm.sh/resource-policy": keep annotation is added to the CRD. This will prevent Helm from uninstalling the CRD when the Helm release is uninstalled. WARNING: when the CRDs are removed, all cert-manager custom resources +(Certificates, Issuers, ...) will be removed too by the garbage collector. +### Controller + +#### **replicaCount** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +The number of replicas of the cert-manager controller to run. + +The default is 1, but in production set this to 2 or 3 to provide high availability. + +If `replicas > 1`, consider setting `podDisruptionBudget.enabled=true`. + +Note that cert-manager uses leader election to ensure that there can only be a single instance active at a time. +#### **strategy** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Deployment update strategy for the cert-manager controller deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). + +For example: + +```yaml +strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 +``` +#### **podDisruptionBudget.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Enable or disable the PodDisruptionBudget resource. + +This prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager +Pod is currently running. +#### **podDisruptionBudget.minAvailable** ~ `unknown` + +This configures the minimum available pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). +It cannot be used if `maxUnavailable` is set. + + +#### **podDisruptionBudget.maxUnavailable** ~ `unknown` + +This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). it cannot be used if `minAvailable` is set. + + +#### **featureGates** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +A comma-separated list of feature gates that should be enabled on the controller pod. +#### **maxConcurrentChallenges** ~ `number` +> Default value: +> ```yaml +> 60 +> ``` + +The maximum number of challenges that can be scheduled as 'processing' at once. +#### **image.registry** ~ `string` + +The container registry to pull the manager image from. + +#### **image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-controller +> ``` + +The container image for the cert-manager controller. + +#### **image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. + +#### **image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **clusterResourceNamespace** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Override the namespace used to store DNS provider credentials etc. for ClusterIssuer resources. By default, the same namespace as cert-manager is deployed within is used. This namespace will not be automatically created by the Helm chart. +#### **namespace** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +This namespace allows you to define where the services are installed into. If not set then they use the namespace of the release. This is helpful when installing cert manager as a chart dependency (sub chart). +#### **fullnameOverride** ~ `string` + +Override the "cert-manager.fullname" value. This value is used as part of most of the names of the resources created by this Helm chart. + +#### **nameOverride** ~ `string` + +Override the "cert-manager.name" value, which is used to annotate some of the resources that are created by this Chart (using "app.kubernetes.io/name"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use eg. "cainjector.name" which resolves to the value "cainjector"). + +#### **serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template. + +#### **serviceAccount.annotations** ~ `object` + +Optional additional annotations to add to the controller's Service Account. + +#### **serviceAccount.labels** ~ `object` + +Optional additional labels to add to the controller's Service Account. + +#### **serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. +#### **automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **enableCertificateOwnerRef** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted. +#### **config** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags. + +If `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself. + +For example: + +```yaml +config: + apiVersion: controller.config.cert-manager.io/v1alpha1 + kind: ControllerConfiguration + logging: + verbosity: 2 + format: text + leaderElectionConfig: + namespace: kube-system + kubernetesAPIQPS: 9000 + kubernetesAPIBurst: 9000 + numberOfConcurrentWorkers: 200 + featureGates: + AdditionalCertificateOutputFormats: true + DisallowInsecureCSRUsageDefinition: true + ExperimentalCertificateSigningRequestControllers: true + ExperimentalGatewayAPISupport: true + LiteralCertificateSubject: true + SecretsFilteredCaching: true + ServerSideApply: true + StableCertificateRequestName: true + UseCertificateRequestBasicConstraints: true + ValidateCAA: true + # Configure the metrics server for TLS + # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + metricsTLSConfig: + dynamic: + secretNamespace: "cert-manager" + secretName: "cert-manager-metrics-ca" + dnsNames: + - cert-manager-metrics +``` +#### **dns01RecursiveNameservers** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +A comma-separated string with the host and port of the recursive nameservers cert-manager should query. +#### **dns01RecursiveNameserversOnly** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Forces cert-manager to use only the recursive nameservers for verification. Enabling this option could cause the DNS01 self check to take longer owing to caching performed by the recursive nameservers. +#### **disableAutoApproval** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Option to disable cert-manager's build-in auto-approver. The auto-approver approves all CertificateRequests that reference issuers matching the 'approveSignerNames' option. This 'disableAutoApproval' option is useful when you want to make all approval decisions using a different approver (like approver-policy - https://github.com/cert-manager/approver-policy). +#### **approveSignerNames** ~ `array` +> Default value: +> ```yaml +> - issuers.cert-manager.io/* +> - clusterissuers.cert-manager.io/* +> ``` + +List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because eg. you are using approver-policy, you can enable 'disableAutoApproval'. +ref: https://cert-manager.io/docs/concepts/certificaterequest/#approval + +#### **extraArgs** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional command line flags to pass to cert-manager controller binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-controller: --help`. + +Use this flag to enable or disable arbitrary controllers. For example, to disable the CertificateRequests approver. + +For example: + +```yaml +extraArgs: + - --controllers=*,-certificaterequests-approver +``` +#### **extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager controller binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager controller pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context. +For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **deploymentAnnotations** ~ `object` + +Optional additional annotations to add to the controller Deployment. + +#### **podAnnotations** ~ `object` + +Optional additional annotations to add to the controller Pods. + +#### **podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the controller Pods. +#### **serviceAnnotations** ~ `object` + +Optional annotations to add to the controller Service. + +#### **serviceLabels** ~ `object` + +Optional additional labels to add to the controller Service. + +#### **serviceIPFamilyPolicy** ~ `string` + +Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). + +#### **serviceIPFamilies** ~ `array` + +Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. + +#### **podDnsPolicy** ~ `string` + +Pod DNS policy. +For more information, see [Pod's DNS Policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + +#### **podDnsConfig** ~ `object` + +Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy settings. However, when a Pod's dnsPolicy is set to "None", the dnsConfig field has to be specified. For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config). + +#### **hostAliases** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Optional hostAliases for cert-manager-controller pods. May be useful when performing ACME DNS-01 self checks. +#### **nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **ingressShim.defaultIssuerName** ~ `string` + +Optional default issuer to use for ingress resources. + +#### **ingressShim.defaultIssuerKind** ~ `string` + +Optional default issuer kind to use for ingress resources. + +#### **ingressShim.defaultIssuerGroup** ~ `string` + +Optional default issuer group to use for ingress resources. + +#### **http_proxy** ~ `string` + +Configures the HTTP_PROXY environment variable where a HTTP proxy is required. + +#### **https_proxy** ~ `string` + +Configures the HTTPS_PROXY environment variable where a HTTP proxy is required. + +#### **no_proxy** ~ `string` + +Configures the NO_PROXY environment variable where a HTTP proxy is required, but certain domains should be excluded. + +#### **affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **topologySpreadConstraints** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core + +For example: + +```yaml +topologySpreadConstraints: +- maxSkew: 2 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/instance: cert-manager + app.kubernetes.io/component: controller +``` +#### **livenessProbe** ~ `object` +> Default value: +> ```yaml +> enabled: true +> failureThreshold: 8 +> initialDelaySeconds: 10 +> periodSeconds: 10 +> successThreshold: 1 +> timeoutSeconds: 15 +> ``` + +LivenessProbe settings for the controller container of the controller Pod. + +This is enabled by default, in order to enable the clock-skew liveness probe that restarts the controller in case of a skew between the system clock and the monotonic clock. LivenessProbe durations and thresholds are based on those used for the Kubernetes controller-manager. For more information see the following on the +[Kubernetes GitHub repository](https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245) + +#### **enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links. +### Prometheus + +#### **prometheus.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a +ServiceMonitor resource. +Otherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. +#### **prometheus.servicemonitor.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create a ServiceMonitor to add cert-manager to Prometheus. +#### **prometheus.servicemonitor.namespace** ~ `string` + +The namespace that the service monitor should live in, defaults to the cert-manager namespace. + +#### **prometheus.servicemonitor.prometheusInstance** ~ `string` +> Default value: +> ```yaml +> default +> ``` + +Specifies the `prometheus` label on the created ServiceMonitor. This is used when different Prometheus instances have label selectors matching different ServiceMonitors. +#### **prometheus.servicemonitor.targetPort** ~ `number` +> Default value: +> ```yaml +> 9402 +> ``` + +The target port to set on the ServiceMonitor. This must match the port that the cert-manager controller is listening on for metrics. +#### **prometheus.servicemonitor.path** ~ `string` +> Default value: +> ```yaml +> /metrics +> ``` + +The path to scrape for metrics. +#### **prometheus.servicemonitor.interval** ~ `string` +> Default value: +> ```yaml +> 60s +> ``` + +The interval to scrape metrics. +#### **prometheus.servicemonitor.scrapeTimeout** ~ `string` +> Default value: +> ```yaml +> 30s +> ``` + +The timeout before a metrics scrape fails. +#### **prometheus.servicemonitor.labels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional labels to add to the ServiceMonitor. +#### **prometheus.servicemonitor.annotations** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional annotations to add to the ServiceMonitor. +#### **prometheus.servicemonitor.honorLabels** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Keep labels from scraped data, overriding server-side labels. +#### **prometheus.servicemonitor.endpointAdditionalProperties** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc. + +For example: + +```yaml +endpointAdditionalProperties: + relabelings: + - action: replace + sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: instance +``` + + + +#### **prometheus.podmonitor.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create a PodMonitor to add cert-manager to Prometheus. +#### **prometheus.podmonitor.namespace** ~ `string` + +The namespace that the pod monitor should live in, defaults to the cert-manager namespace. + +#### **prometheus.podmonitor.prometheusInstance** ~ `string` +> Default value: +> ```yaml +> default +> ``` + +Specifies the `prometheus` label on the created PodMonitor. This is used when different Prometheus instances have label selectors matching different PodMonitors. +#### **prometheus.podmonitor.path** ~ `string` +> Default value: +> ```yaml +> /metrics +> ``` + +The path to scrape for metrics. +#### **prometheus.podmonitor.interval** ~ `string` +> Default value: +> ```yaml +> 60s +> ``` + +The interval to scrape metrics. +#### **prometheus.podmonitor.scrapeTimeout** ~ `string` +> Default value: +> ```yaml +> 30s +> ``` + +The timeout before a metrics scrape fails. +#### **prometheus.podmonitor.labels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional labels to add to the PodMonitor. +#### **prometheus.podmonitor.annotations** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Additional annotations to add to the PodMonitor. +#### **prometheus.podmonitor.honorLabels** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Keep labels from scraped data, overriding server-side labels. +#### **prometheus.podmonitor.endpointAdditionalProperties** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc. + +For example: + +```yaml +endpointAdditionalProperties: + relabelings: + - action: replace + sourceLabels: + - __meta_kubernetes_pod_node_name + targetLabel: instance + # Configure the PodMonitor for TLS connections + # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + scheme: https + tlsConfig: + serverName: cert-manager-metrics + ca: + secret: + name: cert-manager-metrics-ca + key: "tls.crt" +``` + + + +### Webhook + +#### **webhook.replicaCount** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +Number of replicas of the cert-manager webhook to run. + +The default is 1, but in production set this to 2 or 3 to provide high availability. + +If `replicas > 1`, consider setting `webhook.podDisruptionBudget.enabled=true`. +#### **webhook.timeoutSeconds** ~ `number` +> Default value: +> ```yaml +> 30 +> ``` + +The number of seconds the API server should wait for the webhook to respond before treating the call as a failure. The value must be between 1 and 30 seconds. For more information, see +[Validating webhook configuration v1](https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/). + +The default is set to the maximum value of 30 seconds as users sometimes report that the connection between the K8S API server and the cert-manager webhook server times out. If *this* timeout is reached, the error message will be "context deadline exceeded", which doesn't help the user diagnose what phase of the HTTPS connection timed out. For example, it could be during DNS resolution, TCP connection, TLS negotiation, HTTP negotiation, or slow HTTP response from the webhook server. By setting this timeout to its maximum value the underlying timeout error message has more chance of being returned to the end user. +#### **webhook.config** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +This is used to configure options for the webhook pod. This allows setting options that would usually be provided using flags. + +If `apiVersion` and `kind` are unspecified they default to the current latest version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself. + +For example: + +```yaml +apiVersion: webhook.config.cert-manager.io/v1alpha1 +kind: WebhookConfiguration +# The port that the webhook listens on for requests. +# In GKE private clusters, by default Kubernetes apiservers are allowed to +# talk to the cluster nodes only on 443 and 10250. Configuring +# securePort: 10250 therefore will work out-of-the-box without needing to add firewall +# rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000. +# This should be uncommented and set as a default by the chart once +# the apiVersion of WebhookConfiguration graduates beyond v1alpha1. +securePort: 10250 +# Configure the metrics server for TLS +# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls +metricsTLSConfig: + dynamic: + secretNamespace: "cert-manager" + secretName: "cert-manager-metrics-ca" + dnsNames: + - cert-manager-metrics +``` +#### **webhook.strategy** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +The update strategy for the cert-manager webhook deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) + +For example: + +```yaml +strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 +``` +#### **webhook.securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context to be set on the webhook component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **webhook.containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the webhook component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **webhook.podDisruptionBudget.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Enable or disable the PodDisruptionBudget resource. + +This prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager +Pod is currently running. +#### **webhook.podDisruptionBudget.minAvailable** ~ `unknown` + +This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). +It cannot be used if `maxUnavailable` is set. + + +#### **webhook.podDisruptionBudget.maxUnavailable** ~ `unknown` + +This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). +It cannot be used if `minAvailable` is set. + + +#### **webhook.deploymentAnnotations** ~ `object` + +Optional additional annotations to add to the webhook Deployment. + +#### **webhook.podAnnotations** ~ `object` + +Optional additional annotations to add to the webhook Pods. + +#### **webhook.serviceAnnotations** ~ `object` + +Optional additional annotations to add to the webhook Service. + +#### **webhook.mutatingWebhookConfigurationAnnotations** ~ `object` + +Optional additional annotations to add to the webhook MutatingWebhookConfiguration. + +#### **webhook.validatingWebhookConfigurationAnnotations** ~ `object` + +Optional additional annotations to add to the webhook ValidatingWebhookConfiguration. + +#### **webhook.validatingWebhookConfiguration.namespaceSelector** ~ `object` +> Default value: +> ```yaml +> matchExpressions: +> - key: cert-manager.io/disable-validation +> operator: NotIn +> values: +> - "true" +> ``` + +Configure spec.namespaceSelector for validating webhooks. + +#### **webhook.mutatingWebhookConfiguration.namespaceSelector** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Configure spec.namespaceSelector for mutating webhooks. + +#### **webhook.extraArgs** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional command line flags to pass to cert-manager webhook binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-webhook: --help`. +#### **webhook.extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager webhook binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **webhook.featureGates** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Comma separated list of feature gates that should be enabled on the webhook pod. +#### **webhook.resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager webhook pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **webhook.livenessProbe** ~ `object` +> Default value: +> ```yaml +> failureThreshold: 3 +> initialDelaySeconds: 60 +> periodSeconds: 10 +> successThreshold: 1 +> timeoutSeconds: 1 +> ``` + +Liveness probe values. +For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + +#### **webhook.readinessProbe** ~ `object` +> Default value: +> ```yaml +> failureThreshold: 3 +> initialDelaySeconds: 5 +> periodSeconds: 5 +> successThreshold: 1 +> timeoutSeconds: 1 +> ``` + +Readiness probe values. +For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + +#### **webhook.nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **webhook.affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **webhook.tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **webhook.topologySpreadConstraints** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + +For example: + +```yaml +topologySpreadConstraints: +- maxSkew: 2 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/instance: cert-manager + app.kubernetes.io/component: controller +``` +#### **webhook.podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the Webhook Pods. +#### **webhook.serviceLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the Webhook Service. +#### **webhook.serviceIPFamilyPolicy** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). +#### **webhook.serviceIPFamilies** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. +#### **webhook.image.registry** ~ `string` + +The container registry to pull the webhook image from. + +#### **webhook.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-webhook +> ``` + +The container image for the cert-manager webhook + +#### **webhook.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used. + +#### **webhook.image.digest** ~ `string` + +Setting a digest will override any tag + +#### **webhook.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **webhook.serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **webhook.serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template. + +#### **webhook.serviceAccount.annotations** ~ `object` + +Optional additional annotations to add to the webhook's Service Account. + +#### **webhook.serviceAccount.labels** ~ `object` + +Optional additional labels to add to the webhook's Service Account. + +#### **webhook.serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. +#### **webhook.automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **webhook.securePort** ~ `number` +> Default value: +> ```yaml +> 10250 +> ``` + +The port that the webhook listens on for requests. In GKE private clusters, by default Kubernetes apiservers are allowed to talk to the cluster nodes only on 443 and 10250. Configuring securePort: 10250, therefore will work out-of-the-box without needing to add firewall rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. +#### **webhook.hostNetwork** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Specifies if the webhook should be started in hostNetwork mode. + +Required for use in some managed kubernetes clusters (such as AWS EKS) with custom. CNI (such as calico), because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working + +Since the default port for the webhook conflicts with kubelet on the host network, `webhook.securePort` should be changed to an available port if running in hostNetwork mode. +#### **webhook.serviceType** ~ `string` +> Default value: +> ```yaml +> ClusterIP +> ``` + +Specifies how the service should be handled. Useful if you want to expose the webhook outside of the cluster. In some cases, the control plane cannot reach internal services. +#### **webhook.loadBalancerIP** ~ `string` + +Specify the load balancer IP for the created service. + +#### **webhook.url** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Overrides the mutating webhook and validating webhook so they reach the webhook service using the `url` field instead of a service. +#### **webhook.networkPolicy.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Create network policies for the webhooks. +#### **webhook.networkPolicy.ingress** ~ `array` +> Default value: +> ```yaml +> - from: +> - ipBlock: +> cidr: 0.0.0.0/0 +> ``` + +Ingress rule for the webhook network policy. By default, it allows all inbound traffic. + +#### **webhook.networkPolicy.egress** ~ `array` +> Default value: +> ```yaml +> - ports: +> - port: 80 +> protocol: TCP +> - port: 443 +> protocol: TCP +> - port: 53 +> protocol: TCP +> - port: 53 +> protocol: UDP +> - port: 6443 +> protocol: TCP +> to: +> - ipBlock: +> cidr: 0.0.0.0/0 +> ``` + +Egress rule for the webhook network policy. By default, it allows all outbound traffic to ports 80 and 443, as well as DNS ports. + +#### **webhook.volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **webhook.volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **webhook.enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links. +### CA Injector + +#### **cainjector.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Create the CA Injector deployment +#### **cainjector.replicaCount** ~ `number` +> Default value: +> ```yaml +> 1 +> ``` + +The number of replicas of the cert-manager cainjector to run. + +The default is 1, but in production set this to 2 or 3 to provide high availability. + +If `replicas > 1`, consider setting `cainjector.podDisruptionBudget.enabled=true`. + +Note that cert-manager uses leader election to ensure that there can only be a single instance active at a time. +#### **cainjector.config** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +This is used to configure options for the cainjector pod. It allows setting options that are usually provided via flags. + +If `apiVersion` and `kind` are unspecified they default to the current latest version (currently `cainjector.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself. + +For example: + +```yaml +apiVersion: cainjector.config.cert-manager.io/v1alpha1 +kind: CAInjectorConfiguration +logging: + verbosity: 2 + format: text +leaderElectionConfig: + namespace: kube-system +# Configure the metrics server for TLS +# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls +metricsTLSConfig: + dynamic: + secretNamespace: "cert-manager" + secretName: "cert-manager-metrics-ca" + dnsNames: + - cert-manager-metrics +``` +#### **cainjector.strategy** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Deployment update strategy for the cert-manager cainjector deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). + +For example: + +```yaml +strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 +``` +#### **cainjector.securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context to be set on the cainjector component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **cainjector.containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the cainjector component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **cainjector.podDisruptionBudget.enabled** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +Enable or disable the PodDisruptionBudget resource. + +This prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager +Pod is currently running. +#### **cainjector.podDisruptionBudget.minAvailable** ~ `unknown` + +`minAvailable` configures the minimum available pods for disruptions. It can either be set to +an integer (e.g. 1) or a percentage value (e.g. 25%). +Cannot be used if `maxUnavailable` is set. + + +#### **cainjector.podDisruptionBudget.maxUnavailable** ~ `unknown` + +`maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to +an integer (e.g. 1) or a percentage value (e.g. 25%). +Cannot be used if `minAvailable` is set. + + +#### **cainjector.deploymentAnnotations** ~ `object` + +Optional additional annotations to add to the cainjector Deployment. + +#### **cainjector.podAnnotations** ~ `object` + +Optional additional annotations to add to the cainjector Pods. + +#### **cainjector.serviceAnnotations** ~ `object` + +Optional additional annotations to add to the cainjector metrics Service. + +#### **cainjector.extraArgs** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional command line flags to pass to cert-manager cainjector binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-cainjector: --help`. +#### **cainjector.extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager cainjector binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **cainjector.featureGates** ~ `string` +> Default value: +> ```yaml +> "" +> ``` + +Comma separated list of feature gates that should be enabled on the cainjector pod. +#### **cainjector.resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager cainjector pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **cainjector.nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **cainjector.affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **cainjector.tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **cainjector.topologySpreadConstraints** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + +For example: + +```yaml +topologySpreadConstraints: +- maxSkew: 2 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app.kubernetes.io/instance: cert-manager + app.kubernetes.io/component: controller +``` +#### **cainjector.podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the CA Injector Pods. +#### **cainjector.serviceLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the CA Injector metrics Service. +#### **cainjector.image.registry** ~ `string` + +The container registry to pull the cainjector image from. + +#### **cainjector.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-cainjector +> ``` + +The container image for the cert-manager cainjector + +#### **cainjector.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used. + +#### **cainjector.image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **cainjector.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **cainjector.serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **cainjector.serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template + +#### **cainjector.serviceAccount.annotations** ~ `object` + +Optional additional annotations to add to the cainjector's Service Account. + +#### **cainjector.serviceAccount.labels** ~ `object` + +Optional additional labels to add to the cainjector's Service Account. + +#### **cainjector.serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. +#### **cainjector.automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **cainjector.volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **cainjector.volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **cainjector.enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links. +### ACME Solver + +#### **acmesolver.image.registry** ~ `string` + +The container registry to pull the acmesolver image from. + +#### **acmesolver.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-acmesolver +> ``` + +The container image for the cert-manager acmesolver. + +#### **acmesolver.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. + +#### **acmesolver.image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **acmesolver.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +### Startup API Check + + +This startupapicheck is a Helm post-install hook that waits for the webhook endpoints to become available. The check is implemented using a Kubernetes Job - if you are injecting mesh sidecar proxies into cert-manager pods, ensure that they are not injected into this Job's pod. Otherwise, the installation may time out owing to the Job never being completed because the sidecar proxy does not exit. For more information, see [this note](https://github.com/cert-manager/cert-manager/pull/4414). +#### **startupapicheck.enabled** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Enables the startup api check. +#### **startupapicheck.securityContext** ~ `object` +> Default value: +> ```yaml +> runAsNonRoot: true +> seccompProfile: +> type: RuntimeDefault +> ``` + +Pod Security Context to be set on the startupapicheck component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **startupapicheck.containerSecurityContext** ~ `object` +> Default value: +> ```yaml +> allowPrivilegeEscalation: false +> capabilities: +> drop: +> - ALL +> readOnlyRootFilesystem: true +> ``` + +Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + +#### **startupapicheck.timeout** ~ `string` +> Default value: +> ```yaml +> 1m +> ``` + +Timeout for 'kubectl check api' command. +#### **startupapicheck.backoffLimit** ~ `number` +> Default value: +> ```yaml +> 4 +> ``` + +Job backoffLimit +#### **startupapicheck.jobAnnotations** ~ `object` +> Default value: +> ```yaml +> helm.sh/hook: post-install +> helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +> helm.sh/hook-weight: "1" +> ``` + +Optional additional annotations to add to the startupapicheck Job. + +#### **startupapicheck.podAnnotations** ~ `object` + +Optional additional annotations to add to the startupapicheck Pods. + +#### **startupapicheck.extraArgs** ~ `array` +> Default value: +> ```yaml +> - -v +> ``` + +Additional command line flags to pass to startupapicheck binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-startupapicheck: --help`. + +Verbose logging is enabled by default so that if startupapicheck fails, you can know what exactly caused the failure. Verbose logs include details of the webhook URL, IP address and TCP connect errors for example. + +#### **startupapicheck.extraEnv** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional environment variables to pass to cert-manager startupapicheck binary. +For example: + +```yaml +extraEnv: +- name: SOME_VAR + value: 'some value' +``` +#### **startupapicheck.resources** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Resources to provide to the cert-manager controller pod. + +For example: + +```yaml +requests: + cpu: 10m + memory: 32Mi +``` + +For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +#### **startupapicheck.nodeSelector** ~ `object` +> Default value: +> ```yaml +> kubernetes.io/os: linux +> ``` + +The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + +This default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + +#### **startupapicheck.affinity** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). +For example: + +```yaml +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: foo.bar.com/role + operator: In + values: + - master +``` +#### **startupapicheck.tolerations** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + +For example: + +```yaml +tolerations: +- key: foo.bar.com/role + operator: Equal + value: master + effect: NoSchedule +``` +#### **startupapicheck.podLabels** ~ `object` +> Default value: +> ```yaml +> {} +> ``` + +Optional additional labels to add to the startupapicheck Pods. +#### **startupapicheck.image.registry** ~ `string` + +The container registry to pull the startupapicheck image from. + +#### **startupapicheck.image.repository** ~ `string` +> Default value: +> ```yaml +> quay.io/jetstack/cert-manager-startupapicheck +> ``` + +The container image for the cert-manager startupapicheck. + +#### **startupapicheck.image.tag** ~ `string` + +Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used. + +#### **startupapicheck.image.digest** ~ `string` + +Setting a digest will override any tag. + +#### **startupapicheck.image.pullPolicy** ~ `string` +> Default value: +> ```yaml +> IfNotPresent +> ``` + +Kubernetes imagePullPolicy on Deployment. +#### **startupapicheck.rbac.annotations** ~ `object` +> Default value: +> ```yaml +> helm.sh/hook: post-install +> helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +> helm.sh/hook-weight: "-5" +> ``` + +annotations for the startup API Check job RBAC and PSP resources. + +#### **startupapicheck.automountServiceAccountToken** ~ `bool` + +Automounting API credentials for a particular pod. + +#### **startupapicheck.serviceAccount.create** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Specifies whether a service account should be created. +#### **startupapicheck.serviceAccount.name** ~ `string` + +The name of the service account to use. +If not set and create is true, a name is generated using the fullname template. + +#### **startupapicheck.serviceAccount.annotations** ~ `object` +> Default value: +> ```yaml +> helm.sh/hook: post-install +> helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded +> helm.sh/hook-weight: "-5" +> ``` + +Optional additional annotations to add to the Job's Service Account. + +#### **startupapicheck.serviceAccount.automountServiceAccountToken** ~ `bool` +> Default value: +> ```yaml +> true +> ``` + +Automount API credentials for a Service Account. + +#### **startupapicheck.serviceAccount.labels** ~ `object` + +Optional additional labels to add to the startupapicheck's Service Account. + +#### **startupapicheck.volumes** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volumes to add to the cert-manager controller pod. +#### **startupapicheck.volumeMounts** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Additional volume mounts to add to the cert-manager controller container. +#### **startupapicheck.enableServiceLinks** ~ `bool` +> Default value: +> ```yaml +> false +> ``` + +enableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. +#### **extraObjects** ~ `array` +> Default value: +> ```yaml +> [] +> ``` + +Create dynamic manifests via values. + +For example: + +```yaml +extraObjects: + - | + apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ template "cert-manager.fullname" . }}-extra-configmap' +``` + + +### Default Security Contexts + +The default pod-level and container-level security contexts, below, adhere to the [restricted](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted) Pod Security Standards policies. + +Default pod-level securityContext: +```yaml +runAsNonRoot: true +seccompProfile: + type: RuntimeDefault +``` + +Default containerSecurityContext: +```yaml +allowPrivilegeEscalation: false +capabilities: + drop: + - ALL +``` + +### Assigning Values + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, + +```console +$ helm install my-release -f values.yaml . +``` +> **Tip**: You can use the default [values.yaml](https://github.com/cert-manager/cert-manager/blob/master/deploy/charts/cert-manager/values.yaml) + +## Contributing + +This chart is maintained at [github.com/cert-manager/cert-manager](https://github.com/cert-manager/cert-manager/tree/master/deploy/charts/cert-manager). diff --git a/packages/system/cert-manager-crds/templates/_helpers.tpl b/packages/system/cert-manager-crds/charts/cert-manager/templates/_helpers.tpl similarity index 95% rename from packages/system/cert-manager-crds/templates/_helpers.tpl rename to packages/system/cert-manager-crds/charts/cert-manager/templates/_helpers.tpl index f85373f3..e15fa191 100644 --- a/packages/system/cert-manager-crds/templates/_helpers.tpl +++ b/packages/system/cert-manager-crds/charts/cert-manager/templates/_helpers.tpl @@ -187,17 +187,6 @@ See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linke {{- end }} {{- end }} -{{/* -Labels for the CRD resources. -*/}} -{{- define "cert-manager.crd-labels" -}} -app: "{{ template "cert-manager.name" . }}" -app.kubernetes.io/name: "{{ template "cert-manager.name" . }}" -app.kubernetes.io/instance: "{{ .Release.Name }}" -app.kubernetes.io/component: "crds" -{{ include "labels" . }} -{{- end -}} - {{/* Check that the user has not set both .installCRDs and .crds.enabled or set .installCRDs and disabled .crds.keep. diff --git a/packages/system/cert-manager-crds/charts/cert-manager/templates/crds.yaml b/packages/system/cert-manager-crds/charts/cert-manager/templates/crds.yaml new file mode 100644 index 00000000..00930f9c --- /dev/null +++ b/packages/system/cert-manager-crds/charts/cert-manager/templates/crds.yaml @@ -0,0 +1,12013 @@ +# {{- include "cert-manager.crd-check" . }} +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificaterequests.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: CertificateRequest + listKind: CertificateRequestList + plural: certificaterequests + shortNames: + - cr + - crs + singular: certificaterequest + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Approved")].status + name: Approved + type: string + - jsonPath: .status.conditions[?(@.type=="Denied")].status + name: Denied + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + type: string + - jsonPath: .spec.username + name: Requester + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A CertificateRequest is used to request a signed certificate from one of the + configured issuers. + + All fields within the CertificateRequest's `spec` are immutable after creation. + A CertificateRequest will either succeed or fail, as denoted by its `Ready` status + condition and its `status.failureTime` field. + + A CertificateRequest is a one-shot resource, meaning it represents a single + point in time request for a certificate and cannot be re-used. + type: object + 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: |- + Specification of the desired state of the CertificateRequest resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - request + properties: + duration: + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + type: string + extra: + description: |- + Extra contains extra attributes of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: object + additionalProperties: + type: array + items: + type: string + groups: + description: |- + Groups contains group membership of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: array + items: + type: string + x-kubernetes-list-type: atomic + isCA: + description: |- + Requested basic constraints isCA value. Note that the issuer may choose + to ignore the requested isCA value, just like any other requested attribute. + + NOTE: If the CSR in the `Request` field has a BasicConstraints extension, + it must have the same isCA value as specified here. + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. + type: boolean + issuerRef: + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + The `name` field of the reference must always be specified. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: |- + The PEM-encoded X.509 certificate signing request to be submitted to the + issuer for signing. + + If the CSR has a BasicConstraints extension, its isCA attribute must + match the `isCA` value of this CertificateRequest. + If the CSR has a KeyUsage extension, its key usages must match the + key usages in the `usages` field of this CertificateRequest. + If the CSR has a ExtKeyUsage extension, its extended key usages + must match the extended key usages in the `usages` field of this + CertificateRequest. + type: string + format: byte + uid: + description: |- + UID contains the uid of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: string + usages: + description: |- + Requested key usages and extended key usages. + + NOTE: If the CSR in the `Request` field has uses the KeyUsage or + ExtKeyUsage extension, these extensions must have the same values + as specified here without any additional values. + + If unset, defaults to `digital signature` and `key encipherment`. + type: array + items: + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + username: + description: |- + Username contains the name of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: string + status: + description: |- + Status of the CertificateRequest. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + properties: + ca: + description: |- + The PEM encoded X.509 certificate of the signer, also known as the CA + (Certificate Authority). + This is set on a best-effort basis by different issuers. + If not set, the CA is assumed to be unknown/not available. + type: string + format: byte + certificate: + description: |- + The PEM encoded X.509 certificate resulting from the certificate + signing request. + If not set, the CertificateRequest has either not been completed or has + failed. More information on failure can be found by checking the + `conditions` field. + type: string + format: byte + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`, `InvalidRequest`, `Approved` and `Denied`. + type: array + items: + description: CertificateRequestCondition contains condition information for a CertificateRequest. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: |- + Type of the condition, known values are (`Ready`, `InvalidRequest`, + `Approved`, `Denied`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failureTime: + description: |- + FailureTime stores the time that this CertificateRequest failed. This is + used to influence garbage collection and back-off. + type: string + format: date-time + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificates.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Certificate + listKind: CertificateList + plural: certificates + shortNames: + - cert + - certs + singular: certificate + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.secretName + name: Secret + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A Certificate resource should be created to ensure an up to date and signed + X.509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. + + The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`). + type: object + 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: |- + Specification of the desired state of the Certificate resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - secretName + properties: + additionalOutputFormats: + description: |- + Defines extra output formats of the private key and signed certificate chain + to be written to this Certificate's target Secret. + + This is a Beta Feature enabled by default. It can be disabled with the + `--feature-gates=AdditionalCertificateOutputFormats=false` option set on both + the controller and webhook components. + type: array + items: + description: |- + CertificateAdditionalOutputFormat defines an additional output format of a + Certificate resource. These contain supplementary data formats of the signed + certificate chain and paired private key. + type: object + required: + - type + properties: + type: + description: |- + Type is the name of the format type that should be written to the + Certificate's target Secret. + type: string + enum: + - DER + - CombinedPEM + commonName: + description: |- + Requested common name X509 certificate subject attribute. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + NOTE: TLS clients will ignore this value when any subject alternative name is + set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). + + Should have a length of 64 characters or fewer to avoid generating invalid CSRs. + Cannot be set if the `literalSubject` field is set. + type: string + dnsNames: + description: Requested DNS subject alternative names. + type: array + items: + type: string + duration: + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + + If unset, this defaults to 90 days. + Minimum accepted duration is 1 hour. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. + type: string + emailAddresses: + description: Requested email subject alternative names. + type: array + items: + type: string + encodeUsagesInRequest: + description: |- + Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. + + This option defaults to true, and should only be disabled if the target + issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions. + type: boolean + ipAddresses: + description: Requested IP address subject alternative names. + type: array + items: + type: string + isCA: + description: |- + Requested basic constraints isCA value. + The isCA value is used to set the `isCA` field on the created CertificateRequest + resources. Note that the issuer may choose to ignore the requested isCA value, just + like any other requested attribute. + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. + type: boolean + issuerRef: + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + The `name` field of the reference must always be specified. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + keystores: + description: Additional keystore output formats to be stored in the Certificate's Secret. + type: object + properties: + jks: + description: |- + JKS configures options for storing a JKS keystore in the + `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + alias: + description: |- + Alias specifies the alias of the key in the keystore, required by the JKS format. + If not provided, the default alias `certificate` will be used. + type: string + create: + description: |- + Create enables JKS keystore creation for the Certificate. + If true, a file named `keystore.jks` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.jks` + will also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` + containing the issuing Certificate Authority + type: boolean + passwordSecretRef: + description: |- + PasswordSecretRef is a reference to a key in a Secret resource + containing the password used to encrypt the JKS keystore. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + pkcs12: + description: |- + PKCS12 configures options for storing a PKCS12 keystore in the + `spec.secretName` Secret resource. + type: object + required: + - create + - passwordSecretRef + properties: + create: + description: |- + Create enables PKCS12 keystore creation for the Certificate. + If true, a file named `keystore.p12` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.p12` will + also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` containing the issuing Certificate + Authority + type: boolean + passwordSecretRef: + description: |- + PasswordSecretRef is a reference to a key in a Secret resource + containing the password used to encrypt the PKCS12 keystore. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + profile: + description: |- + Profile specifies the key and certificate encryption algorithms and the HMAC algorithm + used to create the PKCS12 keystore. Default value is `LegacyRC2` for backward compatibility. + + If provided, allowed values are: + `LegacyRC2`: Deprecated. Not supported by default in OpenSSL 3 or Java 20. + `LegacyDES`: Less secure algorithm. Use this option for maximal compatibility. + `Modern2023`: Secure algorithm. Use this option in case you have to always use secure algorithms + (eg. because of company policy). Please note that the security of the algorithm is not that important + in reality, because the unencrypted certificate and private key are also stored in the Secret. + type: string + enum: + - LegacyRC2 + - LegacyDES + - Modern2023 + literalSubject: + description: |- + Requested X.509 certificate subject, represented using the LDAP "String + Representation of a Distinguished Name" [1]. + Important: the LDAP string format also specifies the order of the attributes + in the subject, this is important when issuing certs for LDAP authentication. + Example: `CN=foo,DC=corp,DC=example,DC=com` + More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 + More info: https://github.com/cert-manager/cert-manager/issues/3203 + More info: https://github.com/cert-manager/cert-manager/issues/4424 + + Cannot be set if the `subject` or `commonName` field is set. + type: string + nameConstraints: + description: |- + x.509 certificate NameConstraint extension which MUST NOT be used in a non-CA certificate. + More Info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10 + + This is an Alpha Feature and is only enabled with the + `--feature-gates=NameConstraints=true` option set on both + the controller and webhook components. + type: object + properties: + critical: + description: if true then the name constraints are marked critical. + type: boolean + excluded: + description: |- + Excluded contains the constraints which must be disallowed. Any name matching a + restriction in the excluded field is invalid regardless + of information appearing in the permitted + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + permitted: + description: Permitted contains the constraints in which the names must be located. + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + otherNames: + description: |- + `otherNames` is an escape hatch for SAN that allows any type. We currently restrict the support to string like otherNames, cf RFC 5280 p 37 + Any UTF8 String valued otherName can be passed with by setting the keys oid: x.x.x.x and UTF8Value: somevalue for `otherName`. + Most commonly this would be UPN set with oid: 1.3.6.1.4.1.311.20.2.3 + You should ensure that any OID passed is valid for the UTF8String type as we do not explicitly validate this. + type: array + items: + type: object + properties: + oid: + description: |- + OID is the object identifier for the otherName SAN. + The object identifier must be expressed as a dotted string, for + example, "1.2.840.113556.1.4.221". + type: string + utf8Value: + description: |- + utf8Value is the string value of the otherName SAN. + The utf8Value accepts any valid UTF8 string to set as value for the otherName SAN. + type: string + privateKey: + description: |- + Private key options. These include the key algorithm and size, the used + encoding and the rotation policy. + type: object + properties: + algorithm: + description: |- + Algorithm is the private key algorithm of the corresponding private key + for this certificate. + + If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. + If `algorithm` is specified and `size` is not provided, + key size of 2048 will be used for `RSA` key algorithm and + key size of 256 will be used for `ECDSA` key algorithm. + key size is ignored when using the `Ed25519` key algorithm. + type: string + enum: + - RSA + - ECDSA + - Ed25519 + encoding: + description: |- + The private key cryptography standards (PKCS) encoding for this + certificate's private key to be encoded in. + + If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 + and PKCS#8, respectively. + Defaults to `PKCS1` if not specified. + type: string + enum: + - PKCS1 + - PKCS8 + rotationPolicy: + description: |- + RotationPolicy controls how private keys should be regenerated when a + re-issuance is being processed. + + If set to `Never`, a private key will only be generated if one does not + already exist in the target `spec.secretName`. If one does exist but it + does not have the correct algorithm or size, a warning will be raised + to await user intervention. + If set to `Always`, a private key matching the specified requirements + will be generated whenever a re-issuance occurs. + Default is `Never` for backward compatibility. + type: string + enum: + - Never + - Always + size: + description: |- + Size is the key bit size of the corresponding private key for this certificate. + + If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, + and will default to `2048` if not specified. + If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, + and will default to `256` if not specified. + If `algorithm` is set to `Ed25519`, Size is ignored. + No other values are allowed. + type: integer + renewBefore: + description: |- + How long before the currently issued certificate's expiry cert-manager should + renew the certificate. For example, if a certificate is valid for 60 minutes, + and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate + 50 minutes after it was issued (i.e. when there are 10 minutes remaining until + the certificate is no longer valid). + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + If unset, this defaults to 1/3 of the issued certificate's lifetime. + Minimum accepted value is 5 minutes. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. + Cannot be set if the `renewBeforePercentage` field is set. + type: string + renewBeforePercentage: + description: |- + `renewBeforePercentage` is like `renewBefore`, except it is a relative percentage + rather than an absolute duration. For example, if a certificate is valid for 60 + minutes, and `renewBeforePercentage=25`, cert-manager will begin to attempt to + renew the certificate 45 minutes after it was issued (i.e. when there are 15 + minutes (25%) remaining until the certificate is no longer valid). + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + Value must be an integer in the range (0,100). The minimum effective + `renewBefore` derived from the `renewBeforePercentage` and `duration` fields is 5 + minutes. + Cannot be set if the `renewBefore` field is set. + type: integer + format: int32 + revisionHistoryLimit: + description: |- + The maximum number of CertificateRequest revisions that are maintained in + the Certificate's history. Each revision represents a single `CertificateRequest` + created by this Certificate, either when it was created, renewed, or Spec + was changed. Revisions will be removed by oldest first if the number of + revisions exceeds this number. + + If set, revisionHistoryLimit must be a value of `1` or greater. + If unset (`nil`), revisions will not be garbage collected. + Default value is `nil`. + type: integer + format: int32 + secretName: + description: |- + Name of the Secret resource that will be automatically created and + managed by this Certificate resource. It will be populated with a + private key and certificate, signed by the denoted issuer. The Secret + resource lives in the same namespace as the Certificate resource. + type: string + secretTemplate: + description: |- + Defines annotations and labels to be copied to the Certificate's Secret. + Labels and annotations on the Secret will be changed as they appear on the + SecretTemplate when added or removed. SecretTemplate annotations are added + in conjunction with, and cannot overwrite, the base set of annotations + cert-manager sets on the Certificate's Secret. + type: object + properties: + annotations: + description: Annotations is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + labels: + description: Labels is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + subject: + description: |- + Requested set of X509 certificate subject attributes. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + + The common name attribute is specified separately in the `commonName` field. + Cannot be set if the `literalSubject` field is set. + type: object + properties: + countries: + description: Countries to be used on the Certificate. + type: array + items: + type: string + localities: + description: Cities to be used on the Certificate. + type: array + items: + type: string + organizationalUnits: + description: Organizational Units to be used on the Certificate. + type: array + items: + type: string + organizations: + description: Organizations to be used on the Certificate. + type: array + items: + type: string + postalCodes: + description: Postal codes to be used on the Certificate. + type: array + items: + type: string + provinces: + description: State/Provinces to be used on the Certificate. + type: array + items: + type: string + serialNumber: + description: Serial number to be used on the Certificate. + type: string + streetAddresses: + description: Street addresses to be used on the Certificate. + type: array + items: + type: string + uris: + description: Requested URI subject alternative names. + type: array + items: + type: string + usages: + description: |- + Requested key usages and extended key usages. + These usages are used to set the `usages` field on the created CertificateRequest + resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages + will additionally be encoded in the `request` field which contains the CSR blob. + + If unset, defaults to `digital signature` and `key encipherment`. + type: array + items: + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + status: + description: |- + Status of the Certificate. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + properties: + conditions: + description: |- + List of status conditions to indicate the status of certificates. + Known condition types are `Ready` and `Issuing`. + type: array + items: + description: CertificateCondition contains condition information for a Certificate. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Certificate. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`, `Issuing`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failedIssuanceAttempts: + description: |- + The number of continuous failed issuance attempts up till now. This + field gets removed (if set) on a successful issuance and gets set to + 1 if unset and an issuance has failed. If an issuance has failed, the + delay till the next issuance will be calculated using formula + time.Hour * 2 ^ (failedIssuanceAttempts - 1). + type: integer + lastFailureTime: + description: |- + LastFailureTime is set only if the latest issuance for this + Certificate failed and contains the time of the failure. If an + issuance has failed, the delay till the next issuance will be + calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - + 1). If the latest issuance has succeeded this field will be unset. + type: string + format: date-time + nextPrivateKeySecretName: + description: |- + The name of the Secret resource containing the private key to be used + for the next certificate iteration. + The keymanager controller will automatically set this field if the + `Issuing` condition is set to `True`. + It will automatically unset this field when the Issuing condition is + not set or False. + type: string + notAfter: + description: |- + The expiration time of the certificate stored in the secret named + by this resource in `spec.secretName`. + type: string + format: date-time + notBefore: + description: |- + The time after which the certificate stored in the secret named + by this resource in `spec.secretName` is valid. + type: string + format: date-time + renewalTime: + description: |- + RenewalTime is the time at which the certificate will be next + renewed. + If not set, no upcoming renewal is scheduled. + type: string + format: date-time + revision: + description: |- + The current 'revision' of the certificate as issued. + + When a CertificateRequest resource is created, it will have the + `cert-manager.io/certificate-revision` set to one greater than the + current value of this field. + + Upon issuance, this field will be set to the value of the annotation + on the CertificateRequest resource used to issue the certificate. + + Persisting the value on the CertificateRequest resource allows the + certificates controller to know whether a request is part of an old + issuance or if it is part of the ongoing revision's issuance by + checking if the revision value in the annotation is greater than this + field. + type: integer + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: challenges.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Challenge + listKind: ChallengeList + plural: challenges + singular: challenge + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.dnsName + name: Domain + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: Challenge is a type to represent a Challenge request with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - authorizationURL + - dnsName + - issuerRef + - key + - solver + - token + - type + - url + properties: + authorizationURL: + description: |- + The URL to the ACME Authorization resource that this + challenge is a part of. + type: string + dnsName: + description: |- + dnsName is the identifier that this challenge is for, e.g. example.com. + If the requested DNSName is a 'wildcard', this field MUST be set to the + non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. + type: string + issuerRef: + description: |- + References a properly configured ACME-type Issuer which should + be used to create this Challenge. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Challenge will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + key: + description: |- + The ACME challenge key for this challenge + For HTTP01 challenges, this is the value that must be responded with to + complete the HTTP01 challenge in the format: + `.`. + For DNS01 challenges, this is the base64 encoded SHA256 sum of the + `.` + text that must be set as the TXT record content. + type: string + solver: + description: |- + Contains the domain solving configuration that should be used to + solve this challenge resource. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + token: + description: |- + The ACME challenge token for this challenge. + This is the raw value returned from the ACME server. + type: string + type: + description: |- + The type of ACME challenge this resource represents. + One of "HTTP-01" or "DNS-01". + type: string + enum: + - HTTP-01 + - DNS-01 + url: + description: |- + The URL of the ACME Challenge resource for this challenge. + This can be used to lookup details about the status of this challenge. + type: string + wildcard: + description: |- + wildcard will be true if this challenge is for a wildcard identifier, + for example '*.example.com'. + type: boolean + status: + type: object + properties: + presented: + description: |- + presented will be set to true if the challenge values for this challenge + are currently 'presented'. + This *does not* imply the self check is passing. Only that the values + have been 'submitted' for the appropriate challenge mechanism (i.e. the + DNS01 TXT record has been presented, or the HTTP01 configuration has been + configured). + type: boolean + processing: + description: |- + Used to denote whether this challenge should be processed or not. + This field will only be set to true by the 'scheduling' component. + It will only be set to false by the 'challenges' controller, after the + challenge has reached a final state or timed out. + If this field is set to false, the challenge controller will not take + any more action. + type: boolean + reason: + description: |- + Contains human readable information on why the Challenge is in the + current state. + type: string + state: + description: |- + Contains the current 'state' of the challenge. + If not set, the state of the challenge is unknown. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + served: true + storage: true + subresources: + status: {} + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterissuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: ClusterIssuer + listKind: ClusterIssuerList + plural: clusterissuers + singular: clusterissuer + categories: + - cert-manager + scope: Cluster + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A ClusterIssuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is similar to an Issuer, however it is cluster-scoped and therefore can + be referenced by resources that exist in *any* namespace, not just the same + namespace as the referent. + type: object + required: + - spec + 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: Desired state of the ClusterIssuer resource. + type: object + properties: + acme: + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. + type: boolean + email: + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. + type: boolean + externalAccountBinding: + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + preferredChain: + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. + type: string + maxLength: 64 + privateKeySecretRef: + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + server: + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. + type: string + skipTLSVerify: + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. + type: boolean + solvers: + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ + type: array + items: + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". + type: array + items: + type: string + ocspServers: + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. + type: string + selfSigned: + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertificate: + description: |- + ClientCertificate authenticates with Vault by presenting a client + certificate during the request's TLS handshake. + Works only when using HTTPS protocol. + type: object + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/cert" will be used. + type: string + name: + description: |- + Name of the certificate role to authenticate against. + If not set, matching any certificate role, if available. + type: string + secretName: + description: |- + Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing + tls.crt and tls.key) used to authenticate to Vault using TLS client + authentication. + type: string + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a base64-encoded bundle of PEM CAs + which will be used to validate the certificate chain presented by the TPP server. + Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + credentialsRef: + description: |- + CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + The secret must contain the key 'access-token' for the Access Token Authentication, + or two keys, 'username' and 'password' for the API Keys Authentication. + type: object + required: + - name + properties: + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". + type: string + zone: + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. + type: string + status: + description: Status of the ClusterIssuer. This is set and managed automatically. + type: object + properties: + acme: + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + lastRegisteredEmail: + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + uri: + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA + type: string + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: issuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Issuer + listKind: IssuerList + plural: issuers + singular: issuer + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + An Issuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is scoped to a single namespace and can therefore only be referenced by + resources within the same namespace. + type: object + required: + - spec + 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: Desired state of the Issuer resource. + type: object + properties: + acme: + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. + type: boolean + email: + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. + type: boolean + externalAccountBinding: + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + preferredChain: + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. + type: string + maxLength: 64 + privateKeySecretRef: + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + server: + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. + type: string + skipTLSVerify: + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. + type: boolean + solvers: + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ + type: array + items: + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". + type: array + items: + type: string + ocspServers: + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. + type: string + selfSigned: + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertificate: + description: |- + ClientCertificate authenticates with Vault by presenting a client + certificate during the request's TLS handshake. + Works only when using HTTPS protocol. + type: object + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/cert" will be used. + type: string + name: + description: |- + Name of the certificate role to authenticate against. + If not set, matching any certificate role, if available. + type: string + secretName: + description: |- + Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing + tls.crt and tls.key) used to authenticate to Vault using TLS client + authentication. + type: string + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a base64-encoded bundle of PEM CAs + which will be used to validate the certificate chain presented by the TPP server. + Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + credentialsRef: + description: |- + CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + The secret must contain the key 'access-token' for the Access Token Authentication, + or two keys, 'username' and 'password' for the API Keys Authentication. + type: object + required: + - name + properties: + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". + type: string + zone: + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. + type: string + status: + description: Status of the Issuer. This is set and managed automatically. + type: object + properties: + acme: + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + lastRegisteredEmail: + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + uri: + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA + type: string + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: orders.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Order + listKind: OrderList + plural: orders + singular: order + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: Order is a type to represent an Order with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - issuerRef + - request + properties: + commonName: + description: |- + CommonName is the common name as specified on the DER encoded CSR. + If specified, this value must also be present in `dnsNames` or `ipAddresses`. + This field must match the corresponding field on the DER encoded CSR. + type: string + dnsNames: + description: |- + DNSNames is a list of DNS names that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + duration: + description: |- + Duration is the duration for the not after date for the requested certificate. + this is set on order creation as pe the ACME spec. + type: string + ipAddresses: + description: |- + IPAddresses is a list of IP addresses that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + issuerRef: + description: |- + IssuerRef references a properly configured ACME-type Issuer which should + be used to create this Order. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Order will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: |- + Certificate signing request bytes in DER encoding. + This will be used when finalizing the order. + This field must be set on the order. + type: string + format: byte + status: + type: object + properties: + authorizations: + description: |- + Authorizations contains data returned from the ACME server on what + authorizations must be completed in order to validate the DNS names + specified on the Order. + type: array + items: + description: |- + ACMEAuthorization contains data returned from the ACME server on an + authorization that must be completed in order validate a DNS name on an ACME + Order resource. + type: object + required: + - url + properties: + challenges: + description: |- + Challenges specifies the challenge types offered by the ACME server. + One of these challenge types will be selected when validating the DNS + name and an appropriate Challenge resource will be created to perform + the ACME challenge process. + type: array + items: + description: |- + Challenge specifies a challenge offered by the ACME server for an Order. + An appropriate Challenge resource can be created to perform the ACME + challenge process. + type: object + required: + - token + - type + - url + properties: + token: + description: |- + Token is the token that must be presented for this challenge. + This is used to compute the 'key' that must also be presented. + type: string + type: + description: |- + Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', + 'tls-sni-01', etc. + This is the raw value retrieved from the ACME server. + Only 'http-01' and 'dns-01' are supported by cert-manager, other values + will be ignored. + type: string + url: + description: |- + URL is the URL of this challenge. It can be used to retrieve additional + metadata about the Challenge from the ACME server. + type: string + identifier: + description: Identifier is the DNS name to be validated as part of this authorization + type: string + initialState: + description: |- + InitialState is the initial state of the ACME authorization when first + fetched from the ACME server. + If an Authorization is already 'valid', the Order controller will not + create a Challenge resource for the authorization. This will occur when + working with an ACME server that enables 'authz reuse' (such as Let's + Encrypt's production endpoint). + If not set and 'identifier' is set, the state is assumed to be pending + and a Challenge will be created. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: URL is the URL of the Authorization that must be completed + type: string + wildcard: + description: |- + Wildcard will be true if this authorization is for a wildcard DNS name. + If this is true, the identifier will be the *non-wildcard* version of + the DNS name. + For example, if '*.example.com' is the DNS name being validated, this + field will be 'true' and the 'identifier' field will be 'example.com'. + type: boolean + certificate: + description: |- + Certificate is a copy of the PEM encoded certificate for this Order. + This field will be populated after the order has been successfully + finalized with the ACME server, and the order has transitioned to the + 'valid' state. + type: string + format: byte + failureTime: + description: |- + FailureTime stores the time that this order failed. + This is used to influence garbage collection and back-off. + type: string + format: date-time + finalizeURL: + description: |- + FinalizeURL of the Order. + This is used to obtain certificates for this order once it has been completed. + type: string + reason: + description: |- + Reason optionally provides more information about a why the order is in + the current state. + type: string + state: + description: |- + State contains the current state of this Order resource. + States 'success' and 'expired' are 'final' + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: |- + URL of the Order. + This will initially be empty when the resource is first created. + The Order controller will populate this field when the Order is first processed. + This field will be immutable after it is initially set. + type: string + served: true + storage: true + +# END crd {{- end }} diff --git a/packages/system/cert-manager-crds/charts/cert-manager/values.schema.json b/packages/system/cert-manager-crds/charts/cert-manager/values.schema.json new file mode 100644 index 00000000..d04da90c --- /dev/null +++ b/packages/system/cert-manager-crds/charts/cert-manager/values.schema.json @@ -0,0 +1,2135 @@ +{ + "$defs": { + "helm-values": { + "additionalProperties": false, + "properties": { + "acmesolver": { + "$ref": "#/$defs/helm-values.acmesolver" + }, + "affinity": { + "$ref": "#/$defs/helm-values.affinity" + }, + "approveSignerNames": { + "$ref": "#/$defs/helm-values.approveSignerNames" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.automountServiceAccountToken" + }, + "cainjector": { + "$ref": "#/$defs/helm-values.cainjector" + }, + "clusterResourceNamespace": { + "$ref": "#/$defs/helm-values.clusterResourceNamespace" + }, + "config": { + "$ref": "#/$defs/helm-values.config" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.containerSecurityContext" + }, + "crds": { + "$ref": "#/$defs/helm-values.crds" + }, + "creator": { + "$ref": "#/$defs/helm-values.creator" + }, + "deploymentAnnotations": { + "$ref": "#/$defs/helm-values.deploymentAnnotations" + }, + "disableAutoApproval": { + "$ref": "#/$defs/helm-values.disableAutoApproval" + }, + "dns01RecursiveNameservers": { + "$ref": "#/$defs/helm-values.dns01RecursiveNameservers" + }, + "dns01RecursiveNameserversOnly": { + "$ref": "#/$defs/helm-values.dns01RecursiveNameserversOnly" + }, + "enableCertificateOwnerRef": { + "$ref": "#/$defs/helm-values.enableCertificateOwnerRef" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.enableServiceLinks" + }, + "enabled": { + "$ref": "#/$defs/helm-values.enabled" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.extraEnv" + }, + "extraObjects": { + "$ref": "#/$defs/helm-values.extraObjects" + }, + "featureGates": { + "$ref": "#/$defs/helm-values.featureGates" + }, + "fullnameOverride": { + "$ref": "#/$defs/helm-values.fullnameOverride" + }, + "global": { + "$ref": "#/$defs/helm-values.global" + }, + "hostAliases": { + "$ref": "#/$defs/helm-values.hostAliases" + }, + "http_proxy": { + "$ref": "#/$defs/helm-values.http_proxy" + }, + "https_proxy": { + "$ref": "#/$defs/helm-values.https_proxy" + }, + "image": { + "$ref": "#/$defs/helm-values.image" + }, + "ingressShim": { + "$ref": "#/$defs/helm-values.ingressShim" + }, + "installCRDs": { + "$ref": "#/$defs/helm-values.installCRDs" + }, + "livenessProbe": { + "$ref": "#/$defs/helm-values.livenessProbe" + }, + "maxConcurrentChallenges": { + "$ref": "#/$defs/helm-values.maxConcurrentChallenges" + }, + "nameOverride": { + "$ref": "#/$defs/helm-values.nameOverride" + }, + "namespace": { + "$ref": "#/$defs/helm-values.namespace" + }, + "no_proxy": { + "$ref": "#/$defs/helm-values.no_proxy" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.podAnnotations" + }, + "podDisruptionBudget": { + "$ref": "#/$defs/helm-values.podDisruptionBudget" + }, + "podDnsConfig": { + "$ref": "#/$defs/helm-values.podDnsConfig" + }, + "podDnsPolicy": { + "$ref": "#/$defs/helm-values.podDnsPolicy" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.podLabels" + }, + "prometheus": { + "$ref": "#/$defs/helm-values.prometheus" + }, + "replicaCount": { + "$ref": "#/$defs/helm-values.replicaCount" + }, + "resources": { + "$ref": "#/$defs/helm-values.resources" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.serviceAccount" + }, + "serviceAnnotations": { + "$ref": "#/$defs/helm-values.serviceAnnotations" + }, + "serviceIPFamilies": { + "$ref": "#/$defs/helm-values.serviceIPFamilies" + }, + "serviceIPFamilyPolicy": { + "$ref": "#/$defs/helm-values.serviceIPFamilyPolicy" + }, + "serviceLabels": { + "$ref": "#/$defs/helm-values.serviceLabels" + }, + "startupapicheck": { + "$ref": "#/$defs/helm-values.startupapicheck" + }, + "strategy": { + "$ref": "#/$defs/helm-values.strategy" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.tolerations" + }, + "topologySpreadConstraints": { + "$ref": "#/$defs/helm-values.topologySpreadConstraints" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.volumes" + }, + "webhook": { + "$ref": "#/$defs/helm-values.webhook" + } + }, + "type": "object" + }, + "helm-values.acmesolver": { + "additionalProperties": false, + "properties": { + "image": { + "$ref": "#/$defs/helm-values.acmesolver.image" + } + }, + "type": "object" + }, + "helm-values.acmesolver.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.acmesolver.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.acmesolver.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.acmesolver.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.acmesolver.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.acmesolver.image.tag" + } + }, + "type": "object" + }, + "helm-values.acmesolver.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.acmesolver.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.acmesolver.image.registry": { + "description": "The container registry to pull the acmesolver image from.", + "type": "string" + }, + "helm-values.acmesolver.image.repository": { + "default": "quay.io/jetstack/cert-manager-acmesolver", + "description": "The container image for the cert-manager acmesolver.", + "type": "string" + }, + "helm-values.acmesolver.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used.", + "type": "string" + }, + "helm-values.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\n\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.approveSignerNames": { + "default": [ + "issuers.cert-manager.io/*", + "clusterissuers.cert-manager.io/*" + ], + "description": "List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because eg. you are using approver-policy, you can enable 'disableAutoApproval'.\nref: https://cert-manager.io/docs/concepts/certificaterequest/#approval", + "items": {}, + "type": "array" + }, + "helm-values.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.cainjector": { + "additionalProperties": false, + "properties": { + "affinity": { + "$ref": "#/$defs/helm-values.cainjector.affinity" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.cainjector.automountServiceAccountToken" + }, + "config": { + "$ref": "#/$defs/helm-values.cainjector.config" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.cainjector.containerSecurityContext" + }, + "deploymentAnnotations": { + "$ref": "#/$defs/helm-values.cainjector.deploymentAnnotations" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.cainjector.enableServiceLinks" + }, + "enabled": { + "$ref": "#/$defs/helm-values.cainjector.enabled" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.cainjector.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.cainjector.extraEnv" + }, + "featureGates": { + "$ref": "#/$defs/helm-values.cainjector.featureGates" + }, + "image": { + "$ref": "#/$defs/helm-values.cainjector.image" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.cainjector.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.cainjector.podAnnotations" + }, + "podDisruptionBudget": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.cainjector.podLabels" + }, + "replicaCount": { + "$ref": "#/$defs/helm-values.cainjector.replicaCount" + }, + "resources": { + "$ref": "#/$defs/helm-values.cainjector.resources" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.cainjector.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount" + }, + "serviceAnnotations": { + "$ref": "#/$defs/helm-values.cainjector.serviceAnnotations" + }, + "serviceLabels": { + "$ref": "#/$defs/helm-values.cainjector.serviceLabels" + }, + "strategy": { + "$ref": "#/$defs/helm-values.cainjector.strategy" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.cainjector.tolerations" + }, + "topologySpreadConstraints": { + "$ref": "#/$defs/helm-values.cainjector.topologySpreadConstraints" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.cainjector.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.cainjector.volumes" + } + }, + "type": "object" + }, + "helm-values.cainjector.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\n\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.cainjector.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.cainjector.config": { + "default": {}, + "description": "This is used to configure options for the cainjector pod. It allows setting options that are usually provided via flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `cainjector.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\napiVersion: cainjector.config.cert-manager.io/v1alpha1\nkind: CAInjectorConfiguration\nlogging:\n verbosity: 2\n format: text\nleaderElectionConfig:\n namespace: kube-system\n# Configure the metrics server for TLS\n# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\nmetricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "type": "object" + }, + "helm-values.cainjector.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the cainjector component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.cainjector.deploymentAnnotations": { + "description": "Optional additional annotations to add to the cainjector Deployment.", + "type": "object" + }, + "helm-values.cainjector.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.cainjector.enabled": { + "default": true, + "description": "Create the CA Injector deployment", + "type": "boolean" + }, + "helm-values.cainjector.extraArgs": { + "default": [], + "description": "Additional command line flags to pass to cert-manager cainjector binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-cainjector: --help`.", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager cainjector binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.featureGates": { + "default": "", + "description": "Comma separated list of feature gates that should be enabled on the cainjector pod.", + "type": "string" + }, + "helm-values.cainjector.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.cainjector.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.cainjector.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.cainjector.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.cainjector.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.cainjector.image.tag" + } + }, + "type": "object" + }, + "helm-values.cainjector.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.cainjector.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.cainjector.image.registry": { + "description": "The container registry to pull the cainjector image from.", + "type": "string" + }, + "helm-values.cainjector.image.repository": { + "default": "quay.io/jetstack/cert-manager-cainjector", + "description": "The container image for the cert-manager cainjector", + "type": "string" + }, + "helm-values.cainjector.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used.", + "type": "string" + }, + "helm-values.cainjector.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.cainjector.podAnnotations": { + "description": "Optional additional annotations to add to the cainjector Pods.", + "type": "object" + }, + "helm-values.cainjector.podDisruptionBudget": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget.enabled" + }, + "maxUnavailable": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget.maxUnavailable" + }, + "minAvailable": { + "$ref": "#/$defs/helm-values.cainjector.podDisruptionBudget.minAvailable" + } + }, + "type": "object" + }, + "helm-values.cainjector.podDisruptionBudget.enabled": { + "default": false, + "description": "Enable or disable the PodDisruptionBudget resource.\n\nThis prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager\nPod is currently running.", + "type": "boolean" + }, + "helm-values.cainjector.podDisruptionBudget.maxUnavailable": { + "description": "`maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to\nan integer (e.g. 1) or a percentage value (e.g. 25%).\nCannot be used if `minAvailable` is set." + }, + "helm-values.cainjector.podDisruptionBudget.minAvailable": { + "description": "`minAvailable` configures the minimum available pods for disruptions. It can either be set to\nan integer (e.g. 1) or a percentage value (e.g. 25%).\nCannot be used if `maxUnavailable` is set." + }, + "helm-values.cainjector.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the CA Injector Pods.", + "type": "object" + }, + "helm-values.cainjector.replicaCount": { + "default": 1, + "description": "The number of replicas of the cert-manager cainjector to run.\n\nThe default is 1, but in production set this to 2 or 3 to provide high availability.\n\nIf `replicas > 1`, consider setting `cainjector.podDisruptionBudget.enabled=true`.\n\nNote that cert-manager uses leader election to ensure that there can only be a single instance active at a time.", + "type": "number" + }, + "helm-values.cainjector.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager cainjector pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.cainjector.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context to be set on the cainjector component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.cainjector.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.cainjector.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.cainjector.serviceAccount.annotations": { + "description": "Optional additional annotations to add to the cainjector's Service Account.", + "type": "object" + }, + "helm-values.cainjector.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.cainjector.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.cainjector.serviceAccount.labels": { + "description": "Optional additional labels to add to the cainjector's Service Account.", + "type": "object" + }, + "helm-values.cainjector.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template", + "type": "string" + }, + "helm-values.cainjector.serviceAnnotations": { + "description": "Optional additional annotations to add to the cainjector metrics Service.", + "type": "object" + }, + "helm-values.cainjector.serviceLabels": { + "default": {}, + "description": "Optional additional labels to add to the CA Injector metrics Service.", + "type": "object" + }, + "helm-values.cainjector.strategy": { + "default": {}, + "description": "Deployment update strategy for the cert-manager cainjector deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy).\n\nFor example:\nstrategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 0\n maxUnavailable: 1", + "type": "object" + }, + "helm-values.cainjector.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.topologySpreadConstraints": { + "default": [], + "description": "A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core).\n\nFor example:\ntopologySpreadConstraints:\n- maxSkew: 2\n topologyKey: topology.kubernetes.io/zone\n whenUnsatisfiable: ScheduleAnyway\n labelSelector:\n matchLabels:\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/component: controller", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.cainjector.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + }, + "helm-values.clusterResourceNamespace": { + "default": "", + "description": "Override the namespace used to store DNS provider credentials etc. for ClusterIssuer resources. By default, the same namespace as cert-manager is deployed within is used. This namespace will not be automatically created by the Helm chart.", + "type": "string" + }, + "helm-values.config": { + "default": {}, + "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n featureGates:\n AdditionalCertificateOutputFormats: true\n DisallowInsecureCSRUsageDefinition: true\n ExperimentalCertificateSigningRequestControllers: true\n ExperimentalGatewayAPISupport: true\n LiteralCertificateSubject: true\n SecretsFilteredCaching: true\n ServerSideApply: true\n StableCertificateRequestName: true\n UseCertificateRequestBasicConstraints: true\n ValidateCAA: true\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "type": "object" + }, + "helm-values.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.crds": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.crds.enabled" + }, + "keep": { + "$ref": "#/$defs/helm-values.crds.keep" + } + }, + "type": "object" + }, + "helm-values.crds.enabled": { + "default": false, + "description": "This option decides if the CRDs should be installed as part of the Helm installation.", + "type": "boolean" + }, + "helm-values.crds.keep": { + "default": true, + "description": "This option makes it so that the \"helm.sh/resource-policy\": keep annotation is added to the CRD. This will prevent Helm from uninstalling the CRD when the Helm release is uninstalled. WARNING: when the CRDs are removed, all cert-manager custom resources\n(Certificates, Issuers, ...) will be removed too by the garbage collector.", + "type": "boolean" + }, + "helm-values.creator": { + "default": "helm", + "description": "Field used by our release pipeline to produce the static manifests. The field defaults to \"helm\" but is set to \"static\" when we render the static YAML manifests.", + "type": "string" + }, + "helm-values.deploymentAnnotations": { + "description": "Optional additional annotations to add to the controller Deployment.", + "type": "object" + }, + "helm-values.disableAutoApproval": { + "default": false, + "description": "Option to disable cert-manager's build-in auto-approver. The auto-approver approves all CertificateRequests that reference issuers matching the 'approveSignerNames' option. This 'disableAutoApproval' option is useful when you want to make all approval decisions using a different approver (like approver-policy - https://github.com/cert-manager/approver-policy).", + "type": "boolean" + }, + "helm-values.dns01RecursiveNameservers": { + "default": "", + "description": "A comma-separated string with the host and port of the recursive nameservers cert-manager should query.", + "type": "string" + }, + "helm-values.dns01RecursiveNameserversOnly": { + "default": false, + "description": "Forces cert-manager to use only the recursive nameservers for verification. Enabling this option could cause the DNS01 self check to take longer owing to caching performed by the recursive nameservers.", + "type": "boolean" + }, + "helm-values.enableCertificateOwnerRef": { + "default": false, + "description": "When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted.", + "type": "boolean" + }, + "helm-values.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.enabled": { + "default": true, + "description": "Field that can be used as a condition when cert-manager is a dependency. This definition is only here as a placeholder such that it is included in the json schema. See https://helm.sh/docs/chart_best_practices/dependencies/#conditions-and-tags for more info.", + "type": "boolean" + }, + "helm-values.extraArgs": { + "default": [], + "description": "Additional command line flags to pass to cert-manager controller binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-controller: --help`.\n\nUse this flag to enable or disable arbitrary controllers. For example, to disable the CertificateRequests approver.\n\nFor example:\nextraArgs:\n - --controllers=*,-certificaterequests-approver", + "items": {}, + "type": "array" + }, + "helm-values.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager controller binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.extraObjects": { + "default": [], + "description": "Create dynamic manifests via values.\n\nFor example:\nextraObjects:\n - |\n apiVersion: v1\n kind: ConfigMap\n metadata:\n name: '{{ template \"cert-manager.fullname\" . }}-extra-configmap'", + "items": {}, + "type": "array" + }, + "helm-values.featureGates": { + "default": "", + "description": "A comma-separated list of feature gates that should be enabled on the controller pod.", + "type": "string" + }, + "helm-values.fullnameOverride": { + "description": "Override the \"cert-manager.fullname\" value. This value is used as part of most of the names of the resources created by this Helm chart.", + "type": "string" + }, + "helm-values.global": { + "description": "Global values shared across all (sub)charts", + "properties": { + "commonLabels": { + "$ref": "#/$defs/helm-values.global.commonLabels" + }, + "imagePullSecrets": { + "$ref": "#/$defs/helm-values.global.imagePullSecrets" + }, + "leaderElection": { + "$ref": "#/$defs/helm-values.global.leaderElection" + }, + "logLevel": { + "$ref": "#/$defs/helm-values.global.logLevel" + }, + "podSecurityPolicy": { + "$ref": "#/$defs/helm-values.global.podSecurityPolicy" + }, + "priorityClassName": { + "$ref": "#/$defs/helm-values.global.priorityClassName" + }, + "rbac": { + "$ref": "#/$defs/helm-values.global.rbac" + }, + "revisionHistoryLimit": { + "$ref": "#/$defs/helm-values.global.revisionHistoryLimit" + } + }, + "type": "object" + }, + "helm-values.global.commonLabels": { + "default": {}, + "description": "Labels to apply to all resources.\nPlease note that this does not add labels to the resources created dynamically by the controllers. For these resources, you have to add the labels in the template in the cert-manager custom resource: For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress. For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress).\nFor example, secretTemplate in CertificateSpec\nFor more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec).", + "type": "object" + }, + "helm-values.global.imagePullSecrets": { + "default": [], + "description": "Reference to one or more secrets to be used when pulling images. For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/).\n\nFor example:\nimagePullSecrets:\n - name: \"image-pull-secret\"", + "items": {}, + "type": "array" + }, + "helm-values.global.leaderElection": { + "properties": { + "leaseDuration": { + "$ref": "#/$defs/helm-values.global.leaderElection.leaseDuration" + }, + "namespace": { + "$ref": "#/$defs/helm-values.global.leaderElection.namespace" + }, + "renewDeadline": { + "$ref": "#/$defs/helm-values.global.leaderElection.renewDeadline" + }, + "retryPeriod": { + "$ref": "#/$defs/helm-values.global.leaderElection.retryPeriod" + } + }, + "type": "object" + }, + "helm-values.global.leaderElection.leaseDuration": { + "description": "The duration that non-leader candidates will wait after observing a leadership renewal until attempting to acquire leadership of a led but unrenewed leader slot. This is effectively the maximum duration that a leader can be stopped before it is replaced by another candidate.", + "type": "string" + }, + "helm-values.global.leaderElection.namespace": { + "default": "kube-system", + "description": "Override the namespace used for the leader election lease.", + "type": "string" + }, + "helm-values.global.leaderElection.renewDeadline": { + "description": "The interval between attempts by the acting master to renew a leadership slot before it stops leading. This must be less than or equal to the lease duration.", + "type": "string" + }, + "helm-values.global.leaderElection.retryPeriod": { + "description": "The duration the clients should wait between attempting acquisition and renewal of a leadership.", + "type": "string" + }, + "helm-values.global.logLevel": { + "default": 2, + "description": "Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose.", + "type": "number" + }, + "helm-values.global.podSecurityPolicy": { + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.global.podSecurityPolicy.enabled" + }, + "useAppArmor": { + "$ref": "#/$defs/helm-values.global.podSecurityPolicy.useAppArmor" + } + }, + "type": "object" + }, + "helm-values.global.podSecurityPolicy.enabled": { + "default": false, + "description": "Create PodSecurityPolicy for cert-manager.\n\nNote that PodSecurityPolicy was deprecated in Kubernetes 1.21 and removed in Kubernetes 1.25.", + "type": "boolean" + }, + "helm-values.global.podSecurityPolicy.useAppArmor": { + "default": true, + "description": "Configure the PodSecurityPolicy to use AppArmor.", + "type": "boolean" + }, + "helm-values.global.priorityClassName": { + "default": "", + "description": "The optional priority class to be used for the cert-manager pods.", + "type": "string" + }, + "helm-values.global.rbac": { + "properties": { + "aggregateClusterRoles": { + "$ref": "#/$defs/helm-values.global.rbac.aggregateClusterRoles" + }, + "create": { + "$ref": "#/$defs/helm-values.global.rbac.create" + } + }, + "type": "object" + }, + "helm-values.global.rbac.aggregateClusterRoles": { + "default": true, + "description": "Aggregate ClusterRoles to Kubernetes default user-facing roles. For more information, see [User-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)", + "type": "boolean" + }, + "helm-values.global.rbac.create": { + "default": true, + "description": "Create required ClusterRoles and ClusterRoleBindings for cert-manager.", + "type": "boolean" + }, + "helm-values.global.revisionHistoryLimit": { + "description": "The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10).", + "type": "number" + }, + "helm-values.hostAliases": { + "default": [], + "description": "Optional hostAliases for cert-manager-controller pods. May be useful when performing ACME DNS-01 self checks.", + "items": {}, + "type": "array" + }, + "helm-values.http_proxy": { + "description": "Configures the HTTP_PROXY environment variable where a HTTP proxy is required.", + "type": "string" + }, + "helm-values.https_proxy": { + "description": "Configures the HTTPS_PROXY environment variable where a HTTP proxy is required.", + "type": "string" + }, + "helm-values.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.image.tag" + } + }, + "type": "object" + }, + "helm-values.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.image.registry": { + "description": "The container registry to pull the manager image from.", + "type": "string" + }, + "helm-values.image.repository": { + "default": "quay.io/jetstack/cert-manager-controller", + "description": "The container image for the cert-manager controller.", + "type": "string" + }, + "helm-values.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used.", + "type": "string" + }, + "helm-values.ingressShim": { + "additionalProperties": false, + "properties": { + "defaultIssuerGroup": { + "$ref": "#/$defs/helm-values.ingressShim.defaultIssuerGroup" + }, + "defaultIssuerKind": { + "$ref": "#/$defs/helm-values.ingressShim.defaultIssuerKind" + }, + "defaultIssuerName": { + "$ref": "#/$defs/helm-values.ingressShim.defaultIssuerName" + } + }, + "type": "object" + }, + "helm-values.ingressShim.defaultIssuerGroup": { + "description": "Optional default issuer group to use for ingress resources.", + "type": "string" + }, + "helm-values.ingressShim.defaultIssuerKind": { + "description": "Optional default issuer kind to use for ingress resources.", + "type": "string" + }, + "helm-values.ingressShim.defaultIssuerName": { + "description": "Optional default issuer to use for ingress resources.", + "type": "string" + }, + "helm-values.installCRDs": { + "default": false, + "description": "This option is equivalent to setting crds.enabled=true and crds.keep=true. Deprecated: use crds.enabled and crds.keep instead.", + "type": "boolean" + }, + "helm-values.livenessProbe": { + "default": { + "enabled": true, + "failureThreshold": 8, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 15 + }, + "description": "LivenessProbe settings for the controller container of the controller Pod.\n\nThis is enabled by default, in order to enable the clock-skew liveness probe that restarts the controller in case of a skew between the system clock and the monotonic clock. LivenessProbe durations and thresholds are based on those used for the Kubernetes controller-manager. For more information see the following on the\n[Kubernetes GitHub repository](https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245)", + "type": "object" + }, + "helm-values.maxConcurrentChallenges": { + "default": 60, + "description": "The maximum number of challenges that can be scheduled as 'processing' at once.", + "type": "number" + }, + "helm-values.nameOverride": { + "description": "Override the \"cert-manager.name\" value, which is used to annotate some of the resources that are created by this Chart (using \"app.kubernetes.io/name\"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use eg. \"cainjector.name\" which resolves to the value \"cainjector\").", + "type": "string" + }, + "helm-values.namespace": { + "default": "", + "description": "This namespace allows you to define where the services are installed into. If not set then they use the namespace of the release. This is helpful when installing cert manager as a chart dependency (sub chart).", + "type": "string" + }, + "helm-values.no_proxy": { + "description": "Configures the NO_PROXY environment variable where a HTTP proxy is required, but certain domains should be excluded.", + "type": "string" + }, + "helm-values.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.podAnnotations": { + "description": "Optional additional annotations to add to the controller Pods.", + "type": "object" + }, + "helm-values.podDisruptionBudget": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.podDisruptionBudget.enabled" + }, + "maxUnavailable": { + "$ref": "#/$defs/helm-values.podDisruptionBudget.maxUnavailable" + }, + "minAvailable": { + "$ref": "#/$defs/helm-values.podDisruptionBudget.minAvailable" + } + }, + "type": "object" + }, + "helm-values.podDisruptionBudget.enabled": { + "default": false, + "description": "Enable or disable the PodDisruptionBudget resource.\n\nThis prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager\nPod is currently running.", + "type": "boolean" + }, + "helm-values.podDisruptionBudget.maxUnavailable": { + "description": "This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). it cannot be used if `minAvailable` is set." + }, + "helm-values.podDisruptionBudget.minAvailable": { + "description": "This configures the minimum available pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `maxUnavailable` is set." + }, + "helm-values.podDnsConfig": { + "description": "Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy settings. However, when a Pod's dnsPolicy is set to \"None\", the dnsConfig field has to be specified. For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config).", + "type": "object" + }, + "helm-values.podDnsPolicy": { + "description": "Pod DNS policy.\nFor more information, see [Pod's DNS Policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy).", + "type": "string" + }, + "helm-values.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the controller Pods.", + "type": "object" + }, + "helm-values.prometheus": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.prometheus.enabled" + }, + "podmonitor": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor" + }, + "servicemonitor": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor" + } + }, + "type": "object" + }, + "helm-values.prometheus.enabled": { + "default": true, + "description": "Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a\nServiceMonitor resource.\nOtherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error.", + "type": "boolean" + }, + "helm-values.prometheus.podmonitor": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.annotations" + }, + "enabled": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.enabled" + }, + "endpointAdditionalProperties": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.endpointAdditionalProperties" + }, + "honorLabels": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.honorLabels" + }, + "interval": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.interval" + }, + "labels": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.labels" + }, + "namespace": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.namespace" + }, + "path": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.path" + }, + "prometheusInstance": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.prometheusInstance" + }, + "scrapeTimeout": { + "$ref": "#/$defs/helm-values.prometheus.podmonitor.scrapeTimeout" + } + }, + "type": "object" + }, + "helm-values.prometheus.podmonitor.annotations": { + "default": {}, + "description": "Additional annotations to add to the PodMonitor.", + "type": "object" + }, + "helm-values.prometheus.podmonitor.enabled": { + "default": false, + "description": "Create a PodMonitor to add cert-manager to Prometheus.", + "type": "boolean" + }, + "helm-values.prometheus.podmonitor.endpointAdditionalProperties": { + "default": {}, + "description": "EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc.\n\nFor example:\nendpointAdditionalProperties:\n relabelings:\n - action: replace\n sourceLabels:\n - __meta_kubernetes_pod_node_name\n targetLabel: instance\n # Configure the PodMonitor for TLS connections\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n scheme: https\n tlsConfig:\n serverName: cert-manager-metrics\n ca:\n secret:\n name: cert-manager-metrics-ca\n key: \"tls.crt\"", + "type": "object" + }, + "helm-values.prometheus.podmonitor.honorLabels": { + "default": false, + "description": "Keep labels from scraped data, overriding server-side labels.", + "type": "boolean" + }, + "helm-values.prometheus.podmonitor.interval": { + "default": "60s", + "description": "The interval to scrape metrics.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.labels": { + "default": {}, + "description": "Additional labels to add to the PodMonitor.", + "type": "object" + }, + "helm-values.prometheus.podmonitor.namespace": { + "description": "The namespace that the pod monitor should live in, defaults to the cert-manager namespace.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.path": { + "default": "/metrics", + "description": "The path to scrape for metrics.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.prometheusInstance": { + "default": "default", + "description": "Specifies the `prometheus` label on the created PodMonitor. This is used when different Prometheus instances have label selectors matching different PodMonitors.", + "type": "string" + }, + "helm-values.prometheus.podmonitor.scrapeTimeout": { + "default": "30s", + "description": "The timeout before a metrics scrape fails.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.annotations" + }, + "enabled": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.enabled" + }, + "endpointAdditionalProperties": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.endpointAdditionalProperties" + }, + "honorLabels": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.honorLabels" + }, + "interval": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.interval" + }, + "labels": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.labels" + }, + "namespace": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.namespace" + }, + "path": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.path" + }, + "prometheusInstance": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.prometheusInstance" + }, + "scrapeTimeout": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.scrapeTimeout" + }, + "targetPort": { + "$ref": "#/$defs/helm-values.prometheus.servicemonitor.targetPort" + } + }, + "type": "object" + }, + "helm-values.prometheus.servicemonitor.annotations": { + "default": {}, + "description": "Additional annotations to add to the ServiceMonitor.", + "type": "object" + }, + "helm-values.prometheus.servicemonitor.enabled": { + "default": false, + "description": "Create a ServiceMonitor to add cert-manager to Prometheus.", + "type": "boolean" + }, + "helm-values.prometheus.servicemonitor.endpointAdditionalProperties": { + "default": {}, + "description": "EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc.\n\nFor example:\nendpointAdditionalProperties:\n relabelings:\n - action: replace\n sourceLabels:\n - __meta_kubernetes_pod_node_name\n targetLabel: instance", + "type": "object" + }, + "helm-values.prometheus.servicemonitor.honorLabels": { + "default": false, + "description": "Keep labels from scraped data, overriding server-side labels.", + "type": "boolean" + }, + "helm-values.prometheus.servicemonitor.interval": { + "default": "60s", + "description": "The interval to scrape metrics.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.labels": { + "default": {}, + "description": "Additional labels to add to the ServiceMonitor.", + "type": "object" + }, + "helm-values.prometheus.servicemonitor.namespace": { + "description": "The namespace that the service monitor should live in, defaults to the cert-manager namespace.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.path": { + "default": "/metrics", + "description": "The path to scrape for metrics.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.prometheusInstance": { + "default": "default", + "description": "Specifies the `prometheus` label on the created ServiceMonitor. This is used when different Prometheus instances have label selectors matching different ServiceMonitors.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.scrapeTimeout": { + "default": "30s", + "description": "The timeout before a metrics scrape fails.", + "type": "string" + }, + "helm-values.prometheus.servicemonitor.targetPort": { + "default": 9402, + "description": "The target port to set on the ServiceMonitor. This must match the port that the cert-manager controller is listening on for metrics.", + "type": "number" + }, + "helm-values.replicaCount": { + "default": 1, + "description": "The number of replicas of the cert-manager controller to run.\n\nThe default is 1, but in production set this to 2 or 3 to provide high availability.\n\nIf `replicas > 1`, consider setting `podDisruptionBudget.enabled=true`.\n\nNote that cert-manager uses leader election to ensure that there can only be a single instance active at a time.", + "type": "number" + }, + "helm-values.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager controller pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context.\nFor more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.serviceAccount.annotations": { + "description": "Optional additional annotations to add to the controller's Service Account.", + "type": "object" + }, + "helm-values.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.serviceAccount.labels": { + "description": "Optional additional labels to add to the controller's Service Account.", + "type": "object" + }, + "helm-values.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template.", + "type": "string" + }, + "helm-values.serviceAnnotations": { + "description": "Optional annotations to add to the controller Service.", + "type": "object" + }, + "helm-values.serviceIPFamilies": { + "description": "Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6.", + "items": {}, + "type": "array" + }, + "helm-values.serviceIPFamilyPolicy": { + "description": "Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services).", + "type": "string" + }, + "helm-values.serviceLabels": { + "description": "Optional additional labels to add to the controller Service.", + "type": "object" + }, + "helm-values.startupapicheck": { + "additionalProperties": false, + "properties": { + "affinity": { + "$ref": "#/$defs/helm-values.startupapicheck.affinity" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.startupapicheck.automountServiceAccountToken" + }, + "backoffLimit": { + "$ref": "#/$defs/helm-values.startupapicheck.backoffLimit" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.startupapicheck.containerSecurityContext" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.startupapicheck.enableServiceLinks" + }, + "enabled": { + "$ref": "#/$defs/helm-values.startupapicheck.enabled" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.startupapicheck.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.startupapicheck.extraEnv" + }, + "image": { + "$ref": "#/$defs/helm-values.startupapicheck.image" + }, + "jobAnnotations": { + "$ref": "#/$defs/helm-values.startupapicheck.jobAnnotations" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.startupapicheck.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.startupapicheck.podAnnotations" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.startupapicheck.podLabels" + }, + "rbac": { + "$ref": "#/$defs/helm-values.startupapicheck.rbac" + }, + "resources": { + "$ref": "#/$defs/helm-values.startupapicheck.resources" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.startupapicheck.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount" + }, + "timeout": { + "$ref": "#/$defs/helm-values.startupapicheck.timeout" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.startupapicheck.tolerations" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.startupapicheck.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.startupapicheck.volumes" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.startupapicheck.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.startupapicheck.backoffLimit": { + "default": 4, + "description": "Job backoffLimit", + "type": "number" + }, + "helm-values.startupapicheck.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the controller component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.startupapicheck.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.startupapicheck.enabled": { + "default": true, + "description": "Enables the startup api check.", + "type": "boolean" + }, + "helm-values.startupapicheck.extraArgs": { + "default": [ + "-v" + ], + "description": "Additional command line flags to pass to startupapicheck binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-startupapicheck: --help`.\n\nVerbose logging is enabled by default so that if startupapicheck fails, you can know what exactly caused the failure. Verbose logs include details of the webhook URL, IP address and TCP connect errors for example.", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager startupapicheck binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.startupapicheck.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.startupapicheck.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.startupapicheck.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.startupapicheck.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.startupapicheck.image.tag" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.image.digest": { + "description": "Setting a digest will override any tag.", + "type": "string" + }, + "helm-values.startupapicheck.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.startupapicheck.image.registry": { + "description": "The container registry to pull the startupapicheck image from.", + "type": "string" + }, + "helm-values.startupapicheck.image.repository": { + "default": "quay.io/jetstack/cert-manager-startupapicheck", + "description": "The container image for the cert-manager startupapicheck.", + "type": "string" + }, + "helm-values.startupapicheck.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion is used.", + "type": "string" + }, + "helm-values.startupapicheck.jobAnnotations": { + "default": { + "helm.sh/hook": "post-install", + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded", + "helm.sh/hook-weight": "1" + }, + "description": "Optional additional annotations to add to the startupapicheck Job.", + "type": "object" + }, + "helm-values.startupapicheck.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.startupapicheck.podAnnotations": { + "description": "Optional additional annotations to add to the startupapicheck Pods.", + "type": "object" + }, + "helm-values.startupapicheck.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the startupapicheck Pods.", + "type": "object" + }, + "helm-values.startupapicheck.rbac": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.startupapicheck.rbac.annotations" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.rbac.annotations": { + "default": { + "helm.sh/hook": "post-install", + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded", + "helm.sh/hook-weight": "-5" + }, + "description": "annotations for the startup API Check job RBAC and PSP resources.", + "type": "object" + }, + "helm-values.startupapicheck.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager controller pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.startupapicheck.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context to be set on the startupapicheck component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.startupapicheck.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount.annotations": { + "default": { + "helm.sh/hook": "post-install", + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded", + "helm.sh/hook-weight": "-5" + }, + "description": "Optional additional annotations to add to the Job's Service Account.", + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.startupapicheck.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.startupapicheck.serviceAccount.labels": { + "description": "Optional additional labels to add to the startupapicheck's Service Account.", + "type": "object" + }, + "helm-values.startupapicheck.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template.", + "type": "string" + }, + "helm-values.startupapicheck.timeout": { + "default": "1m", + "description": "Timeout for 'kubectl check api' command.", + "type": "string" + }, + "helm-values.startupapicheck.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.startupapicheck.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + }, + "helm-values.strategy": { + "default": {}, + "description": "Deployment update strategy for the cert-manager controller deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy).\n\nFor example:\nstrategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 0\n maxUnavailable: 1", + "type": "object" + }, + "helm-values.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.topologySpreadConstraints": { + "default": [], + "description": "A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core\n\nFor example:\ntopologySpreadConstraints:\n- maxSkew: 2\n topologyKey: topology.kubernetes.io/zone\n whenUnsatisfiable: ScheduleAnyway\n labelSelector:\n matchLabels:\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/component: controller", + "items": {}, + "type": "array" + }, + "helm-values.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + }, + "helm-values.webhook": { + "additionalProperties": false, + "properties": { + "affinity": { + "$ref": "#/$defs/helm-values.webhook.affinity" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.webhook.automountServiceAccountToken" + }, + "config": { + "$ref": "#/$defs/helm-values.webhook.config" + }, + "containerSecurityContext": { + "$ref": "#/$defs/helm-values.webhook.containerSecurityContext" + }, + "deploymentAnnotations": { + "$ref": "#/$defs/helm-values.webhook.deploymentAnnotations" + }, + "enableServiceLinks": { + "$ref": "#/$defs/helm-values.webhook.enableServiceLinks" + }, + "extraArgs": { + "$ref": "#/$defs/helm-values.webhook.extraArgs" + }, + "extraEnv": { + "$ref": "#/$defs/helm-values.webhook.extraEnv" + }, + "featureGates": { + "$ref": "#/$defs/helm-values.webhook.featureGates" + }, + "hostNetwork": { + "$ref": "#/$defs/helm-values.webhook.hostNetwork" + }, + "image": { + "$ref": "#/$defs/helm-values.webhook.image" + }, + "livenessProbe": { + "$ref": "#/$defs/helm-values.webhook.livenessProbe" + }, + "loadBalancerIP": { + "$ref": "#/$defs/helm-values.webhook.loadBalancerIP" + }, + "mutatingWebhookConfiguration": { + "$ref": "#/$defs/helm-values.webhook.mutatingWebhookConfiguration" + }, + "mutatingWebhookConfigurationAnnotations": { + "$ref": "#/$defs/helm-values.webhook.mutatingWebhookConfigurationAnnotations" + }, + "networkPolicy": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy" + }, + "nodeSelector": { + "$ref": "#/$defs/helm-values.webhook.nodeSelector" + }, + "podAnnotations": { + "$ref": "#/$defs/helm-values.webhook.podAnnotations" + }, + "podDisruptionBudget": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget" + }, + "podLabels": { + "$ref": "#/$defs/helm-values.webhook.podLabels" + }, + "readinessProbe": { + "$ref": "#/$defs/helm-values.webhook.readinessProbe" + }, + "replicaCount": { + "$ref": "#/$defs/helm-values.webhook.replicaCount" + }, + "resources": { + "$ref": "#/$defs/helm-values.webhook.resources" + }, + "securePort": { + "$ref": "#/$defs/helm-values.webhook.securePort" + }, + "securityContext": { + "$ref": "#/$defs/helm-values.webhook.securityContext" + }, + "serviceAccount": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount" + }, + "serviceAnnotations": { + "$ref": "#/$defs/helm-values.webhook.serviceAnnotations" + }, + "serviceIPFamilies": { + "$ref": "#/$defs/helm-values.webhook.serviceIPFamilies" + }, + "serviceIPFamilyPolicy": { + "$ref": "#/$defs/helm-values.webhook.serviceIPFamilyPolicy" + }, + "serviceLabels": { + "$ref": "#/$defs/helm-values.webhook.serviceLabels" + }, + "serviceType": { + "$ref": "#/$defs/helm-values.webhook.serviceType" + }, + "strategy": { + "$ref": "#/$defs/helm-values.webhook.strategy" + }, + "timeoutSeconds": { + "$ref": "#/$defs/helm-values.webhook.timeoutSeconds" + }, + "tolerations": { + "$ref": "#/$defs/helm-values.webhook.tolerations" + }, + "topologySpreadConstraints": { + "$ref": "#/$defs/helm-values.webhook.topologySpreadConstraints" + }, + "url": { + "$ref": "#/$defs/helm-values.webhook.url" + }, + "validatingWebhookConfiguration": { + "$ref": "#/$defs/helm-values.webhook.validatingWebhookConfiguration" + }, + "validatingWebhookConfigurationAnnotations": { + "$ref": "#/$defs/helm-values.webhook.validatingWebhookConfigurationAnnotations" + }, + "volumeMounts": { + "$ref": "#/$defs/helm-values.webhook.volumeMounts" + }, + "volumes": { + "$ref": "#/$defs/helm-values.webhook.volumes" + } + }, + "type": "object" + }, + "helm-values.webhook.affinity": { + "default": {}, + "description": "A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core).\n\nFor example:\naffinity:\n nodeAffinity:\n requiredDuringSchedulingIgnoredDuringExecution:\n nodeSelectorTerms:\n - matchExpressions:\n - key: foo.bar.com/role\n operator: In\n values:\n - master", + "type": "object" + }, + "helm-values.webhook.automountServiceAccountToken": { + "description": "Automounting API credentials for a particular pod.", + "type": "boolean" + }, + "helm-values.webhook.config": { + "default": {}, + "description": "This is used to configure options for the webhook pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\napiVersion: webhook.config.cert-manager.io/v1alpha1\nkind: WebhookConfiguration\n# The port that the webhook listens on for requests.\n# In GKE private clusters, by default Kubernetes apiservers are allowed to\n# talk to the cluster nodes only on 443 and 10250. Configuring\n# securePort: 10250 therefore will work out-of-the-box without needing to add firewall\n# rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000.\n# This should be uncommented and set as a default by the chart once\n# the apiVersion of WebhookConfiguration graduates beyond v1alpha1.\nsecurePort: 10250\n# Configure the metrics server for TLS\n# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\nmetricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "type": "object" + }, + "helm-values.webhook.containerSecurityContext": { + "default": { + "allowPrivilegeEscalation": false, + "capabilities": { + "drop": [ + "ALL" + ] + }, + "readOnlyRootFilesystem": true + }, + "description": "Container Security Context to be set on the webhook component container. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.webhook.deploymentAnnotations": { + "description": "Optional additional annotations to add to the webhook Deployment.", + "type": "object" + }, + "helm-values.webhook.enableServiceLinks": { + "default": false, + "description": "enableServiceLinks indicates whether information about services should be injected into the pod's environment variables, matching the syntax of Docker links.", + "type": "boolean" + }, + "helm-values.webhook.extraArgs": { + "default": [], + "description": "Additional command line flags to pass to cert-manager webhook binary. To see all available flags run `docker run quay.io/jetstack/cert-manager-webhook: --help`.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.extraEnv": { + "default": [], + "description": "Additional environment variables to pass to cert-manager webhook binary.\nFor example:\nextraEnv:\n- name: SOME_VAR\n value: 'some value'", + "items": {}, + "type": "array" + }, + "helm-values.webhook.featureGates": { + "default": "", + "description": "Comma separated list of feature gates that should be enabled on the webhook pod.", + "type": "string" + }, + "helm-values.webhook.hostNetwork": { + "default": false, + "description": "Specifies if the webhook should be started in hostNetwork mode.\n\nRequired for use in some managed kubernetes clusters (such as AWS EKS) with custom. CNI (such as calico), because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working\n\nSince the default port for the webhook conflicts with kubelet on the host network, `webhook.securePort` should be changed to an available port if running in hostNetwork mode.", + "type": "boolean" + }, + "helm-values.webhook.image": { + "additionalProperties": false, + "properties": { + "digest": { + "$ref": "#/$defs/helm-values.webhook.image.digest" + }, + "pullPolicy": { + "$ref": "#/$defs/helm-values.webhook.image.pullPolicy" + }, + "registry": { + "$ref": "#/$defs/helm-values.webhook.image.registry" + }, + "repository": { + "$ref": "#/$defs/helm-values.webhook.image.repository" + }, + "tag": { + "$ref": "#/$defs/helm-values.webhook.image.tag" + } + }, + "type": "object" + }, + "helm-values.webhook.image.digest": { + "description": "Setting a digest will override any tag", + "type": "string" + }, + "helm-values.webhook.image.pullPolicy": { + "default": "IfNotPresent", + "description": "Kubernetes imagePullPolicy on Deployment.", + "type": "string" + }, + "helm-values.webhook.image.registry": { + "description": "The container registry to pull the webhook image from.", + "type": "string" + }, + "helm-values.webhook.image.repository": { + "default": "quay.io/jetstack/cert-manager-webhook", + "description": "The container image for the cert-manager webhook", + "type": "string" + }, + "helm-values.webhook.image.tag": { + "description": "Override the image tag to deploy by setting this variable. If no value is set, the chart's appVersion will be used.", + "type": "string" + }, + "helm-values.webhook.livenessProbe": { + "default": { + "failureThreshold": 3, + "initialDelaySeconds": 60, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "description": "Liveness probe values.\nFor more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes).", + "type": "object" + }, + "helm-values.webhook.loadBalancerIP": { + "description": "Specify the load balancer IP for the created service.", + "type": "string" + }, + "helm-values.webhook.mutatingWebhookConfiguration": { + "additionalProperties": false, + "properties": { + "namespaceSelector": { + "$ref": "#/$defs/helm-values.webhook.mutatingWebhookConfiguration.namespaceSelector" + } + }, + "type": "object" + }, + "helm-values.webhook.mutatingWebhookConfiguration.namespaceSelector": { + "default": {}, + "description": "Configure spec.namespaceSelector for mutating webhooks.", + "type": "object" + }, + "helm-values.webhook.mutatingWebhookConfigurationAnnotations": { + "description": "Optional additional annotations to add to the webhook MutatingWebhookConfiguration.", + "type": "object" + }, + "helm-values.webhook.networkPolicy": { + "additionalProperties": false, + "properties": { + "egress": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy.egress" + }, + "enabled": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy.enabled" + }, + "ingress": { + "$ref": "#/$defs/helm-values.webhook.networkPolicy.ingress" + } + }, + "type": "object" + }, + "helm-values.webhook.networkPolicy.egress": { + "default": [ + { + "ports": [ + { + "port": 80, + "protocol": "TCP" + }, + { + "port": 443, + "protocol": "TCP" + }, + { + "port": 53, + "protocol": "TCP" + }, + { + "port": 53, + "protocol": "UDP" + }, + { + "port": 6443, + "protocol": "TCP" + } + ], + "to": [ + { + "ipBlock": { + "cidr": "0.0.0.0/0" + } + } + ] + } + ], + "description": "Egress rule for the webhook network policy. By default, it allows all outbound traffic to ports 80 and 443, as well as DNS ports.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.networkPolicy.enabled": { + "default": false, + "description": "Create network policies for the webhooks.", + "type": "boolean" + }, + "helm-values.webhook.networkPolicy.ingress": { + "default": [ + { + "from": [ + { + "ipBlock": { + "cidr": "0.0.0.0/0" + } + } + ] + } + ], + "description": "Ingress rule for the webhook network policy. By default, it allows all inbound traffic.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.nodeSelector": { + "default": { + "kubernetes.io/os": "linux" + }, + "description": "The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nThis default ensures that Pods are only scheduled to Linux nodes. It prevents Pods being scheduled to Windows nodes in a mixed OS cluster.", + "type": "object" + }, + "helm-values.webhook.podAnnotations": { + "description": "Optional additional annotations to add to the webhook Pods.", + "type": "object" + }, + "helm-values.webhook.podDisruptionBudget": { + "additionalProperties": false, + "properties": { + "enabled": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget.enabled" + }, + "maxUnavailable": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget.maxUnavailable" + }, + "minAvailable": { + "$ref": "#/$defs/helm-values.webhook.podDisruptionBudget.minAvailable" + } + }, + "type": "object" + }, + "helm-values.webhook.podDisruptionBudget.enabled": { + "default": false, + "description": "Enable or disable the PodDisruptionBudget resource.\n\nThis prevents downtime during voluntary disruptions such as during a Node upgrade. For example, the PodDisruptionBudget will block `kubectl drain` if it is used on the Node where the only remaining cert-manager\nPod is currently running.", + "type": "boolean" + }, + "helm-values.webhook.podDisruptionBudget.maxUnavailable": { + "description": "This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `minAvailable` is set." + }, + "helm-values.webhook.podDisruptionBudget.minAvailable": { + "description": "This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `maxUnavailable` is set." + }, + "helm-values.webhook.podLabels": { + "default": {}, + "description": "Optional additional labels to add to the Webhook Pods.", + "type": "object" + }, + "helm-values.webhook.readinessProbe": { + "default": { + "failureThreshold": 3, + "initialDelaySeconds": 5, + "periodSeconds": 5, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "description": "Readiness probe values.\nFor more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes).", + "type": "object" + }, + "helm-values.webhook.replicaCount": { + "default": 1, + "description": "Number of replicas of the cert-manager webhook to run.\n\nThe default is 1, but in production set this to 2 or 3 to provide high availability.\n\nIf `replicas > 1`, consider setting `webhook.podDisruptionBudget.enabled=true`.", + "type": "number" + }, + "helm-values.webhook.resources": { + "default": {}, + "description": "Resources to provide to the cert-manager webhook pod.\n\nFor example:\nrequests:\n cpu: 10m\n memory: 32Mi\nFor more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).", + "type": "object" + }, + "helm-values.webhook.securePort": { + "default": 10250, + "description": "The port that the webhook listens on for requests. In GKE private clusters, by default Kubernetes apiservers are allowed to talk to the cluster nodes only on 443 and 10250. Configuring securePort: 10250, therefore will work out-of-the-box without needing to add firewall rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000.", + "type": "number" + }, + "helm-values.webhook.securityContext": { + "default": { + "runAsNonRoot": true, + "seccompProfile": { + "type": "RuntimeDefault" + } + }, + "description": "Pod Security Context to be set on the webhook component Pod. For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).", + "type": "object" + }, + "helm-values.webhook.serviceAccount": { + "additionalProperties": false, + "properties": { + "annotations": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.annotations" + }, + "automountServiceAccountToken": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.automountServiceAccountToken" + }, + "create": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.create" + }, + "labels": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.labels" + }, + "name": { + "$ref": "#/$defs/helm-values.webhook.serviceAccount.name" + } + }, + "type": "object" + }, + "helm-values.webhook.serviceAccount.annotations": { + "description": "Optional additional annotations to add to the webhook's Service Account.", + "type": "object" + }, + "helm-values.webhook.serviceAccount.automountServiceAccountToken": { + "default": true, + "description": "Automount API credentials for a Service Account.", + "type": "boolean" + }, + "helm-values.webhook.serviceAccount.create": { + "default": true, + "description": "Specifies whether a service account should be created.", + "type": "boolean" + }, + "helm-values.webhook.serviceAccount.labels": { + "description": "Optional additional labels to add to the webhook's Service Account.", + "type": "object" + }, + "helm-values.webhook.serviceAccount.name": { + "description": "The name of the service account to use.\nIf not set and create is true, a name is generated using the fullname template.", + "type": "string" + }, + "helm-values.webhook.serviceAnnotations": { + "description": "Optional additional annotations to add to the webhook Service.", + "type": "object" + }, + "helm-values.webhook.serviceIPFamilies": { + "default": [], + "description": "Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.serviceIPFamilyPolicy": { + "default": "", + "description": "Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services).", + "type": "string" + }, + "helm-values.webhook.serviceLabels": { + "default": {}, + "description": "Optional additional labels to add to the Webhook Service.", + "type": "object" + }, + "helm-values.webhook.serviceType": { + "default": "ClusterIP", + "description": "Specifies how the service should be handled. Useful if you want to expose the webhook outside of the cluster. In some cases, the control plane cannot reach internal services.", + "type": "string" + }, + "helm-values.webhook.strategy": { + "default": {}, + "description": "The update strategy for the cert-manager webhook deployment. For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy)\n\nFor example:\nstrategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 0\n maxUnavailable: 1", + "type": "object" + }, + "helm-values.webhook.timeoutSeconds": { + "default": 30, + "description": "The number of seconds the API server should wait for the webhook to respond before treating the call as a failure. The value must be between 1 and 30 seconds. For more information, see\n[Validating webhook configuration v1](https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/).\n\nThe default is set to the maximum value of 30 seconds as users sometimes report that the connection between the K8S API server and the cert-manager webhook server times out. If *this* timeout is reached, the error message will be \"context deadline exceeded\", which doesn't help the user diagnose what phase of the HTTPS connection timed out. For example, it could be during DNS resolution, TCP connection, TLS negotiation, HTTP negotiation, or slow HTTP response from the webhook server. By setting this timeout to its maximum value the underlying timeout error message has more chance of being returned to the end user.", + "type": "number" + }, + "helm-values.webhook.tolerations": { + "default": [], + "description": "A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core).\n\nFor example:\ntolerations:\n- key: foo.bar.com/role\n operator: Equal\n value: master\n effect: NoSchedule", + "items": {}, + "type": "array" + }, + "helm-values.webhook.topologySpreadConstraints": { + "default": [], + "description": "A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core).\n\nFor example:\ntopologySpreadConstraints:\n- maxSkew: 2\n topologyKey: topology.kubernetes.io/zone\n whenUnsatisfiable: ScheduleAnyway\n labelSelector:\n matchLabels:\n app.kubernetes.io/instance: cert-manager\n app.kubernetes.io/component: controller", + "items": {}, + "type": "array" + }, + "helm-values.webhook.url": { + "default": {}, + "description": "Overrides the mutating webhook and validating webhook so they reach the webhook service using the `url` field instead of a service.", + "type": "object" + }, + "helm-values.webhook.validatingWebhookConfiguration": { + "additionalProperties": false, + "properties": { + "namespaceSelector": { + "$ref": "#/$defs/helm-values.webhook.validatingWebhookConfiguration.namespaceSelector" + } + }, + "type": "object" + }, + "helm-values.webhook.validatingWebhookConfiguration.namespaceSelector": { + "default": { + "matchExpressions": [ + { + "key": "cert-manager.io/disable-validation", + "operator": "NotIn", + "values": [ + "true" + ] + } + ] + }, + "description": "Configure spec.namespaceSelector for validating webhooks.", + "type": "object" + }, + "helm-values.webhook.validatingWebhookConfigurationAnnotations": { + "description": "Optional additional annotations to add to the webhook ValidatingWebhookConfiguration.", + "type": "object" + }, + "helm-values.webhook.volumeMounts": { + "default": [], + "description": "Additional volume mounts to add to the cert-manager controller container.", + "items": {}, + "type": "array" + }, + "helm-values.webhook.volumes": { + "default": [], + "description": "Additional volumes to add to the cert-manager controller pod.", + "items": {}, + "type": "array" + } + }, + "$ref": "#/$defs/helm-values", + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/packages/system/cert-manager-crds/charts/cert-manager/values.yaml b/packages/system/cert-manager-crds/charts/cert-manager/values.yaml new file mode 100644 index 00000000..7a1c2953 --- /dev/null +++ b/packages/system/cert-manager-crds/charts/cert-manager/values.yaml @@ -0,0 +1,1455 @@ +# +docs:section=Global + +# Default values for cert-manager. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +global: + # Reference to one or more secrets to be used when pulling images. + # For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). + # + # For example: + # imagePullSecrets: + # - name: "image-pull-secret" + imagePullSecrets: [] + + # Labels to apply to all resources. + # Please note that this does not add labels to the resources created dynamically by the controllers. + # For these resources, you have to add the labels in the template in the cert-manager custom resource: + # For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress + # For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress). + # For example, secretTemplate in CertificateSpec + # For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec). + commonLabels: {} + + # The number of old ReplicaSets to retain to allow rollback (if not set, the default Kubernetes value is set to 10). + # +docs:property + # revisionHistoryLimit: 1 + + # The optional priority class to be used for the cert-manager pods. + priorityClassName: "" + + rbac: + # Create required ClusterRoles and ClusterRoleBindings for cert-manager. + create: true + # Aggregate ClusterRoles to Kubernetes default user-facing roles. For more information, see [User-facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) + aggregateClusterRoles: true + + podSecurityPolicy: + # Create PodSecurityPolicy for cert-manager. + # + # Note that PodSecurityPolicy was deprecated in Kubernetes 1.21 and removed in Kubernetes 1.25. + enabled: false + # Configure the PodSecurityPolicy to use AppArmor. + useAppArmor: true + + # Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose. + logLevel: 2 + + leaderElection: + # Override the namespace used for the leader election lease. + namespace: "kube-system" + + # The duration that non-leader candidates will wait after observing a + # leadership renewal until attempting to acquire leadership of a led but + # unrenewed leader slot. This is effectively the maximum duration that a + # leader can be stopped before it is replaced by another candidate. + # +docs:property + # leaseDuration: 60s + + # The interval between attempts by the acting master to renew a leadership + # slot before it stops leading. This must be less than or equal to the + # lease duration. + # +docs:property + # renewDeadline: 40s + + # The duration the clients should wait between attempting acquisition and + # renewal of a leadership. + # +docs:property + # retryPeriod: 15s + +# This option is equivalent to setting crds.enabled=true and crds.keep=true. +# Deprecated: use crds.enabled and crds.keep instead. +installCRDs: false + +crds: + # This option decides if the CRDs should be installed + # as part of the Helm installation. + enabled: false + + # This option makes it so that the "helm.sh/resource-policy": keep + # annotation is added to the CRD. This will prevent Helm from uninstalling + # the CRD when the Helm release is uninstalled. + # WARNING: when the CRDs are removed, all cert-manager custom resources + # (Certificates, Issuers, ...) will be removed too by the garbage collector. + keep: true + +# +docs:section=Controller + +# The number of replicas of the cert-manager controller to run. +# +# The default is 1, but in production set this to 2 or 3 to provide high +# availability. +# +# If `replicas > 1`, consider setting `podDisruptionBudget.enabled=true`. +# +# Note that cert-manager uses leader election to ensure that there can +# only be a single instance active at a time. +replicaCount: 1 + +# Deployment update strategy for the cert-manager controller deployment. +# For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). +# +# For example: +# strategy: +# type: RollingUpdate +# rollingUpdate: +# maxSurge: 0 +# maxUnavailable: 1 +strategy: {} + +podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + + # This configures the minimum available pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `maxUnavailable` is set. + # +docs:property + # +docs:type=unknown + # minAvailable: 1 + + # This configures the maximum unavailable pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # it cannot be used if `minAvailable` is set. + # +docs:property + # +docs:type=unknown + # maxUnavailable: 1 + +# A comma-separated list of feature gates that should be enabled on the +# controller pod. +featureGates: "" + +# The maximum number of challenges that can be scheduled as 'processing' at once. +maxConcurrentChallenges: 60 + +image: + # The container registry to pull the manager image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager controller. + # +docs:property + repository: quay.io/jetstack/cert-manager-controller + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + +# Override the namespace used to store DNS provider credentials etc. for ClusterIssuer +# resources. By default, the same namespace as cert-manager is deployed within is +# used. This namespace will not be automatically created by the Helm chart. +clusterResourceNamespace: "" + +# This namespace allows you to define where the services are installed into. +# If not set then they use the namespace of the release. +# This is helpful when installing cert manager as a chart dependency (sub chart). +namespace: "" + +# Override the "cert-manager.fullname" value. This value is used as part of +# most of the names of the resources created by this Helm chart. +# +docs:property +# fullnameOverride: "my-cert-manager" + +# Override the "cert-manager.name" value, which is used to annotate some of +# the resources that are created by this Chart (using "app.kubernetes.io/name"). +# NOTE: There are some inconsistencies in the Helm chart when it comes to +# these annotations (some resources use eg. "cainjector.name" which resolves +# to the value "cainjector"). +# +docs:property +# nameOverride: "my-cert-manager" + +serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + # +docs:property + # name: "" + + # Optional additional annotations to add to the controller's Service Account. + # +docs:property + # annotations: {} + + # Optional additional labels to add to the controller's Service Account. + # +docs:property + # labels: {} + + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + +# Automounting API credentials for a particular pod. +# +docs:property +# automountServiceAccountToken: true + +# When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted. +enableCertificateOwnerRef: false + +# This property is used to configure options for the controller pod. +# This allows setting options that would usually be provided using flags. +# +# If `apiVersion` and `kind` are unspecified they default to the current latest +# version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin +# the version by specifying the `apiVersion` yourself. +# +# For example: +# config: +# apiVersion: controller.config.cert-manager.io/v1alpha1 +# kind: ControllerConfiguration +# logging: +# verbosity: 2 +# format: text +# leaderElectionConfig: +# namespace: kube-system +# kubernetesAPIQPS: 9000 +# kubernetesAPIBurst: 9000 +# numberOfConcurrentWorkers: 200 +# featureGates: +# AdditionalCertificateOutputFormats: true +# DisallowInsecureCSRUsageDefinition: true +# ExperimentalCertificateSigningRequestControllers: true +# ExperimentalGatewayAPISupport: true +# LiteralCertificateSubject: true +# SecretsFilteredCaching: true +# ServerSideApply: true +# StableCertificateRequestName: true +# UseCertificateRequestBasicConstraints: true +# ValidateCAA: true +# # Configure the metrics server for TLS +# # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls +# metricsTLSConfig: +# dynamic: +# secretNamespace: "cert-manager" +# secretName: "cert-manager-metrics-ca" +# dnsNames: +# - cert-manager-metrics +config: {} + +# Setting Nameservers for DNS01 Self Check. +# For more information, see the [cert-manager documentation](https://cert-manager.io/docs/configuration/acme/dns01/#setting-nameservers-for-dns01-self-check). + +# A comma-separated string with the host and port of the recursive nameservers cert-manager should query. +dns01RecursiveNameservers: "" + +# Forces cert-manager to use only the recursive nameservers for verification. +# Enabling this option could cause the DNS01 self check to take longer owing to caching performed by the recursive nameservers. +dns01RecursiveNameserversOnly: false + +# Option to disable cert-manager's build-in auto-approver. The auto-approver +# approves all CertificateRequests that reference issuers matching the 'approveSignerNames' +# option. This 'disableAutoApproval' option is useful when you want to make all approval decisions +# using a different approver (like approver-policy - https://github.com/cert-manager/approver-policy). +disableAutoApproval: false + +# List of signer names that cert-manager will approve by default. CertificateRequests +# referencing these signer names will be auto-approved by cert-manager. Defaults to just +# approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty +# array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, +# because eg. you are using approver-policy, you can enable 'disableAutoApproval'. +# ref: https://cert-manager.io/docs/concepts/certificaterequest/#approval +# +docs:property +approveSignerNames: +- issuers.cert-manager.io/* +- clusterissuers.cert-manager.io/* + +# Additional command line flags to pass to cert-manager controller binary. +# To see all available flags run `docker run quay.io/jetstack/cert-manager-controller: --help`. +# +# Use this flag to enable or disable arbitrary controllers. For example, to disable the CertificateRequests approver. +# +# For example: +# extraArgs: +# - --controllers=*,-certificaterequests-approver +extraArgs: [] + +# Additional environment variables to pass to cert-manager controller binary. +# For example: +# extraEnv: +# - name: SOME_VAR +# value: 'some value' +extraEnv: [] + +# Resources to provide to the cert-manager controller pod. +# +# For example: +# requests: +# cpu: 10m +# memory: 32Mi +# +# For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). +resources: {} + +# Pod Security Context. +# For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). +# +docs:property +securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + +# Container Security Context to be set on the controller component container. +# For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). +# +docs:property +containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + +# Additional volumes to add to the cert-manager controller pod. +volumes: [] + +# Additional volume mounts to add to the cert-manager controller container. +volumeMounts: [] + +# Optional additional annotations to add to the controller Deployment. +# +docs:property +# deploymentAnnotations: {} + +# Optional additional annotations to add to the controller Pods. +# +docs:property +# podAnnotations: {} + +# Optional additional labels to add to the controller Pods. +podLabels: {} + +# Optional annotations to add to the controller Service. +# +docs:property +# serviceAnnotations: {} + +# Optional additional labels to add to the controller Service. +# +docs:property +# serviceLabels: {} + +# Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). +# +docs:property +# serviceIPFamilyPolicy: "" + +# Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. +# +docs:property +# serviceIPFamilies: [] + +# Optional DNS settings. These are useful if you have a public and private DNS zone for +# the same domain on Route 53. The following is an example of ensuring +# cert-manager can access an ingress or DNS TXT records at all times. +# Note that this requires Kubernetes 1.10 or `CustomPodDNS` feature gate enabled for +# the cluster to work. + +# Pod DNS policy. +# For more information, see [Pod's DNS Policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). +# +docs:property +# podDnsPolicy: "None" + +# Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy +# settings. However, when a Pod's dnsPolicy is set to "None", the dnsConfig field has to be specified. +# For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config). +# +docs:property +# podDnsConfig: +# nameservers: +# - "1.1.1.1" +# - "8.8.8.8" + +# Optional hostAliases for cert-manager-controller pods. May be useful when performing ACME DNS-01 self checks. +hostAliases: [] +# - ip: 127.0.0.1 +# hostnames: +# - foo.local +# - bar.local +# - ip: 10.1.2.3 +# hostnames: +# - foo.remote +# - bar.remote + +# The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with +# matching labels. +# For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). +# +# This default ensures that Pods are only scheduled to Linux nodes. +# It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. +# +docs:property +nodeSelector: + kubernetes.io/os: linux + +# +docs:ignore +ingressShim: {} + + # Optional default issuer to use for ingress resources. + # +docs:property=ingressShim.defaultIssuerName + # defaultIssuerName: "" + + # Optional default issuer kind to use for ingress resources. + # +docs:property=ingressShim.defaultIssuerKind + # defaultIssuerKind: "" + + # Optional default issuer group to use for ingress resources. + # +docs:property=ingressShim.defaultIssuerGroup + # defaultIssuerGroup: "" + +# Use these variables to configure the HTTP_PROXY environment variables. + +# Configures the HTTP_PROXY environment variable where a HTTP proxy is required. +# +docs:property +# http_proxy: "http://proxy:8080" + +# Configures the HTTPS_PROXY environment variable where a HTTP proxy is required. +# +docs:property +# https_proxy: "https://proxy:8080" + +# Configures the NO_PROXY environment variable where a HTTP proxy is required, +# but certain domains should be excluded. +# +docs:property +# no_proxy: 127.0.0.1,localhost + + +# A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). +# +# For example: +# affinity: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: foo.bar.com/role +# operator: In +# values: +# - master +affinity: {} + +# A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). +# +# For example: +# tolerations: +# - key: foo.bar.com/role +# operator: Equal +# value: master +# effect: NoSchedule +tolerations: [] + +# A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core +# +# For example: +# topologySpreadConstraints: +# - maxSkew: 2 +# topologyKey: topology.kubernetes.io/zone +# whenUnsatisfiable: ScheduleAnyway +# labelSelector: +# matchLabels: +# app.kubernetes.io/instance: cert-manager +# app.kubernetes.io/component: controller +topologySpreadConstraints: [] + +# LivenessProbe settings for the controller container of the controller Pod. +# +# This is enabled by default, in order to enable the clock-skew liveness probe that +# restarts the controller in case of a skew between the system clock and the monotonic clock. +# LivenessProbe durations and thresholds are based on those used for the Kubernetes +# controller-manager. For more information see the following on the +# [Kubernetes GitHub repository](https://github.com/kubernetes/kubernetes/blob/806b30170c61a38fedd54cc9ede4cd6275a1ad3b/cmd/kubeadm/app/util/staticpod/utils.go#L241-L245) +# +docs:property +livenessProbe: + enabled: true + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 15 + successThreshold: 1 + failureThreshold: 8 + +# enableServiceLinks indicates whether information about services should be +# injected into the pod's environment variables, matching the syntax of Docker +# links. +enableServiceLinks: false + +# +docs:section=Prometheus + +prometheus: + # Enable Prometheus monitoring for the cert-manager controller and webhook. + # If you use the Prometheus Operator, set prometheus.podmonitor.enabled or + # prometheus.servicemonitor.enabled, to create a PodMonitor or a + # ServiceMonitor resource. + # Otherwise, 'prometheus.io' annotations are added to the cert-manager and + # cert-manager-webhook Deployments. + # Note that you can not enable both PodMonitor and ServiceMonitor as they are + # mutually exclusive. Enabling both will result in an error. + enabled: true + + servicemonitor: + # Create a ServiceMonitor to add cert-manager to Prometheus. + enabled: false + + # The namespace that the service monitor should live in, defaults + # to the cert-manager namespace. + # +docs:property + # namespace: cert-manager + + # Specifies the `prometheus` label on the created ServiceMonitor. This is + # used when different Prometheus instances have label selectors matching + # different ServiceMonitors. + prometheusInstance: default + + # The target port to set on the ServiceMonitor. This must match the port that the + # cert-manager controller is listening on for metrics. + targetPort: 9402 + + # The path to scrape for metrics. + path: /metrics + + # The interval to scrape metrics. + interval: 60s + + # The timeout before a metrics scrape fails. + scrapeTimeout: 30s + + # Additional labels to add to the ServiceMonitor. + labels: {} + + # Additional annotations to add to the ServiceMonitor. + annotations: {} + + # Keep labels from scraped data, overriding server-side labels. + honorLabels: false + + # EndpointAdditionalProperties allows setting additional properties on the + # endpoint such as relabelings, metricRelabelings etc. + # + # For example: + # endpointAdditionalProperties: + # relabelings: + # - action: replace + # sourceLabels: + # - __meta_kubernetes_pod_node_name + # targetLabel: instance + # + # +docs:property + endpointAdditionalProperties: {} + + # Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. + podmonitor: + # Create a PodMonitor to add cert-manager to Prometheus. + enabled: false + + # The namespace that the pod monitor should live in, defaults + # to the cert-manager namespace. + # +docs:property + # namespace: cert-manager + + # Specifies the `prometheus` label on the created PodMonitor. This is + # used when different Prometheus instances have label selectors matching + # different PodMonitors. + prometheusInstance: default + + # The path to scrape for metrics. + path: /metrics + + # The interval to scrape metrics. + interval: 60s + + # The timeout before a metrics scrape fails. + scrapeTimeout: 30s + + # Additional labels to add to the PodMonitor. + labels: {} + + # Additional annotations to add to the PodMonitor. + annotations: {} + + # Keep labels from scraped data, overriding server-side labels. + honorLabels: false + + # EndpointAdditionalProperties allows setting additional properties on the + # endpoint such as relabelings, metricRelabelings etc. + # + # For example: + # endpointAdditionalProperties: + # relabelings: + # - action: replace + # sourceLabels: + # - __meta_kubernetes_pod_node_name + # targetLabel: instance + # # Configure the PodMonitor for TLS connections + # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + # scheme: https + # tlsConfig: + # serverName: cert-manager-metrics + # ca: + # secret: + # name: cert-manager-metrics-ca + # key: "tls.crt" + # + # +docs:property + endpointAdditionalProperties: {} + +# +docs:section=Webhook + +webhook: + # Number of replicas of the cert-manager webhook to run. + # + # The default is 1, but in production set this to 2 or 3 to provide high + # availability. + # + # If `replicas > 1`, consider setting `webhook.podDisruptionBudget.enabled=true`. + replicaCount: 1 + + # The number of seconds the API server should wait for the webhook to respond before treating the call as a failure. + # The value must be between 1 and 30 seconds. For more information, see + # [Validating webhook configuration v1](https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/). + # + # The default is set to the maximum value of 30 seconds as + # users sometimes report that the connection between the K8S API server and + # the cert-manager webhook server times out. + # If *this* timeout is reached, the error message will be "context deadline exceeded", + # which doesn't help the user diagnose what phase of the HTTPS connection timed out. + # For example, it could be during DNS resolution, TCP connection, TLS + # negotiation, HTTP negotiation, or slow HTTP response from the webhook + # server. + # By setting this timeout to its maximum value the underlying timeout error + # message has more chance of being returned to the end user. + timeoutSeconds: 30 + + # This is used to configure options for the webhook pod. + # This allows setting options that would usually be provided using flags. + # + # If `apiVersion` and `kind` are unspecified they default to the current latest + # version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin + # the version by specifying the `apiVersion` yourself. + # + # For example: + # apiVersion: webhook.config.cert-manager.io/v1alpha1 + # kind: WebhookConfiguration + # # The port that the webhook listens on for requests. + # # In GKE private clusters, by default Kubernetes apiservers are allowed to + # # talk to the cluster nodes only on 443 and 10250. Configuring + # # securePort: 10250 therefore will work out-of-the-box without needing to add firewall + # # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000. + # # This should be uncommented and set as a default by the chart once + # # the apiVersion of WebhookConfiguration graduates beyond v1alpha1. + # securePort: 10250 + # # Configure the metrics server for TLS + # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + # metricsTLSConfig: + # dynamic: + # secretNamespace: "cert-manager" + # secretName: "cert-manager-metrics-ca" + # dnsNames: + # - cert-manager-metrics + config: {} + + # The update strategy for the cert-manager webhook deployment. + # For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) + # + # For example: + # strategy: + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + strategy: {} + + # Pod Security Context to be set on the webhook component Pod. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + # Container Security Context to be set on the webhook component container. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + + podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + + # This property configures the minimum available pods for disruptions. Can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `maxUnavailable` is set. + # +docs:property + # +docs:type=unknown + # minAvailable: 1 + + # This property configures the maximum unavailable pods for disruptions. Can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # It cannot be used if `minAvailable` is set. + # +docs:property + # +docs:type=unknown + # maxUnavailable: 1 + + # Optional additional annotations to add to the webhook Deployment. + # +docs:property + # deploymentAnnotations: {} + + # Optional additional annotations to add to the webhook Pods. + # +docs:property + # podAnnotations: {} + + # Optional additional annotations to add to the webhook Service. + # +docs:property + # serviceAnnotations: {} + + # Optional additional annotations to add to the webhook MutatingWebhookConfiguration. + # +docs:property + # mutatingWebhookConfigurationAnnotations: {} + + # Optional additional annotations to add to the webhook ValidatingWebhookConfiguration. + # +docs:property + # validatingWebhookConfigurationAnnotations: {} + + validatingWebhookConfiguration: + # Configure spec.namespaceSelector for validating webhooks. + # +docs:property + namespaceSelector: + matchExpressions: + - key: "cert-manager.io/disable-validation" + operator: "NotIn" + values: + - "true" + + mutatingWebhookConfiguration: + # Configure spec.namespaceSelector for mutating webhooks. + # +docs:property + namespaceSelector: {} + # matchLabels: + # key: value + # matchExpressions: + # - key: kubernetes.io/metadata.name + # operator: NotIn + # values: + # - kube-system + + + # Additional command line flags to pass to cert-manager webhook binary. + # To see all available flags run `docker run quay.io/jetstack/cert-manager-webhook: --help`. + extraArgs: [] + # Path to a file containing a WebhookConfiguration object used to configure the webhook. + # - --config= + + # Additional environment variables to pass to cert-manager webhook binary. + # For example: + # extraEnv: + # - name: SOME_VAR + # value: 'some value' + extraEnv: [] + + # Comma separated list of feature gates that should be enabled on the + # webhook pod. + featureGates: "" + + # Resources to provide to the cert-manager webhook pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + resources: {} + + # Liveness probe values. + # For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + # + # +docs:property + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 60 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + + # Readiness probe values. + # For more information, see [Container probes](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes). + # + # +docs:property + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property + nodeSelector: + kubernetes.io/os: linux + + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master + affinity: {} + + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule + tolerations: [] + + # A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + # + # For example: + # topologySpreadConstraints: + # - maxSkew: 2 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: cert-manager + # app.kubernetes.io/component: controller + topologySpreadConstraints: [] + + # Optional additional labels to add to the Webhook Pods. + podLabels: {} + + # Optional additional labels to add to the Webhook Service. + serviceLabels: {} + + # Optionally set the IP family policy for the controller Service to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). + serviceIPFamilyPolicy: "" + + # Optionally set the IP families for the controller Service that should be supported, in the order in which they should be applied to ClusterIP. Can be IPv4 and/or IPv6. + serviceIPFamilies: [] + + image: + # The container registry to pull the webhook image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager webhook + # +docs:property + repository: quay.io/jetstack/cert-manager-webhook + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + + serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + # +docs:property + # name: "" + + # Optional additional annotations to add to the webhook's Service Account. + # +docs:property + # annotations: {} + + # Optional additional labels to add to the webhook's Service Account. + # +docs:property + # labels: {} + + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + + # Automounting API credentials for a particular pod. + # +docs:property + # automountServiceAccountToken: true + + # The port that the webhook listens on for requests. + # In GKE private clusters, by default Kubernetes apiservers are allowed to + # talk to the cluster nodes only on 443 and 10250. Configuring + # securePort: 10250, therefore will work out-of-the-box without needing to add firewall + # rules or requiring NET_BIND_SERVICE capabilities to bind port numbers <1000. + securePort: 10250 + + # Specifies if the webhook should be started in hostNetwork mode. + # + # Required for use in some managed kubernetes clusters (such as AWS EKS) with custom + # CNI (such as calico), because control-plane managed by AWS cannot communicate + # with pods' IP CIDR and admission webhooks are not working + # + # Since the default port for the webhook conflicts with kubelet on the host + # network, `webhook.securePort` should be changed to an available port if + # running in hostNetwork mode. + hostNetwork: false + + # Specifies how the service should be handled. Useful if you want to expose the + # webhook outside of the cluster. In some cases, the control plane cannot + # reach internal services. + serviceType: ClusterIP + + # Specify the load balancer IP for the created service. + # +docs:property + # loadBalancerIP: "10.10.10.10" + + # Overrides the mutating webhook and validating webhook so they reach the webhook + # service using the `url` field instead of a service. + url: {} + # host: + + # Enables default network policies for webhooks. + networkPolicy: + # Create network policies for the webhooks. + enabled: false + + # Ingress rule for the webhook network policy. By default, it allows all + # inbound traffic. + # +docs:property + ingress: + - from: + - ipBlock: + cidr: 0.0.0.0/0 + + # Egress rule for the webhook network policy. By default, it allows all + # outbound traffic to ports 80 and 443, as well as DNS ports. + # +docs:property + egress: + - ports: + - port: 80 + protocol: TCP + - port: 443 + protocol: TCP + - port: 53 + protocol: TCP + - port: 53 + protocol: UDP + # On OpenShift and OKD, the Kubernetes API server listens on. + # port 6443. + - port: 6443 + protocol: TCP + to: + - ipBlock: + cidr: 0.0.0.0/0 + + # Additional volumes to add to the cert-manager controller pod. + volumes: [] + + # Additional volume mounts to add to the cert-manager controller container. + volumeMounts: [] + + # enableServiceLinks indicates whether information about services should be + # injected into the pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false + +# +docs:section=CA Injector + +cainjector: + # Create the CA Injector deployment + enabled: true + + # The number of replicas of the cert-manager cainjector to run. + # + # The default is 1, but in production set this to 2 or 3 to provide high + # availability. + # + # If `replicas > 1`, consider setting `cainjector.podDisruptionBudget.enabled=true`. + # + # Note that cert-manager uses leader election to ensure that there can + # only be a single instance active at a time. + replicaCount: 1 + + # This is used to configure options for the cainjector pod. + # It allows setting options that are usually provided via flags. + # + # If `apiVersion` and `kind` are unspecified they default to the current latest + # version (currently `cainjector.config.cert-manager.io/v1alpha1`). You can pin + # the version by specifying the `apiVersion` yourself. + # + # For example: + # apiVersion: cainjector.config.cert-manager.io/v1alpha1 + # kind: CAInjectorConfiguration + # logging: + # verbosity: 2 + # format: text + # leaderElectionConfig: + # namespace: kube-system + # # Configure the metrics server for TLS + # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls + # metricsTLSConfig: + # dynamic: + # secretNamespace: "cert-manager" + # secretName: "cert-manager-metrics-ca" + # dnsNames: + # - cert-manager-metrics + config: {} + + # Deployment update strategy for the cert-manager cainjector deployment. + # For more information, see the [Kubernetes documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy). + # + # For example: + # strategy: + # type: RollingUpdate + # rollingUpdate: + # maxSurge: 0 + # maxUnavailable: 1 + strategy: {} + + # Pod Security Context to be set on the cainjector component Pod + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + # Container Security Context to be set on the cainjector component container + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + + podDisruptionBudget: + # Enable or disable the PodDisruptionBudget resource. + # + # This prevents downtime during voluntary disruptions such as during a Node upgrade. + # For example, the PodDisruptionBudget will block `kubectl drain` + # if it is used on the Node where the only remaining cert-manager + # Pod is currently running. + enabled: false + + # `minAvailable` configures the minimum available pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # Cannot be used if `maxUnavailable` is set. + # +docs:property + # +docs:type=unknown + # minAvailable: 1 + + # `maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to + # an integer (e.g. 1) or a percentage value (e.g. 25%). + # Cannot be used if `minAvailable` is set. + # +docs:property + # +docs:type=unknown + # maxUnavailable: 1 + + # Optional additional annotations to add to the cainjector Deployment. + # +docs:property + # deploymentAnnotations: {} + + # Optional additional annotations to add to the cainjector Pods. + # +docs:property + # podAnnotations: {} + + # Optional additional annotations to add to the cainjector metrics Service. + # +docs:property + # serviceAnnotations: {} + + # Additional command line flags to pass to cert-manager cainjector binary. + # To see all available flags run `docker run quay.io/jetstack/cert-manager-cainjector: --help`. + extraArgs: [] + # Enable profiling for cainjector. + # - --enable-profiling=true + + # Additional environment variables to pass to cert-manager cainjector binary. + # For example: + # extraEnv: + # - name: SOME_VAR + # value: 'some value' + extraEnv: [] + + # Comma separated list of feature gates that should be enabled on the + # cainjector pod. + featureGates: "" + + # Resources to provide to the cert-manager cainjector pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + resources: {} + + + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property + nodeSelector: + kubernetes.io/os: linux + + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master + affinity: {} + + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule + tolerations: [] + + # A list of Kubernetes TopologySpreadConstraints, if required. For more information, see [Topology spread constraint v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#topologyspreadconstraint-v1-core). + # + # For example: + # topologySpreadConstraints: + # - maxSkew: 2 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: cert-manager + # app.kubernetes.io/component: controller + topologySpreadConstraints: [] + + # Optional additional labels to add to the CA Injector Pods. + podLabels: {} + + # Optional additional labels to add to the CA Injector metrics Service. + serviceLabels: {} + + image: + # The container registry to pull the cainjector image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager cainjector + # +docs:property + repository: quay.io/jetstack/cert-manager-cainjector + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion will be used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + + serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + # +docs:property + # name: "" + + # Optional additional annotations to add to the cainjector's Service Account. + # +docs:property + # annotations: {} + + # Optional additional labels to add to the cainjector's Service Account. + # +docs:property + # labels: {} + + # Automount API credentials for a Service Account. + automountServiceAccountToken: true + + # Automounting API credentials for a particular pod. + # +docs:property + # automountServiceAccountToken: true + + # Additional volumes to add to the cert-manager controller pod. + volumes: [] + + # Additional volume mounts to add to the cert-manager controller container. + volumeMounts: [] + + # enableServiceLinks indicates whether information about services should be + # injected into the pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false + +# +docs:section=ACME Solver + +acmesolver: + image: + # The container registry to pull the acmesolver image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager acmesolver. + # +docs:property + repository: quay.io/jetstack/cert-manager-acmesolver + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + +# +docs:section=Startup API Check +# This startupapicheck is a Helm post-install hook that waits for the webhook +# endpoints to become available. +# The check is implemented using a Kubernetes Job - if you are injecting mesh +# sidecar proxies into cert-manager pods, ensure that they +# are not injected into this Job's pod. Otherwise, the installation may time out +# owing to the Job never being completed because the sidecar proxy does not exit. +# For more information, see [this note](https://github.com/cert-manager/cert-manager/pull/4414). + +startupapicheck: + # Enables the startup api check. + enabled: true + + # Pod Security Context to be set on the startupapicheck component Pod. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + + # Container Security Context to be set on the controller component container. + # For more information, see [Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). + # +docs:property + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + + # Timeout for 'kubectl check api' command. + timeout: 1m + + # Job backoffLimit + backoffLimit: 4 + + # Optional additional annotations to add to the startupapicheck Job. + # +docs:property + jobAnnotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "1" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Optional additional annotations to add to the startupapicheck Pods. + # +docs:property + # podAnnotations: {} + + # Additional command line flags to pass to startupapicheck binary. + # To see all available flags run `docker run quay.io/jetstack/cert-manager-startupapicheck: --help`. + # + # Verbose logging is enabled by default so that if startupapicheck fails, you + # can know what exactly caused the failure. Verbose logs include details of + # the webhook URL, IP address and TCP connect errors for example. + # +docs:property + extraArgs: + - -v + + # Additional environment variables to pass to cert-manager startupapicheck binary. + # For example: + # extraEnv: + # - name: SOME_VAR + # value: 'some value' + extraEnv: [] + + # Resources to provide to the cert-manager controller pod. + # + # For example: + # requests: + # cpu: 10m + # memory: 32Mi + # + # For more information, see [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + resources: {} + + + # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with + # matching labels. + # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). + # + # This default ensures that Pods are only scheduled to Linux nodes. + # It prevents Pods being scheduled to Windows nodes in a mixed OS cluster. + # +docs:property + nodeSelector: + kubernetes.io/os: linux + + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). + # For example: + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: foo.bar.com/role + # operator: In + # values: + # - master + affinity: {} + + # A list of Kubernetes Tolerations, if required. For more information, see [Toleration v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core). + # + # For example: + # tolerations: + # - key: foo.bar.com/role + # operator: Equal + # value: master + # effect: NoSchedule + tolerations: [] + + # Optional additional labels to add to the startupapicheck Pods. + podLabels: {} + + image: + # The container registry to pull the startupapicheck image from. + # +docs:property + # registry: quay.io + + # The container image for the cert-manager startupapicheck. + # +docs:property + repository: quay.io/jetstack/cert-manager-startupapicheck + + # Override the image tag to deploy by setting this variable. + # If no value is set, the chart's appVersion is used. + # +docs:property + # tag: vX.Y.Z + + # Setting a digest will override any tag. + # +docs:property + # digest: sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20 + + # Kubernetes imagePullPolicy on Deployment. + pullPolicy: IfNotPresent + + rbac: + # annotations for the startup API Check job RBAC and PSP resources. + # +docs:property + annotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Automounting API credentials for a particular pod. + # +docs:property + # automountServiceAccountToken: true + + serviceAccount: + # Specifies whether a service account should be created. + create: true + + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + # +docs:property + # name: "" + + # Optional additional annotations to add to the Job's Service Account. + # +docs:property + annotations: + helm.sh/hook: post-install + helm.sh/hook-weight: "-5" + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + + # Automount API credentials for a Service Account. + # +docs:property + automountServiceAccountToken: true + + # Optional additional labels to add to the startupapicheck's Service Account. + # +docs:property + # labels: {} + + # Additional volumes to add to the cert-manager controller pod. + volumes: [] + + # Additional volume mounts to add to the cert-manager controller container. + volumeMounts: [] + + # enableServiceLinks indicates whether information about services should be + # injected into pod's environment variables, matching the syntax of Docker + # links. + enableServiceLinks: false + +# Create dynamic manifests via values. +# +# For example: +# extraObjects: +# - | +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: '{{ template "cert-manager.fullname" . }}-extra-configmap' +extraObjects: [] + +# Field used by our release pipeline to produce the static manifests. +# The field defaults to "helm" but is set to "static" when we render +# the static YAML manifests. +# +docs:hidden +creator: "helm" + +# Field that can be used as a condition when cert-manager is a dependency. +# This definition is only here as a placeholder such that it is included in +# the json schema. +# See https://helm.sh/docs/chart_best_practices/dependencies/#conditions-and-tags +# for more info. +# +docs:hidden +enabled: true diff --git a/packages/system/cert-manager-crds/templates/crd-acme.cert-manager.io_challenges.yaml b/packages/system/cert-manager-crds/templates/crd-acme.cert-manager.io_challenges.yaml deleted file mode 100644 index 5bed0cd8..00000000 --- a/packages/system/cert-manager-crds/templates/crd-acme.cert-manager.io_challenges.yaml +++ /dev/null @@ -1,3281 +0,0 @@ -{{- if or .Values.crds.enabled .Values.installCRDs }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: "challenges.acme.cert-manager.io" - {{- if .Values.crds.keep }} - annotations: - helm.sh/resource-policy: keep - {{- end }} - labels: - {{- include "cert-manager.crd-labels" . | nindent 4 }} -spec: - group: acme.cert-manager.io - names: - categories: - - cert-manager - - cert-manager-acme - kind: Challenge - listKind: ChallengeList - plural: challenges - singular: challenge - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.state - name: State - type: string - - jsonPath: .spec.dnsName - name: Domain - type: string - - jsonPath: .status.reason - name: Reason - priority: 1 - type: string - - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: Challenge is a type to represent a Challenge request with an ACME server - 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: - properties: - authorizationURL: - description: |- - The URL to the ACME Authorization resource that this - challenge is a part of. - type: string - dnsName: - description: |- - dnsName is the identifier that this challenge is for, e.g., example.com. - If the requested DNSName is a 'wildcard', this field MUST be set to the - non-wildcard domain, e.g., for `*.example.com`, it must be `example.com`. - type: string - issuerRef: - description: |- - References a properly configured ACME-type Issuer which should - be used to create this Challenge. - If the Issuer does not exist, processing will be retried. - If the Issuer is not an 'ACME' Issuer, an error will be returned and the - Challenge will be marked as failed. - properties: - group: - description: |- - Group of the issuer being referred to. - Defaults to 'cert-manager.io'. - type: string - kind: - description: |- - Kind of the issuer being referred to. - Defaults to 'Issuer'. - type: string - name: - description: Name of the issuer being referred to. - type: string - required: - - name - type: object - key: - description: |- - The ACME challenge key for this challenge - For HTTP01 challenges, this is the value that must be responded with to - complete the HTTP01 challenge in the format: - `.`. - For DNS01 challenges, this is the base64 encoded SHA256 sum of the - `.` - text that must be set as the TXT record content. - type: string - solver: - description: |- - Contains the domain solving configuration that should be used to - solve this challenge resource. - properties: - dns01: - description: |- - Configures cert-manager to attempt to complete authorizations by - performing the DNS01 challenge flow. - properties: - acmeDNS: - description: |- - Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage - DNS01 challenge records. - properties: - accountSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - host: - type: string - required: - - accountSecretRef - - host - type: object - akamai: - description: Use the Akamai DNS zone management API to manage DNS01 challenge records. - properties: - accessTokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientTokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - serviceConsumerDomain: - type: string - required: - - accessTokenSecretRef - - clientSecretSecretRef - - clientTokenSecretRef - - serviceConsumerDomain - type: object - azureDNS: - description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. - properties: - clientID: - description: |- - Auth: Azure Service Principal: - The ClientID of the Azure Service Principal used to authenticate with Azure DNS. - If set, ClientSecret and TenantID must also be set. - type: string - clientSecretSecretRef: - description: |- - Auth: Azure Service Principal: - A reference to a Secret containing the password associated with the Service Principal. - If set, ClientID and TenantID must also be set. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - environment: - description: name of the Azure environment (default AzurePublicCloud) - enum: - - AzurePublicCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureUSGovernmentCloud - type: string - hostedZoneName: - description: name of the DNS zone that should be used - type: string - managedIdentity: - description: |- - Auth: Azure Workload Identity or Azure Managed Service Identity: - Settings to enable Azure Workload Identity or Azure Managed Service Identity - If set, ClientID, ClientSecret and TenantID must not be set. - properties: - clientID: - description: client ID of the managed identity, cannot be used at the same time as resourceID - type: string - resourceID: - description: |- - resource ID of the managed identity, cannot be used at the same time as clientID - Cannot be used for Azure Managed Service Identity - type: string - tenantID: - description: tenant ID of the managed identity, cannot be used at the same time as resourceID - type: string - type: object - resourceGroupName: - description: resource group the DNS zone is located in - type: string - subscriptionID: - description: ID of the Azure subscription - type: string - tenantID: - description: |- - Auth: Azure Service Principal: - The TenantID of the Azure Service Principal used to authenticate with Azure DNS. - If set, ClientID and ClientSecret must also be set. - type: string - required: - - resourceGroupName - - subscriptionID - type: object - cloudDNS: - description: Use the Google Cloud DNS API to manage DNS01 challenge records. - properties: - hostedZoneName: - description: |- - HostedZoneName is an optional field that tells cert-manager in which - Cloud DNS zone the challenge record has to be created. - If left empty cert-manager will automatically choose a zone. - type: string - project: - type: string - serviceAccountSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - project - type: object - cloudflare: - description: Use the Cloudflare API to manage DNS01 challenge records. - properties: - apiKeySecretRef: - description: |- - API key to use to authenticate with Cloudflare. - Note: using an API token to authenticate is now the recommended method - as it allows greater control of permissions. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - apiTokenSecretRef: - description: API token used to authenticate with Cloudflare. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - email: - description: Email of the account, only required when using API key based authentication. - type: string - type: object - cnameStrategy: - description: |- - CNAMEStrategy configures how the DNS01 provider should handle CNAME - records when found in DNS zones. - enum: - - None - - Follow - type: string - digitalocean: - description: Use the DigitalOcean DNS API to manage DNS01 challenge records. - properties: - tokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - tokenSecretRef - type: object - rfc2136: - description: |- - Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) - to manage DNS01 challenge records. - properties: - nameserver: - description: |- - The IP address or hostname of an authoritative DNS server supporting - RFC2136 in the form host:port. If the host is an IPv6 address it must be - enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. - This field is required. - type: string - protocol: - description: Protocol to use for dynamic DNS update queries. Valid values are (case-sensitive) ``TCP`` and ``UDP``; ``UDP`` (default). - enum: - - TCP - - UDP - type: string - tsigAlgorithm: - description: |- - The TSIG Algorithm configured in the DNS supporting RFC2136. Used only - when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. - Supported values are (case-insensitive): ``HMACMD5`` (default), - ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. - type: string - tsigKeyName: - description: |- - The TSIG Key name configured in the DNS. - If ``tsigSecretSecretRef`` is defined, this field is required. - type: string - tsigSecretSecretRef: - description: |- - The name of the secret containing the TSIG value. - If ``tsigKeyName`` is defined, this field is required. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - nameserver - type: object - route53: - description: Use the AWS Route53 API to manage DNS01 challenge records. - properties: - accessKeyID: - description: |- - The AccessKeyID is used for authentication. - Cannot be set when SecretAccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - type: string - accessKeyIDSecretRef: - description: |- - The SecretAccessKey is used for authentication. If set, pull the AWS - access key ID from a key within a Kubernetes Secret. - Cannot be set when AccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - auth: - description: Auth configures how cert-manager authenticates. - properties: - kubernetes: - description: |- - Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity - by passing a bound ServiceAccount token. - properties: - serviceAccountRef: - description: |- - A reference to a service account that will be used to request a bound - token (also known as "projected token"). To use this field, you must - configure an RBAC rule to let cert-manager request a token. - properties: - audiences: - description: |- - TokenAudiences is an optional list of audiences to include in the - token passed to AWS. The default token consisting of the issuer's namespace - and name is always included. - If unset the audience defaults to `sts.amazonaws.com`. - items: - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: Name of the ServiceAccount used to request a token. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - required: - - kubernetes - type: object - hostedZoneID: - description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. - type: string - region: - description: |- - Override the AWS region. - - Route53 is a global service and does not have regional endpoints but the - region specified here (or via environment variables) is used as a hint to - help compute the correct AWS credential scope and partition when it - connects to Route53. See: - - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) - - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) - - If you omit this region field, cert-manager will use the region from - AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set - in the cert-manager controller Pod. - - The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). - Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: - [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). - In this case this `region` field value is ignored. - - The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). - Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: - [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), - In this case this `region` field value is ignored. - type: string - role: - description: |- - Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey - or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata - type: string - secretAccessKeySecretRef: - description: |- - The SecretAccessKey is used for authentication. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - type: object - webhook: - description: |- - Configure an external webhook based DNS01 challenge solver to manage - DNS01 challenge records. - properties: - config: - description: |- - Additional configuration that should be passed to the webhook apiserver - when challenges are processed. - This can contain arbitrary JSON data. - Secret values should not be specified in this stanza. - If secret values are needed (e.g., credentials for a DNS service), you - should use a SecretKeySelector to reference a Secret resource. - For details on the schema of this field, consult the webhook provider - implementation's documentation. - x-kubernetes-preserve-unknown-fields: true - groupName: - description: |- - The API group name that should be used when POSTing ChallengePayload - resources to the webhook apiserver. - This should be the same as the GroupName specified in the webhook - provider implementation. - type: string - solverName: - description: |- - The name of the solver to use, as defined in the webhook provider - implementation. - This will typically be the name of the provider, e.g., 'cloudflare'. - type: string - required: - - groupName - - solverName - type: object - type: object - http01: - description: |- - Configures cert-manager to attempt to complete authorizations by - performing the HTTP01 challenge flow. - It is not possible to obtain certificates for wildcard domain names - (e.g., `*.example.com`) using the HTTP01 challenge mechanism. - properties: - gatewayHTTPRoute: - description: |- - The Gateway API is a sig-network community API that models service networking - in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will - create HTTPRoutes with the specified labels in the same namespace as the challenge. - This solver is experimental, and fields / behaviour may change in the future. - properties: - labels: - additionalProperties: - type: string - description: |- - Custom labels that will be applied to HTTPRoutes created by cert-manager - while solving HTTP-01 challenges. - type: object - parentRefs: - description: |- - When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. - cert-manager needs to know which parentRefs should be used when creating - the HTTPRoute. Usually, the parentRef references a Gateway. See: - https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways - items: - description: |- - ParentReference identifies an API object (usually a Gateway) that can be considered - a parent of this resource (usually a route). There are two kinds of parent resources - with "Core" support: - - * Gateway (Gateway conformance profile) - * Service (Mesh conformance profile, ClusterIP Services only) - - This API may be extended in the future to support additional kinds of parent - resources. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - properties: - group: - default: gateway.networking.k8s.io - description: |- - Group is the group of the referent. - When unspecified, "gateway.networking.k8s.io" is inferred. - To set the core API group (such as for a "Service" kind referent), - Group must be explicitly set to "" (empty string). - - Support: Core - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: |- - Kind is kind of the referent. - - There are two kinds of parent resources with "Core" support: - - * Gateway (Gateway conformance profile) - * Service (Mesh conformance profile, ClusterIP Services only) - - Support for other resources is Implementation-Specific. - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: |- - Name is the name of the referent. - - Support: Core - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referent. When unspecified, this refers - to the local namespace of the Route. - - Note that there are specific rules for ParentRefs which cross namespace - boundaries. Cross-namespace references are only valid if they are explicitly - allowed by something in the namespace they are referring to. For example: - Gateway has the AllowedRoutes field, and ReferenceGrant provides a - generic way to enable any other kind of cross-namespace reference. - - - ParentRefs from a Route to a Service in the same namespace are "producer" - routes, which apply default routing rules to inbound connections from - any namespace to the Service. - - ParentRefs from a Route to a Service in a different namespace are - "consumer" routes, and these routing rules are only applied to outbound - connections originating from the same namespace as the Route, for which - the intended destination of the connections are a Service targeted as a - ParentRef of the Route. - - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port is the network port this Route targets. It can be interpreted - differently based on the type of parent resource. - - When the parent resource is a Gateway, this targets all listeners - listening on the specified port that also support this kind of Route(and - select this Route). It's not recommended to set `Port` unless the - networking behaviors specified in a Route must apply to a specific port - as opposed to a listener(s) whose port(s) may be changed. When both Port - and SectionName are specified, the name and port of the selected listener - must match both specified values. - - - When the parent resource is a Service, this targets a specific port in the - Service spec. When both Port (experimental) and SectionName are specified, - the name and port of the selected port must match both specified values. - - - Implementations MAY choose to support other parent resources. - Implementations supporting other types of parent resources MUST clearly - document how/if Port is interpreted. - - For the purpose of status, an attachment is considered successful as - long as the parent resource accepts it partially. For example, Gateway - listeners can restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept attachment - from the referencing Route, the Route MUST be considered successfully - attached. If no Gateway listeners accept attachment from this Route, - the Route MUST be considered detached from the Gateway. - - Support: Extended - format: int32 - maximum: 65535 - minimum: 1 - type: integer - sectionName: - description: |- - SectionName is the name of a section within the target resource. In the - following resources, SectionName is interpreted as the following: - - * Gateway: Listener name. When both Port (experimental) and SectionName - are specified, the name and port of the selected listener must match - both specified values. - * Service: Port name. When both Port (experimental) and SectionName - are specified, the name and port of the selected listener must match - both specified values. - - Implementations MAY choose to support attaching Routes to other resources. - If that is the case, they MUST clearly document how SectionName is - interpreted. - - When unspecified (empty string), this will reference the entire resource. - For the purpose of status, an attachment is considered successful if at - least one section in the parent resource accepts it. For example, Gateway - listeners can restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from - the referencing Route, the Route MUST be considered successfully - attached. If no Gateway listeners accept attachment from this Route, the - Route MUST be considered detached from the Gateway. - - Support: Core - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - type: array - x-kubernetes-list-type: atomic - podTemplate: - description: |- - Optional pod template used to configure the ACME challenge solver pods - used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the pod used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver pods. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - type: object - spec: - description: |- - PodSpec defines overrides for the HTTP01 challenge solver pod. - Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. - All other fields will be ignored. - properties: - affinity: - description: If specified, the pod's scheduling constraints - 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 - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - 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 - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - resources: - description: |- - If specified, the pod's resource requirements. - These values override the global resource configuration flags. - Note that when only specifying resource limits, ensure they are greater than or equal - to the corresponding global resource requests configured via controller flags - (--acme-http01-solver-resource-request-cpu, --acme-http01-solver-resource-request-memory). - Kubernetes will reject pod creation if limits are lower than requests, causing challenge failures. - 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 - 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 the global values configured via controller flags. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: If specified, the pod's security context - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - type: object - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - 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 - x-kubernetes-list-type: atomic - type: object - type: object - serviceType: - description: |- - Optional service type for Kubernetes solver service. Supported values - are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - type: object - ingress: - description: |- - The ingress based HTTP01 challenge solver will solve challenges by - creating or modifying Ingress resources in order to route requests for - '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are - provisioned by cert-manager for each Challenge to be completed. - properties: - class: - description: |- - This field configures the annotation `kubernetes.io/ingress.class` when - creating Ingress resources to solve ACME challenges that use this - challenge solver. Only one of `class`, `name` or `ingressClassName` may - be specified. - type: string - ingressClassName: - description: |- - This field configures the field `ingressClassName` on the created Ingress - resources used to solve ACME challenges that use this challenge solver. - This is the recommended way of configuring the ingress class. Only one of - `class`, `name` or `ingressClassName` may be specified. - type: string - ingressTemplate: - description: |- - Optional ingress template used to configure the ACME challenge solver - ingress used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the ingress used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver ingress. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver ingress. - type: object - type: object - type: object - name: - description: |- - The name of the ingress resource that should have ACME challenge solving - routes inserted into it in order to solve HTTP01 challenges. - This is typically used in conjunction with ingress controllers like - ingress-gce, which maintains a 1:1 mapping between external IPs and - ingress resources. Only one of `class`, `name` or `ingressClassName` may - be specified. - type: string - podTemplate: - description: |- - Optional pod template used to configure the ACME challenge solver pods - used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the pod used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver pods. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - type: object - spec: - description: |- - PodSpec defines overrides for the HTTP01 challenge solver pod. - Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. - All other fields will be ignored. - properties: - affinity: - description: If specified, the pod's scheduling constraints - 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 - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - 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 - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - resources: - description: |- - If specified, the pod's resource requirements. - These values override the global resource configuration flags. - Note that when only specifying resource limits, ensure they are greater than or equal - to the corresponding global resource requests configured via controller flags - (--acme-http01-solver-resource-request-cpu, --acme-http01-solver-resource-request-memory). - Kubernetes will reject pod creation if limits are lower than requests, causing challenge failures. - 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 - 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 the global values configured via controller flags. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: If specified, the pod's security context - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - type: object - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - 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 - x-kubernetes-list-type: atomic - type: object - type: object - serviceType: - description: |- - Optional service type for Kubernetes solver service. Supported values - are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - type: object - type: object - selector: - description: |- - Selector selects a set of DNSNames on the Certificate resource that - should be solved using this challenge solver. - If not specified, the solver will be treated as the 'default' solver - with the lowest priority, i.e. if any other solver has a more specific - match, it will be used instead. - properties: - dnsNames: - description: |- - List of DNSNames that this solver will be used to solve. - If specified and a match is found, a dnsNames selector will take - precedence over a dnsZones selector. - If multiple solvers match with the same dnsNames value, the solver - with the most matching labels in matchLabels will be selected. - If neither has more matches, the solver defined earlier in the list - will be selected. - items: - type: string - type: array - x-kubernetes-list-type: atomic - dnsZones: - description: |- - List of DNSZones that this solver will be used to solve. - The most specific DNS zone match specified here will take precedence - over other DNS zone matches, so a solver specifying sys.example.com - will be selected over one specifying example.com for the domain - www.sys.example.com. - If multiple solvers match with the same dnsZones value, the solver - with the most matching labels in matchLabels will be selected. - If neither has more matches, the solver defined earlier in the list - will be selected. - items: - type: string - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - A label selector that is used to refine the set of certificate's that - this challenge solver will apply to. - type: object - type: object - type: object - token: - description: |- - The ACME challenge token for this challenge. - This is the raw value returned from the ACME server. - type: string - type: - description: |- - The type of ACME challenge this resource represents. - One of "HTTP-01" or "DNS-01". - enum: - - HTTP-01 - - DNS-01 - type: string - url: - description: |- - The URL of the ACME Challenge resource for this challenge. - This can be used to lookup details about the status of this challenge. - type: string - wildcard: - description: |- - wildcard will be true if this challenge is for a wildcard identifier, - for example '*.example.com'. - type: boolean - required: - - authorizationURL - - dnsName - - issuerRef - - key - - solver - - token - - type - - url - type: object - status: - properties: - presented: - description: |- - presented will be set to true if the challenge values for this challenge - are currently 'presented'. - This *does not* imply the self check is passing. Only that the values - have been 'submitted' for the appropriate challenge mechanism (i.e. the - DNS01 TXT record has been presented, or the HTTP01 configuration has been - configured). - type: boolean - processing: - description: |- - Used to denote whether this challenge should be processed or not. - This field will only be set to true by the 'scheduling' component. - It will only be set to false by the 'challenges' controller, after the - challenge has reached a final state or timed out. - If this field is set to false, the challenge controller will not take - any more action. - type: boolean - reason: - description: |- - Contains human readable information on why the Challenge is in the - current state. - type: string - state: - description: |- - Contains the current 'state' of the challenge. - If not set, the state of the challenge is unknown. - enum: - - valid - - ready - - pending - - processing - - invalid - - expired - - errored - type: string - type: object - required: - - metadata - - spec - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/packages/system/cert-manager-crds/templates/crd-acme.cert-manager.io_orders.yaml b/packages/system/cert-manager-crds/templates/crd-acme.cert-manager.io_orders.yaml deleted file mode 100644 index 3242fc41..00000000 --- a/packages/system/cert-manager-crds/templates/crd-acme.cert-manager.io_orders.yaml +++ /dev/null @@ -1,274 +0,0 @@ -{{- if or .Values.crds.enabled .Values.installCRDs }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: "orders.acme.cert-manager.io" - {{- if .Values.crds.keep }} - annotations: - helm.sh/resource-policy: keep - {{- end }} - labels: - {{- include "cert-manager.crd-labels" . | nindent 4 }} -spec: - group: acme.cert-manager.io - names: - categories: - - cert-manager - - cert-manager-acme - kind: Order - listKind: OrderList - plural: orders - singular: order - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.state - name: State - type: string - - jsonPath: .spec.issuerRef.name - name: Issuer - priority: 1 - type: string - - jsonPath: .status.reason - name: Reason - priority: 1 - type: string - - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: Order is a type to represent an Order with an ACME server - 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: - properties: - commonName: - description: |- - CommonName is the common name as specified on the DER encoded CSR. - If specified, this value must also be present in `dnsNames` or `ipAddresses`. - This field must match the corresponding field on the DER encoded CSR. - type: string - dnsNames: - description: |- - DNSNames is a list of DNS names that should be included as part of the Order - validation process. - This field must match the corresponding field on the DER encoded CSR. - items: - type: string - type: array - x-kubernetes-list-type: atomic - duration: - description: |- - Duration is the duration for the not after date for the requested certificate. - this is set on order creation as pe the ACME spec. - type: string - ipAddresses: - description: |- - IPAddresses is a list of IP addresses that should be included as part of the Order - validation process. - This field must match the corresponding field on the DER encoded CSR. - items: - type: string - type: array - x-kubernetes-list-type: atomic - issuerRef: - description: |- - IssuerRef references a properly configured ACME-type Issuer which should - be used to create this Order. - If the Issuer does not exist, processing will be retried. - If the Issuer is not an 'ACME' Issuer, an error will be returned and the - Order will be marked as failed. - properties: - group: - description: |- - Group of the issuer being referred to. - Defaults to 'cert-manager.io'. - type: string - kind: - description: |- - Kind of the issuer being referred to. - Defaults to 'Issuer'. - type: string - name: - description: Name of the issuer being referred to. - type: string - required: - - name - type: object - profile: - description: |- - Profile allows requesting a certificate profile from the ACME server. - Supported profiles are listed by the server's ACME directory URL. - type: string - request: - description: |- - Certificate signing request bytes in DER encoding. - This will be used when finalizing the order. - This field must be set on the order. - format: byte - type: string - required: - - issuerRef - - request - type: object - status: - properties: - authorizations: - description: |- - Authorizations contains data returned from the ACME server on what - authorizations must be completed in order to validate the DNS names - specified on the Order. - items: - description: |- - ACMEAuthorization contains data returned from the ACME server on an - authorization that must be completed in order validate a DNS name on an ACME - Order resource. - properties: - challenges: - description: |- - Challenges specifies the challenge types offered by the ACME server. - One of these challenge types will be selected when validating the DNS - name and an appropriate Challenge resource will be created to perform - the ACME challenge process. - items: - description: |- - Challenge specifies a challenge offered by the ACME server for an Order. - An appropriate Challenge resource can be created to perform the ACME - challenge process. - properties: - token: - description: |- - Token is the token that must be presented for this challenge. - This is used to compute the 'key' that must also be presented. - type: string - type: - description: |- - Type is the type of challenge being offered, e.g., 'http-01', 'dns-01', - 'tls-sni-01', etc. - This is the raw value retrieved from the ACME server. - Only 'http-01' and 'dns-01' are supported by cert-manager, other values - will be ignored. - type: string - url: - description: |- - URL is the URL of this challenge. It can be used to retrieve additional - metadata about the Challenge from the ACME server. - type: string - required: - - token - - type - - url - type: object - type: array - x-kubernetes-list-type: atomic - identifier: - description: Identifier is the DNS name to be validated as part of this authorization - type: string - initialState: - description: |- - InitialState is the initial state of the ACME authorization when first - fetched from the ACME server. - If an Authorization is already 'valid', the Order controller will not - create a Challenge resource for the authorization. This will occur when - working with an ACME server that enables 'authz reuse' (such as Let's - Encrypt's production endpoint). - If not set and 'identifier' is set, the state is assumed to be pending - and a Challenge will be created. - enum: - - valid - - ready - - pending - - processing - - invalid - - expired - - errored - type: string - url: - description: URL is the URL of the Authorization that must be completed - type: string - wildcard: - description: |- - Wildcard will be true if this authorization is for a wildcard DNS name. - If this is true, the identifier will be the *non-wildcard* version of - the DNS name. - For example, if '*.example.com' is the DNS name being validated, this - field will be 'true' and the 'identifier' field will be 'example.com'. - type: boolean - required: - - url - type: object - type: array - x-kubernetes-list-type: atomic - certificate: - description: |- - Certificate is a copy of the PEM encoded certificate for this Order. - This field will be populated after the order has been successfully - finalized with the ACME server, and the order has transitioned to the - 'valid' state. - format: byte - type: string - failureTime: - description: |- - FailureTime stores the time that this order failed. - This is used to influence garbage collection and back-off. - format: date-time - type: string - finalizeURL: - description: |- - FinalizeURL of the Order. - This is used to obtain certificates for this order once it has been completed. - type: string - reason: - description: |- - Reason optionally provides more information about a why the order is in - the current state. - type: string - state: - description: |- - State contains the current state of this Order resource. - States 'success' and 'expired' are 'final' - enum: - - valid - - ready - - pending - - processing - - invalid - - expired - - errored - type: string - url: - description: |- - URL of the Order. - This will initially be empty when the resource is first created. - The Order controller will populate this field when the Order is first processed. - This field will be immutable after it is initially set. - type: string - type: object - required: - - metadata - - spec - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_certificaterequests.yaml b/packages/system/cert-manager-crds/templates/crd-cert-manager.io_certificaterequests.yaml deleted file mode 100644 index e25ad1d0..00000000 --- a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_certificaterequests.yaml +++ /dev/null @@ -1,319 +0,0 @@ -{{- if or .Values.crds.enabled .Values.installCRDs }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: "certificaterequests.cert-manager.io" - {{- if .Values.crds.keep }} - annotations: - helm.sh/resource-policy: keep - {{- end }} - labels: - {{- include "cert-manager.crd-labels" . | nindent 4 }} -spec: - group: cert-manager.io - names: - categories: - - cert-manager - kind: CertificateRequest - listKind: CertificateRequestList - plural: certificaterequests - shortNames: - - cr - - crs - singular: certificaterequest - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type == "Approved")].status - name: Approved - type: string - - jsonPath: .status.conditions[?(@.type == "Denied")].status - name: Denied - type: string - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: Ready - type: string - - jsonPath: .spec.issuerRef.name - name: Issuer - type: string - - jsonPath: .spec.username - name: Requester - type: string - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: Status - priority: 1 - type: string - - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: |- - A CertificateRequest is used to request a signed certificate from one of the - configured issuers. - - All fields within the CertificateRequest's `spec` are immutable after creation. - A CertificateRequest will either succeed or fail, as denoted by its `Ready` status - condition and its `status.failureTime` field. - - A CertificateRequest is a one-shot resource, meaning it represents a single - point in time request for a certificate and cannot be re-used. - 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: |- - Specification of the desired state of the CertificateRequest resource. - https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - duration: - description: |- - Requested 'duration' (i.e. lifetime) of the Certificate. Note that the - issuer may choose to ignore the requested duration, just like any other - requested attribute. - type: string - extra: - additionalProperties: - items: - type: string - type: array - description: |- - Extra contains extra attributes of the user that created the CertificateRequest. - Populated by the cert-manager webhook on creation and immutable. - type: object - groups: - description: |- - Groups contains group membership of the user that created the CertificateRequest. - Populated by the cert-manager webhook on creation and immutable. - items: - type: string - type: array - x-kubernetes-list-type: atomic - isCA: - description: |- - Requested basic constraints isCA value. Note that the issuer may choose - to ignore the requested isCA value, just like any other requested attribute. - - NOTE: If the CSR in the `Request` field has a BasicConstraints extension, - it must have the same isCA value as specified here. - - If true, this will automatically add the `cert sign` usage to the list - of requested `usages`. - type: boolean - issuerRef: - description: |- - Reference to the issuer responsible for issuing the certificate. - If the issuer is namespace-scoped, it must be in the same namespace - as the Certificate. If the issuer is cluster-scoped, it can be used - from any namespace. - - The `name` field of the reference must always be specified. - properties: - group: - description: |- - Group of the issuer being referred to. - Defaults to 'cert-manager.io'. - type: string - kind: - description: |- - Kind of the issuer being referred to. - Defaults to 'Issuer'. - type: string - name: - description: Name of the issuer being referred to. - type: string - required: - - name - type: object - request: - description: |- - The PEM-encoded X.509 certificate signing request to be submitted to the - issuer for signing. - - If the CSR has a BasicConstraints extension, its isCA attribute must - match the `isCA` value of this CertificateRequest. - If the CSR has a KeyUsage extension, its key usages must match the - key usages in the `usages` field of this CertificateRequest. - If the CSR has a ExtKeyUsage extension, its extended key usages - must match the extended key usages in the `usages` field of this - CertificateRequest. - format: byte - type: string - uid: - description: |- - UID contains the uid of the user that created the CertificateRequest. - Populated by the cert-manager webhook on creation and immutable. - type: string - usages: - description: |- - Requested key usages and extended key usages. - - NOTE: If the CSR in the `Request` field has uses the KeyUsage or - ExtKeyUsage extension, these extensions must have the same values - as specified here without any additional values. - - If unset, defaults to `digital signature` and `key encipherment`. - items: - description: |- - KeyUsage specifies valid usage contexts for keys. - See: - https://tools.ietf.org/html/rfc5280#section-4.2.1.3 - https://tools.ietf.org/html/rfc5280#section-4.2.1.12 - - Valid KeyUsage values are as follows: - "signing", - "digital signature", - "content commitment", - "key encipherment", - "key agreement", - "data encipherment", - "cert sign", - "crl sign", - "encipher only", - "decipher only", - "any", - "server auth", - "client auth", - "code signing", - "email protection", - "s/mime", - "ipsec end system", - "ipsec tunnel", - "ipsec user", - "timestamping", - "ocsp signing", - "microsoft sgc", - "netscape sgc" - enum: - - signing - - digital signature - - content commitment - - key encipherment - - key agreement - - data encipherment - - cert sign - - crl sign - - encipher only - - decipher only - - any - - server auth - - client auth - - code signing - - email protection - - s/mime - - ipsec end system - - ipsec tunnel - - ipsec user - - timestamping - - ocsp signing - - microsoft sgc - - netscape sgc - type: string - type: array - x-kubernetes-list-type: atomic - username: - description: |- - Username contains the name of the user that created the CertificateRequest. - Populated by the cert-manager webhook on creation and immutable. - type: string - required: - - issuerRef - - request - type: object - status: - description: |- - Status of the CertificateRequest. - This is set and managed automatically. - Read-only. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - ca: - description: |- - The PEM encoded X.509 certificate of the signer, also known as the CA - (Certificate Authority). - This is set on a best-effort basis by different issuers. - If not set, the CA is assumed to be unknown/not available. - format: byte - type: string - certificate: - description: |- - The PEM encoded X.509 certificate resulting from the certificate - signing request. - If not set, the CertificateRequest has either not been completed or has - failed. More information on failure can be found by checking the - `conditions` field. - format: byte - type: string - conditions: - description: |- - List of status conditions to indicate the status of a CertificateRequest. - Known condition types are `Ready`, `InvalidRequest`, `Approved` and `Denied`. - items: - description: CertificateRequestCondition contains condition information for a CertificateRequest. - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the timestamp corresponding to the last status - change of this condition. - format: date-time - type: string - message: - description: |- - Message is a human readable description of the details of the last - transition, complementing reason. - type: string - reason: - description: |- - Reason is a brief machine readable explanation for the condition's last - transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: |- - Type of the condition, known values are (`Ready`, `InvalidRequest`, - `Approved`, `Denied`). - type: string - required: - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - failureTime: - description: |- - FailureTime stores the time that this CertificateRequest failed. This is - used to influence garbage collection and back-off. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_certificates.yaml b/packages/system/cert-manager-crds/templates/crd-cert-manager.io_certificates.yaml deleted file mode 100644 index 6689de66..00000000 --- a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_certificates.yaml +++ /dev/null @@ -1,816 +0,0 @@ -{{- if or .Values.crds.enabled .Values.installCRDs }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: "certificates.cert-manager.io" - {{- if .Values.crds.keep }} - annotations: - helm.sh/resource-policy: keep - {{- end }} - labels: - {{- include "cert-manager.crd-labels" . | nindent 4 }} -spec: - group: cert-manager.io - names: - categories: - - cert-manager - kind: Certificate - listKind: CertificateList - plural: certificates - shortNames: - - cert - - certs - singular: certificate - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: Ready - type: string - - jsonPath: .spec.secretName - name: Secret - type: string - - jsonPath: .spec.issuerRef.name - name: Issuer - priority: 1 - type: string - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: Status - priority: 1 - type: string - - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: |- - A Certificate resource should be created to ensure an up to date and signed - X.509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. - - The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`). - 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: |- - Specification of the desired state of the Certificate resource. - https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - additionalOutputFormats: - description: |- - Defines extra output formats of the private key and signed certificate chain - to be written to this Certificate's target Secret. - items: - description: |- - CertificateAdditionalOutputFormat defines an additional output format of a - Certificate resource. These contain supplementary data formats of the signed - certificate chain and paired private key. - properties: - type: - description: |- - Type is the name of the format type that should be written to the - Certificate's target Secret. - enum: - - DER - - CombinedPEM - type: string - required: - - type - type: object - type: array - x-kubernetes-list-type: atomic - commonName: - description: |- - Requested common name X509 certificate subject attribute. - More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 - NOTE: TLS clients will ignore this value when any subject alternative name is - set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). - - Should have a length of 64 characters or fewer to avoid generating invalid CSRs. - Cannot be set if the `literalSubject` field is set. - type: string - dnsNames: - description: Requested DNS subject alternative names. - items: - type: string - type: array - x-kubernetes-list-type: atomic - duration: - description: |- - Requested 'duration' (i.e. lifetime) of the Certificate. Note that the - issuer may choose to ignore the requested duration, just like any other - requested attribute. - - If unset, this defaults to 90 days. - Minimum accepted duration is 1 hour. - Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. - type: string - emailAddresses: - description: Requested email subject alternative names. - items: - type: string - type: array - x-kubernetes-list-type: atomic - encodeUsagesInRequest: - description: |- - Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. - - This option defaults to true, and should only be disabled if the target - issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions. - type: boolean - ipAddresses: - description: Requested IP address subject alternative names. - items: - type: string - type: array - x-kubernetes-list-type: atomic - isCA: - description: |- - Requested basic constraints isCA value. - The isCA value is used to set the `isCA` field on the created CertificateRequest - resources. Note that the issuer may choose to ignore the requested isCA value, just - like any other requested attribute. - - If true, this will automatically add the `cert sign` usage to the list - of requested `usages`. - type: boolean - issuerRef: - description: |- - Reference to the issuer responsible for issuing the certificate. - If the issuer is namespace-scoped, it must be in the same namespace - as the Certificate. If the issuer is cluster-scoped, it can be used - from any namespace. - - The `name` field of the reference must always be specified. - properties: - group: - description: |- - Group of the issuer being referred to. - Defaults to 'cert-manager.io'. - type: string - kind: - description: |- - Kind of the issuer being referred to. - Defaults to 'Issuer'. - type: string - name: - description: Name of the issuer being referred to. - type: string - required: - - name - type: object - keystores: - description: Additional keystore output formats to be stored in the Certificate's Secret. - properties: - jks: - description: |- - JKS configures options for storing a JKS keystore in the - `spec.secretName` Secret resource. - properties: - alias: - description: |- - Alias specifies the alias of the key in the keystore, required by the JKS format. - If not provided, the default alias `certificate` will be used. - type: string - create: - description: |- - Create enables JKS keystore creation for the Certificate. - If true, a file named `keystore.jks` will be created in the target - Secret resource, encrypted using the password stored in - `passwordSecretRef` or `password`. - The keystore file will be updated immediately. - If the issuer provided a CA certificate, a file named `truststore.jks` - will also be created in the target Secret resource, encrypted using the - password stored in `passwordSecretRef` - containing the issuing Certificate Authority - type: boolean - password: - description: |- - Password provides a literal password used to encrypt the JKS keystore. - Mutually exclusive with passwordSecretRef. - One of password or passwordSecretRef must provide a password with a non-zero length. - type: string - passwordSecretRef: - description: |- - PasswordSecretRef is a reference to a non-empty key in a Secret resource - containing the password used to encrypt the JKS keystore. - Mutually exclusive with password. - One of password or passwordSecretRef must provide a password with a non-zero length. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - create - type: object - pkcs12: - description: |- - PKCS12 configures options for storing a PKCS12 keystore in the - `spec.secretName` Secret resource. - properties: - create: - description: |- - Create enables PKCS12 keystore creation for the Certificate. - If true, a file named `keystore.p12` will be created in the target - Secret resource, encrypted using the password stored in - `passwordSecretRef` or in `password`. - The keystore file will be updated immediately. - If the issuer provided a CA certificate, a file named `truststore.p12` will - also be created in the target Secret resource, encrypted using the - password stored in `passwordSecretRef` containing the issuing Certificate - Authority - type: boolean - password: - description: |- - Password provides a literal password used to encrypt the PKCS#12 keystore. - Mutually exclusive with passwordSecretRef. - One of password or passwordSecretRef must provide a password with a non-zero length. - type: string - passwordSecretRef: - description: |- - PasswordSecretRef is a reference to a non-empty key in a Secret resource - containing the password used to encrypt the PKCS#12 keystore. - Mutually exclusive with password. - One of password or passwordSecretRef must provide a password with a non-zero length. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - profile: - description: |- - Profile specifies the key and certificate encryption algorithms and the HMAC algorithm - used to create the PKCS12 keystore. Default value is `LegacyRC2` for backward compatibility. - - If provided, allowed values are: - `LegacyRC2`: Deprecated. Not supported by default in OpenSSL 3 or Java 20. - `LegacyDES`: Less secure algorithm. Use this option for maximal compatibility. - `Modern2023`: Secure algorithm. Use this option in case you have to always use secure algorithms - (e.g., because of company policy). Please note that the security of the algorithm is not that important - in reality, because the unencrypted certificate and private key are also stored in the Secret. - enum: - - LegacyRC2 - - LegacyDES - - Modern2023 - type: string - required: - - create - type: object - type: object - literalSubject: - description: |- - Requested X.509 certificate subject, represented using the LDAP "String - Representation of a Distinguished Name" [1]. - Important: the LDAP string format also specifies the order of the attributes - in the subject, this is important when issuing certs for LDAP authentication. - Example: `CN=foo,DC=corp,DC=example,DC=com` - More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 - More info: https://github.com/cert-manager/cert-manager/issues/3203 - More info: https://github.com/cert-manager/cert-manager/issues/4424 - - Cannot be set if the `subject` or `commonName` field is set. - type: string - nameConstraints: - description: |- - x.509 certificate NameConstraint extension which MUST NOT be used in a non-CA certificate. - More Info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10 - - This is an Alpha Feature and is only enabled with the - `--feature-gates=NameConstraints=true` option set on both - the controller and webhook components. - properties: - critical: - description: if true then the name constraints are marked critical. - type: boolean - excluded: - description: |- - Excluded contains the constraints which must be disallowed. Any name matching a - restriction in the excluded field is invalid regardless - of information appearing in the permitted - properties: - dnsDomains: - description: DNSDomains is a list of DNS domains that are permitted or excluded. - items: - type: string - type: array - x-kubernetes-list-type: atomic - emailAddresses: - description: EmailAddresses is a list of Email Addresses that are permitted or excluded. - items: - type: string - type: array - x-kubernetes-list-type: atomic - ipRanges: - description: |- - IPRanges is a list of IP Ranges that are permitted or excluded. - This should be a valid CIDR notation. - items: - type: string - type: array - x-kubernetes-list-type: atomic - uriDomains: - description: URIDomains is a list of URI domains that are permitted or excluded. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - permitted: - description: Permitted contains the constraints in which the names must be located. - properties: - dnsDomains: - description: DNSDomains is a list of DNS domains that are permitted or excluded. - items: - type: string - type: array - x-kubernetes-list-type: atomic - emailAddresses: - description: EmailAddresses is a list of Email Addresses that are permitted or excluded. - items: - type: string - type: array - x-kubernetes-list-type: atomic - ipRanges: - description: |- - IPRanges is a list of IP Ranges that are permitted or excluded. - This should be a valid CIDR notation. - items: - type: string - type: array - x-kubernetes-list-type: atomic - uriDomains: - description: URIDomains is a list of URI domains that are permitted or excluded. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - type: object - otherNames: - description: |- - `otherNames` is an escape hatch for SAN that allows any type. We currently restrict the support to string like otherNames, cf RFC 5280 p 37 - Any UTF8 String valued otherName can be passed with by setting the keys oid: x.x.x.x and UTF8Value: somevalue for `otherName`. - Most commonly this would be UPN set with oid: 1.3.6.1.4.1.311.20.2.3 - You should ensure that any OID passed is valid for the UTF8String type as we do not explicitly validate this. - items: - properties: - oid: - description: |- - OID is the object identifier for the otherName SAN. - The object identifier must be expressed as a dotted string, for - example, "1.2.840.113556.1.4.221". - type: string - utf8Value: - description: |- - utf8Value is the string value of the otherName SAN. - The utf8Value accepts any valid UTF8 string to set as value for the otherName SAN. - type: string - type: object - type: array - x-kubernetes-list-type: atomic - privateKey: - description: |- - Private key options. These include the key algorithm and size, the used - encoding and the rotation policy. - properties: - algorithm: - description: |- - Algorithm is the private key algorithm of the corresponding private key - for this certificate. - - If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. - If `algorithm` is specified and `size` is not provided, - key size of 2048 will be used for `RSA` key algorithm and - key size of 256 will be used for `ECDSA` key algorithm. - key size is ignored when using the `Ed25519` key algorithm. - enum: - - RSA - - ECDSA - - Ed25519 - type: string - encoding: - description: |- - The private key cryptography standards (PKCS) encoding for this - certificate's private key to be encoded in. - - If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 - and PKCS#8, respectively. - Defaults to `PKCS1` if not specified. - enum: - - PKCS1 - - PKCS8 - type: string - rotationPolicy: - description: |- - RotationPolicy controls how private keys should be regenerated when a - re-issuance is being processed. - - If set to `Never`, a private key will only be generated if one does not - already exist in the target `spec.secretName`. If one does exist but it - does not have the correct algorithm or size, a warning will be raised - to await user intervention. - If set to `Always`, a private key matching the specified requirements - will be generated whenever a re-issuance occurs. - Default is `Always`. - The default was changed from `Never` to `Always` in cert-manager >=v1.18.0. - The new default can be disabled by setting the - `--feature-gates=DefaultPrivateKeyRotationPolicyAlways=false` option on - the controller component. - enum: - - Never - - Always - type: string - size: - description: |- - Size is the key bit size of the corresponding private key for this certificate. - - If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, - and will default to `2048` if not specified. - If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, - and will default to `256` if not specified. - If `algorithm` is set to `Ed25519`, Size is ignored. - No other values are allowed. - type: integer - type: object - renewBefore: - description: |- - How long before the currently issued certificate's expiry cert-manager should - renew the certificate. For example, if a certificate is valid for 60 minutes, - and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate - 50 minutes after it was issued (i.e. when there are 10 minutes remaining until - the certificate is no longer valid). - - NOTE: The actual lifetime of the issued certificate is used to determine the - renewal time. If an issuer returns a certificate with a different lifetime than - the one requested, cert-manager will use the lifetime of the issued certificate. - - If unset, this defaults to 1/3 of the issued certificate's lifetime. - Minimum accepted value is 5 minutes. - Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. - Cannot be set if the `renewBeforePercentage` field is set. - type: string - renewBeforePercentage: - description: |- - `renewBeforePercentage` is like `renewBefore`, except it is a relative percentage - rather than an absolute duration. For example, if a certificate is valid for 60 - minutes, and `renewBeforePercentage=25`, cert-manager will begin to attempt to - renew the certificate 45 minutes after it was issued (i.e. when there are 15 - minutes (25%) remaining until the certificate is no longer valid). - - NOTE: The actual lifetime of the issued certificate is used to determine the - renewal time. If an issuer returns a certificate with a different lifetime than - the one requested, cert-manager will use the lifetime of the issued certificate. - - Value must be an integer in the range (0,100). The minimum effective - `renewBefore` derived from the `renewBeforePercentage` and `duration` fields is 5 - minutes. - Cannot be set if the `renewBefore` field is set. - format: int32 - type: integer - revisionHistoryLimit: - description: |- - The maximum number of CertificateRequest revisions that are maintained in - the Certificate's history. Each revision represents a single `CertificateRequest` - created by this Certificate, either when it was created, renewed, or Spec - was changed. Revisions will be removed by oldest first if the number of - revisions exceeds this number. - - If set, revisionHistoryLimit must be a value of `1` or greater. - Default value is `1`. - format: int32 - type: integer - secretName: - description: |- - Name of the Secret resource that will be automatically created and - managed by this Certificate resource. It will be populated with a - private key and certificate, signed by the denoted issuer. The Secret - resource lives in the same namespace as the Certificate resource. - type: string - secretTemplate: - description: |- - Defines annotations and labels to be copied to the Certificate's Secret. - Labels and annotations on the Secret will be changed as they appear on the - SecretTemplate when added or removed. SecretTemplate annotations are added - in conjunction with, and cannot overwrite, the base set of annotations - cert-manager sets on the Certificate's Secret. - properties: - annotations: - additionalProperties: - type: string - description: Annotations is a key value map to be copied to the target Kubernetes Secret. - type: object - labels: - additionalProperties: - type: string - description: Labels is a key value map to be copied to the target Kubernetes Secret. - type: object - type: object - signatureAlgorithm: - description: |- - Signature algorithm to use. - Allowed values for RSA keys: SHA256WithRSA, SHA384WithRSA, SHA512WithRSA. - Allowed values for ECDSA keys: ECDSAWithSHA256, ECDSAWithSHA384, ECDSAWithSHA512. - Allowed values for Ed25519 keys: PureEd25519. - enum: - - SHA256WithRSA - - SHA384WithRSA - - SHA512WithRSA - - ECDSAWithSHA256 - - ECDSAWithSHA384 - - ECDSAWithSHA512 - - PureEd25519 - type: string - subject: - description: |- - Requested set of X509 certificate subject attributes. - More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 - - The common name attribute is specified separately in the `commonName` field. - Cannot be set if the `literalSubject` field is set. - properties: - countries: - description: Countries to be used on the Certificate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - localities: - description: Cities to be used on the Certificate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - organizationalUnits: - description: Organizational Units to be used on the Certificate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - organizations: - description: Organizations to be used on the Certificate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - postalCodes: - description: Postal codes to be used on the Certificate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - provinces: - description: State/Provinces to be used on the Certificate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - serialNumber: - description: Serial number to be used on the Certificate. - type: string - streetAddresses: - description: Street addresses to be used on the Certificate. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - uris: - description: Requested URI subject alternative names. - items: - type: string - type: array - x-kubernetes-list-type: atomic - usages: - description: |- - Requested key usages and extended key usages. - These usages are used to set the `usages` field on the created CertificateRequest - resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages - will additionally be encoded in the `request` field which contains the CSR blob. - - If unset, defaults to `digital signature` and `key encipherment`. - items: - description: |- - KeyUsage specifies valid usage contexts for keys. - See: - https://tools.ietf.org/html/rfc5280#section-4.2.1.3 - https://tools.ietf.org/html/rfc5280#section-4.2.1.12 - - Valid KeyUsage values are as follows: - "signing", - "digital signature", - "content commitment", - "key encipherment", - "key agreement", - "data encipherment", - "cert sign", - "crl sign", - "encipher only", - "decipher only", - "any", - "server auth", - "client auth", - "code signing", - "email protection", - "s/mime", - "ipsec end system", - "ipsec tunnel", - "ipsec user", - "timestamping", - "ocsp signing", - "microsoft sgc", - "netscape sgc" - enum: - - signing - - digital signature - - content commitment - - key encipherment - - key agreement - - data encipherment - - cert sign - - crl sign - - encipher only - - decipher only - - any - - server auth - - client auth - - code signing - - email protection - - s/mime - - ipsec end system - - ipsec tunnel - - ipsec user - - timestamping - - ocsp signing - - microsoft sgc - - netscape sgc - type: string - type: array - x-kubernetes-list-type: atomic - required: - - issuerRef - - secretName - type: object - status: - description: |- - Status of the Certificate. - This is set and managed automatically. - Read-only. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - conditions: - description: |- - List of status conditions to indicate the status of certificates. - Known condition types are `Ready` and `Issuing`. - items: - description: CertificateCondition contains condition information for a Certificate. - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the timestamp corresponding to the last status - change of this condition. - format: date-time - type: string - message: - description: |- - Message is a human readable description of the details of the last - transition, complementing reason. - type: string - observedGeneration: - description: |- - If set, this represents the .metadata.generation that the condition was - set based upon. - For instance, if .metadata.generation is currently 12, but the - .status.condition[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the Certificate. - format: int64 - type: integer - reason: - description: |- - Reason is a brief machine readable explanation for the condition's last - transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: Type of the condition, known values are (`Ready`, `Issuing`). - type: string - required: - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - failedIssuanceAttempts: - description: |- - The number of continuous failed issuance attempts up till now. This - field gets removed (if set) on a successful issuance and gets set to - 1 if unset and an issuance has failed. If an issuance has failed, the - delay till the next issuance will be calculated using formula - time.Hour * 2 ^ (failedIssuanceAttempts - 1). - type: integer - lastFailureTime: - description: |- - LastFailureTime is set only if the latest issuance for this - Certificate failed and contains the time of the failure. If an - issuance has failed, the delay till the next issuance will be - calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - - 1). If the latest issuance has succeeded this field will be unset. - format: date-time - type: string - nextPrivateKeySecretName: - description: |- - The name of the Secret resource containing the private key to be used - for the next certificate iteration. - The keymanager controller will automatically set this field if the - `Issuing` condition is set to `True`. - It will automatically unset this field when the Issuing condition is - not set or False. - type: string - notAfter: - description: |- - The expiration time of the certificate stored in the secret named - by this resource in `spec.secretName`. - format: date-time - type: string - notBefore: - description: |- - The time after which the certificate stored in the secret named - by this resource in `spec.secretName` is valid. - format: date-time - type: string - renewalTime: - description: |- - RenewalTime is the time at which the certificate will be next - renewed. - If not set, no upcoming renewal is scheduled. - format: date-time - type: string - revision: - description: |- - The current 'revision' of the certificate as issued. - - When a CertificateRequest resource is created, it will have the - `cert-manager.io/certificate-revision` set to one greater than the - current value of this field. - - Upon issuance, this field will be set to the value of the annotation - on the CertificateRequest resource used to issue the certificate. - - Persisting the value on the CertificateRequest resource allows the - certificates controller to know whether a request is part of an old - issuance or if it is part of the ongoing revision's issuance by - checking if the revision value in the annotation is greater than this - field. - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_clusterissuers.yaml b/packages/system/cert-manager-crds/templates/crd-cert-manager.io_clusterissuers.yaml deleted file mode 100644 index 790d4b5c..00000000 --- a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_clusterissuers.yaml +++ /dev/null @@ -1,3815 +0,0 @@ -{{- if or .Values.crds.enabled .Values.installCRDs }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: "clusterissuers.cert-manager.io" - {{- if .Values.crds.keep }} - annotations: - helm.sh/resource-policy: keep - {{- end }} - labels: - {{- include "cert-manager.crd-labels" . | nindent 4 }} -spec: - group: cert-manager.io - names: - categories: - - cert-manager - kind: ClusterIssuer - listKind: ClusterIssuerList - plural: clusterissuers - shortNames: - - ciss - singular: clusterissuer - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: Status - priority: 1 - type: string - - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: |- - A ClusterIssuer represents a certificate issuing authority which can be - referenced as part of `issuerRef` fields. - It is similar to an Issuer, however it is cluster-scoped and therefore can - be referenced by resources that exist in *any* namespace, not just the same - namespace as the referent. - 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: Desired state of the ClusterIssuer resource. - properties: - acme: - description: |- - ACME configures this issuer to communicate with a RFC8555 (ACME) server - to obtain signed x509 certificates. - properties: - caBundle: - description: |- - Base64-encoded bundle of PEM CAs which can be used to validate the certificate - chain presented by the ACME server. - Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various - kinds of security vulnerabilities. - If CABundle and SkipTLSVerify are unset, the system certificate bundle inside - the container is used to validate the TLS connection. - format: byte - type: string - disableAccountKeyGeneration: - description: |- - Enables or disables generating a new ACME account key. - If true, the Issuer resource will *not* request a new account but will expect - the account key to be supplied via an existing secret. - If false, the cert-manager system will generate a new ACME account key - for the Issuer. - Defaults to false. - type: boolean - email: - description: |- - Email is the email address to be associated with the ACME account. - This field is optional, but it is strongly recommended to be set. - It will be used to contact you in case of issues with your account or - certificates, including expiry notification emails. - This field may be updated after the account is initially registered. - type: string - enableDurationFeature: - description: |- - Enables requesting a Not After date on certificates that matches the - duration of the certificate. This is not supported by all ACME servers - like Let's Encrypt. If set to true when the ACME server does not support - it, it will create an error on the Order. - Defaults to false. - type: boolean - externalAccountBinding: - description: |- - ExternalAccountBinding is a reference to a CA external account of the ACME - server. - If set, upon registration cert-manager will attempt to associate the given - external account credentials with the registered ACME account. - properties: - keyAlgorithm: - description: |- - Deprecated: keyAlgorithm field exists for historical compatibility - reasons and should not be used. The algorithm is now hardcoded to HS256 - in golang/x/crypto/acme. - enum: - - HS256 - - HS384 - - HS512 - type: string - keyID: - description: keyID is the ID of the CA key that the External Account is bound to. - type: string - keySecretRef: - description: |- - keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes - Secret which holds the symmetric MAC key of the External Account Binding. - The `key` is the index string that is paired with the key data in the - Secret and should not be confused with the key data itself, or indeed with - the External Account Binding keyID above. - The secret key stored in the Secret **must** be un-padded, base64 URL - encoded data. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - keyID - - keySecretRef - type: object - preferredChain: - description: |- - PreferredChain is the chain to use if the ACME server outputs multiple. - PreferredChain is no guarantee that this one gets delivered by the ACME - endpoint. - For example, for Let's Encrypt's DST cross-sign you would use: - "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. - This value picks the first certificate bundle in the combined set of - ACME default and alternative chains that has a root-most certificate with - this value as its issuer's commonname. - maxLength: 64 - type: string - privateKeySecretRef: - description: |- - PrivateKey is the name of a Kubernetes Secret resource that will be used to - store the automatically generated ACME account private key. - Optionally, a `key` may be specified to select a specific entry within - the named Secret resource. - If `key` is not specified, a default of `tls.key` will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - profile: - description: |- - Profile allows requesting a certificate profile from the ACME server. - Supported profiles are listed by the server's ACME directory URL. - type: string - server: - description: |- - Server is the URL used to access the ACME server's 'directory' endpoint. - For example, for Let's Encrypt's staging endpoint, you would use: - "https://acme-staging-v02.api.letsencrypt.org/directory". - Only ACME v2 endpoints (i.e. RFC 8555) are supported. - type: string - skipTLSVerify: - description: |- - INSECURE: Enables or disables validation of the ACME server TLS certificate. - If true, requests to the ACME server will not have the TLS certificate chain - validated. - Mutually exclusive with CABundle; prefer using CABundle to prevent various - kinds of security vulnerabilities. - Only enable this option in development environments. - If CABundle and SkipTLSVerify are unset, the system certificate bundle inside - the container is used to validate the TLS connection. - Defaults to false. - type: boolean - solvers: - description: |- - Solvers is a list of challenge solvers that will be used to solve - ACME challenges for the matching domains. - Solver configurations must be provided in order to obtain certificates - from an ACME server. - For more information, see: https://cert-manager.io/docs/configuration/acme/ - items: - description: |- - An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. - A selector may be provided to use different solving strategies for different DNS names. - Only one of HTTP01 or DNS01 must be provided. - properties: - dns01: - description: |- - Configures cert-manager to attempt to complete authorizations by - performing the DNS01 challenge flow. - properties: - acmeDNS: - description: |- - Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage - DNS01 challenge records. - properties: - accountSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - host: - type: string - required: - - accountSecretRef - - host - type: object - akamai: - description: Use the Akamai DNS zone management API to manage DNS01 challenge records. - properties: - accessTokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientTokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - serviceConsumerDomain: - type: string - required: - - accessTokenSecretRef - - clientSecretSecretRef - - clientTokenSecretRef - - serviceConsumerDomain - type: object - azureDNS: - description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. - properties: - clientID: - description: |- - Auth: Azure Service Principal: - The ClientID of the Azure Service Principal used to authenticate with Azure DNS. - If set, ClientSecret and TenantID must also be set. - type: string - clientSecretSecretRef: - description: |- - Auth: Azure Service Principal: - A reference to a Secret containing the password associated with the Service Principal. - If set, ClientID and TenantID must also be set. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - environment: - description: name of the Azure environment (default AzurePublicCloud) - enum: - - AzurePublicCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureUSGovernmentCloud - type: string - hostedZoneName: - description: name of the DNS zone that should be used - type: string - managedIdentity: - description: |- - Auth: Azure Workload Identity or Azure Managed Service Identity: - Settings to enable Azure Workload Identity or Azure Managed Service Identity - If set, ClientID, ClientSecret and TenantID must not be set. - properties: - clientID: - description: client ID of the managed identity, cannot be used at the same time as resourceID - type: string - resourceID: - description: |- - resource ID of the managed identity, cannot be used at the same time as clientID - Cannot be used for Azure Managed Service Identity - type: string - tenantID: - description: tenant ID of the managed identity, cannot be used at the same time as resourceID - type: string - type: object - resourceGroupName: - description: resource group the DNS zone is located in - type: string - subscriptionID: - description: ID of the Azure subscription - type: string - tenantID: - description: |- - Auth: Azure Service Principal: - The TenantID of the Azure Service Principal used to authenticate with Azure DNS. - If set, ClientID and ClientSecret must also be set. - type: string - required: - - resourceGroupName - - subscriptionID - type: object - cloudDNS: - description: Use the Google Cloud DNS API to manage DNS01 challenge records. - properties: - hostedZoneName: - description: |- - HostedZoneName is an optional field that tells cert-manager in which - Cloud DNS zone the challenge record has to be created. - If left empty cert-manager will automatically choose a zone. - type: string - project: - type: string - serviceAccountSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - project - type: object - cloudflare: - description: Use the Cloudflare API to manage DNS01 challenge records. - properties: - apiKeySecretRef: - description: |- - API key to use to authenticate with Cloudflare. - Note: using an API token to authenticate is now the recommended method - as it allows greater control of permissions. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - apiTokenSecretRef: - description: API token used to authenticate with Cloudflare. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - email: - description: Email of the account, only required when using API key based authentication. - type: string - type: object - cnameStrategy: - description: |- - CNAMEStrategy configures how the DNS01 provider should handle CNAME - records when found in DNS zones. - enum: - - None - - Follow - type: string - digitalocean: - description: Use the DigitalOcean DNS API to manage DNS01 challenge records. - properties: - tokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - tokenSecretRef - type: object - rfc2136: - description: |- - Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) - to manage DNS01 challenge records. - properties: - nameserver: - description: |- - The IP address or hostname of an authoritative DNS server supporting - RFC2136 in the form host:port. If the host is an IPv6 address it must be - enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. - This field is required. - type: string - protocol: - description: Protocol to use for dynamic DNS update queries. Valid values are (case-sensitive) ``TCP`` and ``UDP``; ``UDP`` (default). - enum: - - TCP - - UDP - type: string - tsigAlgorithm: - description: |- - The TSIG Algorithm configured in the DNS supporting RFC2136. Used only - when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. - Supported values are (case-insensitive): ``HMACMD5`` (default), - ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. - type: string - tsigKeyName: - description: |- - The TSIG Key name configured in the DNS. - If ``tsigSecretSecretRef`` is defined, this field is required. - type: string - tsigSecretSecretRef: - description: |- - The name of the secret containing the TSIG value. - If ``tsigKeyName`` is defined, this field is required. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - nameserver - type: object - route53: - description: Use the AWS Route53 API to manage DNS01 challenge records. - properties: - accessKeyID: - description: |- - The AccessKeyID is used for authentication. - Cannot be set when SecretAccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - type: string - accessKeyIDSecretRef: - description: |- - The SecretAccessKey is used for authentication. If set, pull the AWS - access key ID from a key within a Kubernetes Secret. - Cannot be set when AccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - auth: - description: Auth configures how cert-manager authenticates. - properties: - kubernetes: - description: |- - Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity - by passing a bound ServiceAccount token. - properties: - serviceAccountRef: - description: |- - A reference to a service account that will be used to request a bound - token (also known as "projected token"). To use this field, you must - configure an RBAC rule to let cert-manager request a token. - properties: - audiences: - description: |- - TokenAudiences is an optional list of audiences to include in the - token passed to AWS. The default token consisting of the issuer's namespace - and name is always included. - If unset the audience defaults to `sts.amazonaws.com`. - items: - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: Name of the ServiceAccount used to request a token. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - required: - - kubernetes - type: object - hostedZoneID: - description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. - type: string - region: - description: |- - Override the AWS region. - - Route53 is a global service and does not have regional endpoints but the - region specified here (or via environment variables) is used as a hint to - help compute the correct AWS credential scope and partition when it - connects to Route53. See: - - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) - - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) - - If you omit this region field, cert-manager will use the region from - AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set - in the cert-manager controller Pod. - - The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). - Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: - [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). - In this case this `region` field value is ignored. - - The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). - Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: - [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), - In this case this `region` field value is ignored. - type: string - role: - description: |- - Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey - or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata - type: string - secretAccessKeySecretRef: - description: |- - The SecretAccessKey is used for authentication. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - type: object - webhook: - description: |- - Configure an external webhook based DNS01 challenge solver to manage - DNS01 challenge records. - properties: - config: - description: |- - Additional configuration that should be passed to the webhook apiserver - when challenges are processed. - This can contain arbitrary JSON data. - Secret values should not be specified in this stanza. - If secret values are needed (e.g., credentials for a DNS service), you - should use a SecretKeySelector to reference a Secret resource. - For details on the schema of this field, consult the webhook provider - implementation's documentation. - x-kubernetes-preserve-unknown-fields: true - groupName: - description: |- - The API group name that should be used when POSTing ChallengePayload - resources to the webhook apiserver. - This should be the same as the GroupName specified in the webhook - provider implementation. - type: string - solverName: - description: |- - The name of the solver to use, as defined in the webhook provider - implementation. - This will typically be the name of the provider, e.g., 'cloudflare'. - type: string - required: - - groupName - - solverName - type: object - type: object - http01: - description: |- - Configures cert-manager to attempt to complete authorizations by - performing the HTTP01 challenge flow. - It is not possible to obtain certificates for wildcard domain names - (e.g., `*.example.com`) using the HTTP01 challenge mechanism. - properties: - gatewayHTTPRoute: - description: |- - The Gateway API is a sig-network community API that models service networking - in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will - create HTTPRoutes with the specified labels in the same namespace as the challenge. - This solver is experimental, and fields / behaviour may change in the future. - properties: - labels: - additionalProperties: - type: string - description: |- - Custom labels that will be applied to HTTPRoutes created by cert-manager - while solving HTTP-01 challenges. - type: object - parentRefs: - description: |- - When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. - cert-manager needs to know which parentRefs should be used when creating - the HTTPRoute. Usually, the parentRef references a Gateway. See: - https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways - items: - description: |- - ParentReference identifies an API object (usually a Gateway) that can be considered - a parent of this resource (usually a route). There are two kinds of parent resources - with "Core" support: - - * Gateway (Gateway conformance profile) - * Service (Mesh conformance profile, ClusterIP Services only) - - This API may be extended in the future to support additional kinds of parent - resources. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - properties: - group: - default: gateway.networking.k8s.io - description: |- - Group is the group of the referent. - When unspecified, "gateway.networking.k8s.io" is inferred. - To set the core API group (such as for a "Service" kind referent), - Group must be explicitly set to "" (empty string). - - Support: Core - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: |- - Kind is kind of the referent. - - There are two kinds of parent resources with "Core" support: - - * Gateway (Gateway conformance profile) - * Service (Mesh conformance profile, ClusterIP Services only) - - Support for other resources is Implementation-Specific. - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: |- - Name is the name of the referent. - - Support: Core - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referent. When unspecified, this refers - to the local namespace of the Route. - - Note that there are specific rules for ParentRefs which cross namespace - boundaries. Cross-namespace references are only valid if they are explicitly - allowed by something in the namespace they are referring to. For example: - Gateway has the AllowedRoutes field, and ReferenceGrant provides a - generic way to enable any other kind of cross-namespace reference. - - - ParentRefs from a Route to a Service in the same namespace are "producer" - routes, which apply default routing rules to inbound connections from - any namespace to the Service. - - ParentRefs from a Route to a Service in a different namespace are - "consumer" routes, and these routing rules are only applied to outbound - connections originating from the same namespace as the Route, for which - the intended destination of the connections are a Service targeted as a - ParentRef of the Route. - - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port is the network port this Route targets. It can be interpreted - differently based on the type of parent resource. - - When the parent resource is a Gateway, this targets all listeners - listening on the specified port that also support this kind of Route(and - select this Route). It's not recommended to set `Port` unless the - networking behaviors specified in a Route must apply to a specific port - as opposed to a listener(s) whose port(s) may be changed. When both Port - and SectionName are specified, the name and port of the selected listener - must match both specified values. - - - When the parent resource is a Service, this targets a specific port in the - Service spec. When both Port (experimental) and SectionName are specified, - the name and port of the selected port must match both specified values. - - - Implementations MAY choose to support other parent resources. - Implementations supporting other types of parent resources MUST clearly - document how/if Port is interpreted. - - For the purpose of status, an attachment is considered successful as - long as the parent resource accepts it partially. For example, Gateway - listeners can restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept attachment - from the referencing Route, the Route MUST be considered successfully - attached. If no Gateway listeners accept attachment from this Route, - the Route MUST be considered detached from the Gateway. - - Support: Extended - format: int32 - maximum: 65535 - minimum: 1 - type: integer - sectionName: - description: |- - SectionName is the name of a section within the target resource. In the - following resources, SectionName is interpreted as the following: - - * Gateway: Listener name. When both Port (experimental) and SectionName - are specified, the name and port of the selected listener must match - both specified values. - * Service: Port name. When both Port (experimental) and SectionName - are specified, the name and port of the selected listener must match - both specified values. - - Implementations MAY choose to support attaching Routes to other resources. - If that is the case, they MUST clearly document how SectionName is - interpreted. - - When unspecified (empty string), this will reference the entire resource. - For the purpose of status, an attachment is considered successful if at - least one section in the parent resource accepts it. For example, Gateway - listeners can restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from - the referencing Route, the Route MUST be considered successfully - attached. If no Gateway listeners accept attachment from this Route, the - Route MUST be considered detached from the Gateway. - - Support: Core - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - type: array - x-kubernetes-list-type: atomic - podTemplate: - description: |- - Optional pod template used to configure the ACME challenge solver pods - used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the pod used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver pods. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - type: object - spec: - description: |- - PodSpec defines overrides for the HTTP01 challenge solver pod. - Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. - All other fields will be ignored. - properties: - affinity: - description: If specified, the pod's scheduling constraints - 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 - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - 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 - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - resources: - description: |- - If specified, the pod's resource requirements. - These values override the global resource configuration flags. - Note that when only specifying resource limits, ensure they are greater than or equal - to the corresponding global resource requests configured via controller flags - (--acme-http01-solver-resource-request-cpu, --acme-http01-solver-resource-request-memory). - Kubernetes will reject pod creation if limits are lower than requests, causing challenge failures. - 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 - 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 the global values configured via controller flags. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: If specified, the pod's security context - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - type: object - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - 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 - x-kubernetes-list-type: atomic - type: object - type: object - serviceType: - description: |- - Optional service type for Kubernetes solver service. Supported values - are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - type: object - ingress: - description: |- - The ingress based HTTP01 challenge solver will solve challenges by - creating or modifying Ingress resources in order to route requests for - '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are - provisioned by cert-manager for each Challenge to be completed. - properties: - class: - description: |- - This field configures the annotation `kubernetes.io/ingress.class` when - creating Ingress resources to solve ACME challenges that use this - challenge solver. Only one of `class`, `name` or `ingressClassName` may - be specified. - type: string - ingressClassName: - description: |- - This field configures the field `ingressClassName` on the created Ingress - resources used to solve ACME challenges that use this challenge solver. - This is the recommended way of configuring the ingress class. Only one of - `class`, `name` or `ingressClassName` may be specified. - type: string - ingressTemplate: - description: |- - Optional ingress template used to configure the ACME challenge solver - ingress used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the ingress used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver ingress. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver ingress. - type: object - type: object - type: object - name: - description: |- - The name of the ingress resource that should have ACME challenge solving - routes inserted into it in order to solve HTTP01 challenges. - This is typically used in conjunction with ingress controllers like - ingress-gce, which maintains a 1:1 mapping between external IPs and - ingress resources. Only one of `class`, `name` or `ingressClassName` may - be specified. - type: string - podTemplate: - description: |- - Optional pod template used to configure the ACME challenge solver pods - used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the pod used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver pods. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - type: object - spec: - description: |- - PodSpec defines overrides for the HTTP01 challenge solver pod. - Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. - All other fields will be ignored. - properties: - affinity: - description: If specified, the pod's scheduling constraints - 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 - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - 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 - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - resources: - description: |- - If specified, the pod's resource requirements. - These values override the global resource configuration flags. - Note that when only specifying resource limits, ensure they are greater than or equal - to the corresponding global resource requests configured via controller flags - (--acme-http01-solver-resource-request-cpu, --acme-http01-solver-resource-request-memory). - Kubernetes will reject pod creation if limits are lower than requests, causing challenge failures. - 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 - 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 the global values configured via controller flags. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: If specified, the pod's security context - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - type: object - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - 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 - x-kubernetes-list-type: atomic - type: object - type: object - serviceType: - description: |- - Optional service type for Kubernetes solver service. Supported values - are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - type: object - type: object - selector: - description: |- - Selector selects a set of DNSNames on the Certificate resource that - should be solved using this challenge solver. - If not specified, the solver will be treated as the 'default' solver - with the lowest priority, i.e. if any other solver has a more specific - match, it will be used instead. - properties: - dnsNames: - description: |- - List of DNSNames that this solver will be used to solve. - If specified and a match is found, a dnsNames selector will take - precedence over a dnsZones selector. - If multiple solvers match with the same dnsNames value, the solver - with the most matching labels in matchLabels will be selected. - If neither has more matches, the solver defined earlier in the list - will be selected. - items: - type: string - type: array - x-kubernetes-list-type: atomic - dnsZones: - description: |- - List of DNSZones that this solver will be used to solve. - The most specific DNS zone match specified here will take precedence - over other DNS zone matches, so a solver specifying sys.example.com - will be selected over one specifying example.com for the domain - www.sys.example.com. - If multiple solvers match with the same dnsZones value, the solver - with the most matching labels in matchLabels will be selected. - If neither has more matches, the solver defined earlier in the list - will be selected. - items: - type: string - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - A label selector that is used to refine the set of certificate's that - this challenge solver will apply to. - type: object - type: object - type: object - type: array - x-kubernetes-list-type: atomic - required: - - privateKeySecretRef - - server - type: object - ca: - description: |- - CA configures this issuer to sign certificates using a signing CA keypair - stored in a Secret resource. - This is used to build internal PKIs that are managed by cert-manager. - properties: - crlDistributionPoints: - description: |- - The CRL distribution points is an X.509 v3 certificate extension which identifies - the location of the CRL from which the revocation of this certificate can be checked. - If not set, certificates will be issued without distribution points set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - issuingCertificateURLs: - description: |- - IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates - it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. - As an example, such a URL might be "http://ca.domain.com/ca.crt". - items: - type: string - type: array - x-kubernetes-list-type: atomic - ocspServers: - description: |- - The OCSP server list is an X.509 v3 extension that defines a list of - URLs of OCSP responders. The OCSP responders can be queried for the - revocation status of an issued certificate. If not set, the - certificate will be issued with no OCSP servers set. For example, an - OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". - items: - type: string - type: array - x-kubernetes-list-type: atomic - secretName: - description: |- - SecretName is the name of the secret used to sign Certificates issued - by this Issuer. - type: string - required: - - secretName - type: object - selfSigned: - description: |- - SelfSigned configures this issuer to 'self sign' certificates using the - private key used to create the CertificateRequest object. - properties: - crlDistributionPoints: - description: |- - The CRL distribution points is an X.509 v3 certificate extension which identifies - the location of the CRL from which the revocation of this certificate can be checked. - If not set certificate will be issued without CDP. Values are strings. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - vault: - description: |- - Vault configures this issuer to sign certificates using a HashiCorp Vault - PKI backend. - properties: - auth: - description: Auth configures how cert-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - description: |- - Path where the App Role authentication backend is mounted in Vault, e.g: - "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - path - - roleId - - secretRef - type: object - clientCertificate: - description: |- - ClientCertificate authenticates with Vault by presenting a client - certificate during the request's TLS handshake. - Works only when using HTTPS protocol. - properties: - mountPath: - description: |- - The Vault mountPath here is the mount path to use when authenticating with - Vault. For example, setting a value to `/v1/auth/foo`, will use the path - `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the - default value "/v1/auth/cert" will be used. - type: string - name: - description: |- - Name of the certificate role to authenticate against. - If not set, matching any certificate role, if available. - type: string - secretName: - description: |- - Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing - tls.crt and tls.key) used to authenticate to Vault using TLS client - authentication. - type: string - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - description: |- - The Vault mountPath here is the mount path to use when authenticating with - Vault. For example, setting a value to `/v1/auth/foo`, will use the path - `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the - default value "/v1/auth/kubernetes" will be used. - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - The required Secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. Use of 'ambient credentials' is not - supported. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - serviceAccountRef: - description: |- - A reference to a service account that will be used to request a bound - token (also known as "projected token"). Compared to using "secretRef", - using this field means that you don't rely on statically bound tokens. To - use this field, you must configure an RBAC rule to let cert-manager - request a token. - properties: - audiences: - description: |- - TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token - consisting of the issuer's namespace and name is always included. - items: - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: Name of the ServiceAccount used to request a token. - type: string - required: - - name - type: object - required: - - role - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - type: object - caBundle: - description: |- - Base64-encoded bundle of PEM CAs which will be used to validate the certificate - chain presented by Vault. Only used if using HTTPS to connect to Vault and - ignored for HTTP connections. - Mutually exclusive with CABundleSecretRef. - If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in - the cert-manager controller container is used to validate the TLS connection. - format: byte - type: string - caBundleSecretRef: - description: |- - Reference to a Secret containing a bundle of PEM-encoded CAs to use when - verifying the certificate chain presented by Vault when using HTTPS. - Mutually exclusive with CABundle. - If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in - the cert-manager controller container is used to validate the TLS connection. - If no key for the Secret is specified, cert-manager will default to 'ca.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientCertSecretRef: - description: |- - Reference to a Secret containing a PEM-encoded Client Certificate to use when the - Vault server requires mTLS. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientKeySecretRef: - description: |- - Reference to a Secret containing a PEM-encoded Client Private Key to use when the - Vault server requires mTLS. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: - "my_pki_mount/sign/my-role-name". - type: string - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - serverName: - description: |- - ServerName is used to verify the hostname on the returned certificates - by the Vault server. - type: string - required: - - auth - - path - - server - type: object - venafi: - description: |- - Venafi configures this issuer to sign certificates using a Venafi TPP - or Venafi Cloud policy zone. - properties: - cloud: - description: |- - Cloud specifies the Venafi cloud configuration settings. - Only one of TPP or Cloud may be specified. - properties: - apiTokenSecretRef: - description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - url: - description: |- - URL is the base URL for Venafi Cloud. - Defaults to "https://api.venafi.cloud/". - type: string - required: - - apiTokenSecretRef - type: object - tpp: - description: |- - TPP specifies Trust Protection Platform configuration settings. - Only one of TPP or Cloud may be specified. - properties: - caBundle: - description: |- - Base64-encoded bundle of PEM CAs which will be used to validate the certificate - chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. - If undefined, the certificate bundle in the cert-manager controller container - is used to validate the chain. - format: byte - type: string - caBundleSecretRef: - description: |- - Reference to a Secret containing a base64-encoded bundle of PEM CAs - which will be used to validate the certificate chain presented by the TPP server. - Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. - If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in - the cert-manager controller container is used to validate the TLS connection. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - credentialsRef: - description: |- - CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. - The secret must contain the key 'access-token' for the Access Token Authentication, - or two keys, 'username' and 'password' for the API Keys Authentication. - properties: - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - url: - description: |- - URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, - for example: "https://tpp.example.com/vedsdk". - type: string - required: - - credentialsRef - - url - type: object - zone: - description: |- - Zone is the Venafi Policy Zone to use for this issuer. - All requests made to the Venafi platform will be restricted by the named - zone policy. - This field is required. - type: string - required: - - zone - type: object - type: object - status: - description: Status of the ClusterIssuer. This is set and managed automatically. - properties: - acme: - description: |- - ACME specific status options. - This field should only be set if the Issuer is configured to use an ACME - server to issue certificates. - properties: - lastPrivateKeyHash: - description: |- - LastPrivateKeyHash is a hash of the private key associated with the latest - registered ACME account, in order to track changes made to registered account - associated with the Issuer - type: string - lastRegisteredEmail: - description: |- - LastRegisteredEmail is the email associated with the latest registered - ACME account, in order to track changes made to registered account - associated with the Issuer - type: string - uri: - description: |- - URI is the unique account identifier, which can also be used to retrieve - account details from the CA - type: string - type: object - conditions: - description: |- - List of status conditions to indicate the status of a CertificateRequest. - Known condition types are `Ready`. - items: - description: IssuerCondition contains condition information for an Issuer. - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the timestamp corresponding to the last status - change of this condition. - format: date-time - type: string - message: - description: |- - Message is a human readable description of the details of the last - transition, complementing reason. - type: string - observedGeneration: - description: |- - If set, this represents the .metadata.generation that the condition was - set based upon. - For instance, if .metadata.generation is currently 12, but the - .status.condition[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the Issuer. - format: int64 - type: integer - reason: - description: |- - Reason is a brief machine readable explanation for the condition's last - transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: Type of the condition, known values are (`Ready`). - type: string - required: - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_issuers.yaml b/packages/system/cert-manager-crds/templates/crd-cert-manager.io_issuers.yaml deleted file mode 100644 index 43277f84..00000000 --- a/packages/system/cert-manager-crds/templates/crd-cert-manager.io_issuers.yaml +++ /dev/null @@ -1,3814 +0,0 @@ -{{- if or .Values.crds.enabled .Values.installCRDs }} -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: "issuers.cert-manager.io" - {{- if .Values.crds.keep }} - annotations: - helm.sh/resource-policy: keep - {{- end }} - labels: - {{- include "cert-manager.crd-labels" . | nindent 4 }} -spec: - group: cert-manager.io - names: - categories: - - cert-manager - kind: Issuer - listKind: IssuerList - plural: issuers - shortNames: - - iss - singular: issuer - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type == "Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type == "Ready")].message - name: Status - priority: 1 - type: string - - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: |- - An Issuer represents a certificate issuing authority which can be - referenced as part of `issuerRef` fields. - It is scoped to a single namespace and can therefore only be referenced by - resources within the same namespace. - 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: Desired state of the Issuer resource. - properties: - acme: - description: |- - ACME configures this issuer to communicate with a RFC8555 (ACME) server - to obtain signed x509 certificates. - properties: - caBundle: - description: |- - Base64-encoded bundle of PEM CAs which can be used to validate the certificate - chain presented by the ACME server. - Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various - kinds of security vulnerabilities. - If CABundle and SkipTLSVerify are unset, the system certificate bundle inside - the container is used to validate the TLS connection. - format: byte - type: string - disableAccountKeyGeneration: - description: |- - Enables or disables generating a new ACME account key. - If true, the Issuer resource will *not* request a new account but will expect - the account key to be supplied via an existing secret. - If false, the cert-manager system will generate a new ACME account key - for the Issuer. - Defaults to false. - type: boolean - email: - description: |- - Email is the email address to be associated with the ACME account. - This field is optional, but it is strongly recommended to be set. - It will be used to contact you in case of issues with your account or - certificates, including expiry notification emails. - This field may be updated after the account is initially registered. - type: string - enableDurationFeature: - description: |- - Enables requesting a Not After date on certificates that matches the - duration of the certificate. This is not supported by all ACME servers - like Let's Encrypt. If set to true when the ACME server does not support - it, it will create an error on the Order. - Defaults to false. - type: boolean - externalAccountBinding: - description: |- - ExternalAccountBinding is a reference to a CA external account of the ACME - server. - If set, upon registration cert-manager will attempt to associate the given - external account credentials with the registered ACME account. - properties: - keyAlgorithm: - description: |- - Deprecated: keyAlgorithm field exists for historical compatibility - reasons and should not be used. The algorithm is now hardcoded to HS256 - in golang/x/crypto/acme. - enum: - - HS256 - - HS384 - - HS512 - type: string - keyID: - description: keyID is the ID of the CA key that the External Account is bound to. - type: string - keySecretRef: - description: |- - keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes - Secret which holds the symmetric MAC key of the External Account Binding. - The `key` is the index string that is paired with the key data in the - Secret and should not be confused with the key data itself, or indeed with - the External Account Binding keyID above. - The secret key stored in the Secret **must** be un-padded, base64 URL - encoded data. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - keyID - - keySecretRef - type: object - preferredChain: - description: |- - PreferredChain is the chain to use if the ACME server outputs multiple. - PreferredChain is no guarantee that this one gets delivered by the ACME - endpoint. - For example, for Let's Encrypt's DST cross-sign you would use: - "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. - This value picks the first certificate bundle in the combined set of - ACME default and alternative chains that has a root-most certificate with - this value as its issuer's commonname. - maxLength: 64 - type: string - privateKeySecretRef: - description: |- - PrivateKey is the name of a Kubernetes Secret resource that will be used to - store the automatically generated ACME account private key. - Optionally, a `key` may be specified to select a specific entry within - the named Secret resource. - If `key` is not specified, a default of `tls.key` will be used. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - profile: - description: |- - Profile allows requesting a certificate profile from the ACME server. - Supported profiles are listed by the server's ACME directory URL. - type: string - server: - description: |- - Server is the URL used to access the ACME server's 'directory' endpoint. - For example, for Let's Encrypt's staging endpoint, you would use: - "https://acme-staging-v02.api.letsencrypt.org/directory". - Only ACME v2 endpoints (i.e. RFC 8555) are supported. - type: string - skipTLSVerify: - description: |- - INSECURE: Enables or disables validation of the ACME server TLS certificate. - If true, requests to the ACME server will not have the TLS certificate chain - validated. - Mutually exclusive with CABundle; prefer using CABundle to prevent various - kinds of security vulnerabilities. - Only enable this option in development environments. - If CABundle and SkipTLSVerify are unset, the system certificate bundle inside - the container is used to validate the TLS connection. - Defaults to false. - type: boolean - solvers: - description: |- - Solvers is a list of challenge solvers that will be used to solve - ACME challenges for the matching domains. - Solver configurations must be provided in order to obtain certificates - from an ACME server. - For more information, see: https://cert-manager.io/docs/configuration/acme/ - items: - description: |- - An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. - A selector may be provided to use different solving strategies for different DNS names. - Only one of HTTP01 or DNS01 must be provided. - properties: - dns01: - description: |- - Configures cert-manager to attempt to complete authorizations by - performing the DNS01 challenge flow. - properties: - acmeDNS: - description: |- - Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage - DNS01 challenge records. - properties: - accountSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - host: - type: string - required: - - accountSecretRef - - host - type: object - akamai: - description: Use the Akamai DNS zone management API to manage DNS01 challenge records. - properties: - accessTokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientSecretSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientTokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - serviceConsumerDomain: - type: string - required: - - accessTokenSecretRef - - clientSecretSecretRef - - clientTokenSecretRef - - serviceConsumerDomain - type: object - azureDNS: - description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. - properties: - clientID: - description: |- - Auth: Azure Service Principal: - The ClientID of the Azure Service Principal used to authenticate with Azure DNS. - If set, ClientSecret and TenantID must also be set. - type: string - clientSecretSecretRef: - description: |- - Auth: Azure Service Principal: - A reference to a Secret containing the password associated with the Service Principal. - If set, ClientID and TenantID must also be set. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - environment: - description: name of the Azure environment (default AzurePublicCloud) - enum: - - AzurePublicCloud - - AzureChinaCloud - - AzureGermanCloud - - AzureUSGovernmentCloud - type: string - hostedZoneName: - description: name of the DNS zone that should be used - type: string - managedIdentity: - description: |- - Auth: Azure Workload Identity or Azure Managed Service Identity: - Settings to enable Azure Workload Identity or Azure Managed Service Identity - If set, ClientID, ClientSecret and TenantID must not be set. - properties: - clientID: - description: client ID of the managed identity, cannot be used at the same time as resourceID - type: string - resourceID: - description: |- - resource ID of the managed identity, cannot be used at the same time as clientID - Cannot be used for Azure Managed Service Identity - type: string - tenantID: - description: tenant ID of the managed identity, cannot be used at the same time as resourceID - type: string - type: object - resourceGroupName: - description: resource group the DNS zone is located in - type: string - subscriptionID: - description: ID of the Azure subscription - type: string - tenantID: - description: |- - Auth: Azure Service Principal: - The TenantID of the Azure Service Principal used to authenticate with Azure DNS. - If set, ClientID and ClientSecret must also be set. - type: string - required: - - resourceGroupName - - subscriptionID - type: object - cloudDNS: - description: Use the Google Cloud DNS API to manage DNS01 challenge records. - properties: - hostedZoneName: - description: |- - HostedZoneName is an optional field that tells cert-manager in which - Cloud DNS zone the challenge record has to be created. - If left empty cert-manager will automatically choose a zone. - type: string - project: - type: string - serviceAccountSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - project - type: object - cloudflare: - description: Use the Cloudflare API to manage DNS01 challenge records. - properties: - apiKeySecretRef: - description: |- - API key to use to authenticate with Cloudflare. - Note: using an API token to authenticate is now the recommended method - as it allows greater control of permissions. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - apiTokenSecretRef: - description: API token used to authenticate with Cloudflare. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - email: - description: Email of the account, only required when using API key based authentication. - type: string - type: object - cnameStrategy: - description: |- - CNAMEStrategy configures how the DNS01 provider should handle CNAME - records when found in DNS zones. - enum: - - None - - Follow - type: string - digitalocean: - description: Use the DigitalOcean DNS API to manage DNS01 challenge records. - properties: - tokenSecretRef: - description: |- - A reference to a specific 'key' within a Secret resource. - In some instances, `key` is a required field. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - tokenSecretRef - type: object - rfc2136: - description: |- - Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) - to manage DNS01 challenge records. - properties: - nameserver: - description: |- - The IP address or hostname of an authoritative DNS server supporting - RFC2136 in the form host:port. If the host is an IPv6 address it must be - enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. - This field is required. - type: string - protocol: - description: Protocol to use for dynamic DNS update queries. Valid values are (case-sensitive) ``TCP`` and ``UDP``; ``UDP`` (default). - enum: - - TCP - - UDP - type: string - tsigAlgorithm: - description: |- - The TSIG Algorithm configured in the DNS supporting RFC2136. Used only - when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. - Supported values are (case-insensitive): ``HMACMD5`` (default), - ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. - type: string - tsigKeyName: - description: |- - The TSIG Key name configured in the DNS. - If ``tsigSecretSecretRef`` is defined, this field is required. - type: string - tsigSecretSecretRef: - description: |- - The name of the secret containing the TSIG value. - If ``tsigKeyName`` is defined, this field is required. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - nameserver - type: object - route53: - description: Use the AWS Route53 API to manage DNS01 challenge records. - properties: - accessKeyID: - description: |- - The AccessKeyID is used for authentication. - Cannot be set when SecretAccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - type: string - accessKeyIDSecretRef: - description: |- - The SecretAccessKey is used for authentication. If set, pull the AWS - access key ID from a key within a Kubernetes Secret. - Cannot be set when AccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - auth: - description: Auth configures how cert-manager authenticates. - properties: - kubernetes: - description: |- - Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity - by passing a bound ServiceAccount token. - properties: - serviceAccountRef: - description: |- - A reference to a service account that will be used to request a bound - token (also known as "projected token"). To use this field, you must - configure an RBAC rule to let cert-manager request a token. - properties: - audiences: - description: |- - TokenAudiences is an optional list of audiences to include in the - token passed to AWS. The default token consisting of the issuer's namespace - and name is always included. - If unset the audience defaults to `sts.amazonaws.com`. - items: - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: Name of the ServiceAccount used to request a token. - type: string - required: - - name - type: object - required: - - serviceAccountRef - type: object - required: - - kubernetes - type: object - hostedZoneID: - description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. - type: string - region: - description: |- - Override the AWS region. - - Route53 is a global service and does not have regional endpoints but the - region specified here (or via environment variables) is used as a hint to - help compute the correct AWS credential scope and partition when it - connects to Route53. See: - - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) - - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) - - If you omit this region field, cert-manager will use the region from - AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set - in the cert-manager controller Pod. - - The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). - Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: - [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). - In this case this `region` field value is ignored. - - The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). - Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: - [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), - In this case this `region` field value is ignored. - type: string - role: - description: |- - Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey - or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata - type: string - secretAccessKeySecretRef: - description: |- - The SecretAccessKey is used for authentication. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, - see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - type: object - webhook: - description: |- - Configure an external webhook based DNS01 challenge solver to manage - DNS01 challenge records. - properties: - config: - description: |- - Additional configuration that should be passed to the webhook apiserver - when challenges are processed. - This can contain arbitrary JSON data. - Secret values should not be specified in this stanza. - If secret values are needed (e.g., credentials for a DNS service), you - should use a SecretKeySelector to reference a Secret resource. - For details on the schema of this field, consult the webhook provider - implementation's documentation. - x-kubernetes-preserve-unknown-fields: true - groupName: - description: |- - The API group name that should be used when POSTing ChallengePayload - resources to the webhook apiserver. - This should be the same as the GroupName specified in the webhook - provider implementation. - type: string - solverName: - description: |- - The name of the solver to use, as defined in the webhook provider - implementation. - This will typically be the name of the provider, e.g., 'cloudflare'. - type: string - required: - - groupName - - solverName - type: object - type: object - http01: - description: |- - Configures cert-manager to attempt to complete authorizations by - performing the HTTP01 challenge flow. - It is not possible to obtain certificates for wildcard domain names - (e.g., `*.example.com`) using the HTTP01 challenge mechanism. - properties: - gatewayHTTPRoute: - description: |- - The Gateway API is a sig-network community API that models service networking - in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will - create HTTPRoutes with the specified labels in the same namespace as the challenge. - This solver is experimental, and fields / behaviour may change in the future. - properties: - labels: - additionalProperties: - type: string - description: |- - Custom labels that will be applied to HTTPRoutes created by cert-manager - while solving HTTP-01 challenges. - type: object - parentRefs: - description: |- - When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. - cert-manager needs to know which parentRefs should be used when creating - the HTTPRoute. Usually, the parentRef references a Gateway. See: - https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways - items: - description: |- - ParentReference identifies an API object (usually a Gateway) that can be considered - a parent of this resource (usually a route). There are two kinds of parent resources - with "Core" support: - - * Gateway (Gateway conformance profile) - * Service (Mesh conformance profile, ClusterIP Services only) - - This API may be extended in the future to support additional kinds of parent - resources. - - The API object must be valid in the cluster; the Group and Kind must - be registered in the cluster for this reference to be valid. - properties: - group: - default: gateway.networking.k8s.io - description: |- - Group is the group of the referent. - When unspecified, "gateway.networking.k8s.io" is inferred. - To set the core API group (such as for a "Service" kind referent), - Group must be explicitly set to "" (empty string). - - Support: Core - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: |- - Kind is kind of the referent. - - There are two kinds of parent resources with "Core" support: - - * Gateway (Gateway conformance profile) - * Service (Mesh conformance profile, ClusterIP Services only) - - Support for other resources is Implementation-Specific. - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: |- - Name is the name of the referent. - - Support: Core - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the referent. When unspecified, this refers - to the local namespace of the Route. - - Note that there are specific rules for ParentRefs which cross namespace - boundaries. Cross-namespace references are only valid if they are explicitly - allowed by something in the namespace they are referring to. For example: - Gateway has the AllowedRoutes field, and ReferenceGrant provides a - generic way to enable any other kind of cross-namespace reference. - - - ParentRefs from a Route to a Service in the same namespace are "producer" - routes, which apply default routing rules to inbound connections from - any namespace to the Service. - - ParentRefs from a Route to a Service in a different namespace are - "consumer" routes, and these routing rules are only applied to outbound - connections originating from the same namespace as the Route, for which - the intended destination of the connections are a Service targeted as a - ParentRef of the Route. - - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port is the network port this Route targets. It can be interpreted - differently based on the type of parent resource. - - When the parent resource is a Gateway, this targets all listeners - listening on the specified port that also support this kind of Route(and - select this Route). It's not recommended to set `Port` unless the - networking behaviors specified in a Route must apply to a specific port - as opposed to a listener(s) whose port(s) may be changed. When both Port - and SectionName are specified, the name and port of the selected listener - must match both specified values. - - - When the parent resource is a Service, this targets a specific port in the - Service spec. When both Port (experimental) and SectionName are specified, - the name and port of the selected port must match both specified values. - - - Implementations MAY choose to support other parent resources. - Implementations supporting other types of parent resources MUST clearly - document how/if Port is interpreted. - - For the purpose of status, an attachment is considered successful as - long as the parent resource accepts it partially. For example, Gateway - listeners can restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept attachment - from the referencing Route, the Route MUST be considered successfully - attached. If no Gateway listeners accept attachment from this Route, - the Route MUST be considered detached from the Gateway. - - Support: Extended - format: int32 - maximum: 65535 - minimum: 1 - type: integer - sectionName: - description: |- - SectionName is the name of a section within the target resource. In the - following resources, SectionName is interpreted as the following: - - * Gateway: Listener name. When both Port (experimental) and SectionName - are specified, the name and port of the selected listener must match - both specified values. - * Service: Port name. When both Port (experimental) and SectionName - are specified, the name and port of the selected listener must match - both specified values. - - Implementations MAY choose to support attaching Routes to other resources. - If that is the case, they MUST clearly document how SectionName is - interpreted. - - When unspecified (empty string), this will reference the entire resource. - For the purpose of status, an attachment is considered successful if at - least one section in the parent resource accepts it. For example, Gateway - listeners can restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from - the referencing Route, the Route MUST be considered successfully - attached. If no Gateway listeners accept attachment from this Route, the - Route MUST be considered detached from the Gateway. - - Support: Core - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - type: array - x-kubernetes-list-type: atomic - podTemplate: - description: |- - Optional pod template used to configure the ACME challenge solver pods - used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the pod used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver pods. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - type: object - spec: - description: |- - PodSpec defines overrides for the HTTP01 challenge solver pod. - Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. - All other fields will be ignored. - properties: - affinity: - description: If specified, the pod's scheduling constraints - 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 - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - 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 - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - resources: - description: |- - If specified, the pod's resource requirements. - These values override the global resource configuration flags. - Note that when only specifying resource limits, ensure they are greater than or equal - to the corresponding global resource requests configured via controller flags - (--acme-http01-solver-resource-request-cpu, --acme-http01-solver-resource-request-memory). - Kubernetes will reject pod creation if limits are lower than requests, causing challenge failures. - 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 - 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 the global values configured via controller flags. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: If specified, the pod's security context - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - type: object - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - 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 - x-kubernetes-list-type: atomic - type: object - type: object - serviceType: - description: |- - Optional service type for Kubernetes solver service. Supported values - are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - type: object - ingress: - description: |- - The ingress based HTTP01 challenge solver will solve challenges by - creating or modifying Ingress resources in order to route requests for - '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are - provisioned by cert-manager for each Challenge to be completed. - properties: - class: - description: |- - This field configures the annotation `kubernetes.io/ingress.class` when - creating Ingress resources to solve ACME challenges that use this - challenge solver. Only one of `class`, `name` or `ingressClassName` may - be specified. - type: string - ingressClassName: - description: |- - This field configures the field `ingressClassName` on the created Ingress - resources used to solve ACME challenges that use this challenge solver. - This is the recommended way of configuring the ingress class. Only one of - `class`, `name` or `ingressClassName` may be specified. - type: string - ingressTemplate: - description: |- - Optional ingress template used to configure the ACME challenge solver - ingress used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the ingress used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver ingress. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver ingress. - type: object - type: object - type: object - name: - description: |- - The name of the ingress resource that should have ACME challenge solving - routes inserted into it in order to solve HTTP01 challenges. - This is typically used in conjunction with ingress controllers like - ingress-gce, which maintains a 1:1 mapping between external IPs and - ingress resources. Only one of `class`, `name` or `ingressClassName` may - be specified. - type: string - podTemplate: - description: |- - Optional pod template used to configure the ACME challenge solver pods - used for HTTP01 challenges. - properties: - metadata: - description: |- - ObjectMeta overrides for the pod used to solve HTTP01 challenges. - Only the 'labels' and 'annotations' fields may be set. - If labels or annotations overlap with in-built values, the values here - will override the in-built values. - properties: - annotations: - additionalProperties: - type: string - description: Annotations that should be added to the created ACME HTTP01 solver pods. - type: object - labels: - additionalProperties: - type: string - description: Labels that should be added to the created ACME HTTP01 solver pods. - type: object - type: object - spec: - description: |- - PodSpec defines overrides for the HTTP01 challenge solver pod. - Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. - All other fields will be ignored. - properties: - affinity: - description: If specified, the pod's scheduling constraints - 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 - imagePullSecrets: - description: If specified, the pod's imagePullSecrets - 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 - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - nodeSelector: - additionalProperties: - type: string - description: |- - NodeSelector is a selector which must be true for the pod to fit on a node. - Selector which must match a node's labels for the pod to be scheduled on that node. - More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - type: object - priorityClassName: - description: If specified, the pod's priorityClassName. - type: string - resources: - description: |- - If specified, the pod's resource requirements. - These values override the global resource configuration flags. - Note that when only specifying resource limits, ensure they are greater than or equal - to the corresponding global resource requests configured via controller flags - (--acme-http01-solver-resource-request-cpu, --acme-http01-solver-resource-request-memory). - Kubernetes will reject pod creation if limits are lower than requests, causing challenge failures. - 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 - 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 the global values configured via controller flags. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: If specified, the pod's security context - properties: - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies to the container. - type: string - role: - description: Role is a SELinux role label that applies to the container. - type: string - type: - description: Type is a SELinux type label that applies to the container. - type: string - user: - description: User is a SELinux user label that applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - type: object - serviceAccountName: - description: If specified, the pod's service account - type: string - tolerations: - description: If specified, the pod's tolerations. - 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 - x-kubernetes-list-type: atomic - type: object - type: object - serviceType: - description: |- - Optional service type for Kubernetes solver service. Supported values - are NodePort or ClusterIP. If unset, defaults to NodePort. - type: string - type: object - type: object - selector: - description: |- - Selector selects a set of DNSNames on the Certificate resource that - should be solved using this challenge solver. - If not specified, the solver will be treated as the 'default' solver - with the lowest priority, i.e. if any other solver has a more specific - match, it will be used instead. - properties: - dnsNames: - description: |- - List of DNSNames that this solver will be used to solve. - If specified and a match is found, a dnsNames selector will take - precedence over a dnsZones selector. - If multiple solvers match with the same dnsNames value, the solver - with the most matching labels in matchLabels will be selected. - If neither has more matches, the solver defined earlier in the list - will be selected. - items: - type: string - type: array - x-kubernetes-list-type: atomic - dnsZones: - description: |- - List of DNSZones that this solver will be used to solve. - The most specific DNS zone match specified here will take precedence - over other DNS zone matches, so a solver specifying sys.example.com - will be selected over one specifying example.com for the domain - www.sys.example.com. - If multiple solvers match with the same dnsZones value, the solver - with the most matching labels in matchLabels will be selected. - If neither has more matches, the solver defined earlier in the list - will be selected. - items: - type: string - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - A label selector that is used to refine the set of certificate's that - this challenge solver will apply to. - type: object - type: object - type: object - type: array - x-kubernetes-list-type: atomic - required: - - privateKeySecretRef - - server - type: object - ca: - description: |- - CA configures this issuer to sign certificates using a signing CA keypair - stored in a Secret resource. - This is used to build internal PKIs that are managed by cert-manager. - properties: - crlDistributionPoints: - description: |- - The CRL distribution points is an X.509 v3 certificate extension which identifies - the location of the CRL from which the revocation of this certificate can be checked. - If not set, certificates will be issued without distribution points set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - issuingCertificateURLs: - description: |- - IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates - it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. - As an example, such a URL might be "http://ca.domain.com/ca.crt". - items: - type: string - type: array - x-kubernetes-list-type: atomic - ocspServers: - description: |- - The OCSP server list is an X.509 v3 extension that defines a list of - URLs of OCSP responders. The OCSP responders can be queried for the - revocation status of an issued certificate. If not set, the - certificate will be issued with no OCSP servers set. For example, an - OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". - items: - type: string - type: array - x-kubernetes-list-type: atomic - secretName: - description: |- - SecretName is the name of the secret used to sign Certificates issued - by this Issuer. - type: string - required: - - secretName - type: object - selfSigned: - description: |- - SelfSigned configures this issuer to 'self sign' certificates using the - private key used to create the CertificateRequest object. - properties: - crlDistributionPoints: - description: |- - The CRL distribution points is an X.509 v3 certificate extension which identifies - the location of the CRL from which the revocation of this certificate can be checked. - If not set certificate will be issued without CDP. Values are strings. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - vault: - description: |- - Vault configures this issuer to sign certificates using a HashiCorp Vault - PKI backend. - properties: - auth: - description: Auth configures how cert-manager authenticates with the Vault server. - properties: - appRole: - description: |- - AppRole authenticates with Vault using the App Role auth mechanism, - with the role and secret stored in a Kubernetes Secret resource. - properties: - path: - description: |- - Path where the App Role authentication backend is mounted in Vault, e.g: - "approle" - type: string - roleId: - description: |- - RoleID configured in the App Role authentication backend when setting - up the authentication backend in Vault. - type: string - secretRef: - description: |- - Reference to a key in a Secret that contains the App Role secret used - to authenticate with Vault. - The `key` field must be specified and denotes which entry within the Secret - resource is used as the app role secret. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - required: - - path - - roleId - - secretRef - type: object - clientCertificate: - description: |- - ClientCertificate authenticates with Vault by presenting a client - certificate during the request's TLS handshake. - Works only when using HTTPS protocol. - properties: - mountPath: - description: |- - The Vault mountPath here is the mount path to use when authenticating with - Vault. For example, setting a value to `/v1/auth/foo`, will use the path - `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the - default value "/v1/auth/cert" will be used. - type: string - name: - description: |- - Name of the certificate role to authenticate against. - If not set, matching any certificate role, if available. - type: string - secretName: - description: |- - Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing - tls.crt and tls.key) used to authenticate to Vault using TLS client - authentication. - type: string - type: object - kubernetes: - description: |- - Kubernetes authenticates with Vault by passing the ServiceAccount - token stored in the named Secret resource to the Vault server. - properties: - mountPath: - description: |- - The Vault mountPath here is the mount path to use when authenticating with - Vault. For example, setting a value to `/v1/auth/foo`, will use the path - `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the - default value "/v1/auth/kubernetes" will be used. - type: string - role: - description: |- - A required field containing the Vault Role to assume. A Role binds a - Kubernetes ServiceAccount with a set of Vault policies. - type: string - secretRef: - description: |- - The required Secret field containing a Kubernetes ServiceAccount JWT used - for authenticating with Vault. Use of 'ambient credentials' is not - supported. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - serviceAccountRef: - description: |- - A reference to a service account that will be used to request a bound - token (also known as "projected token"). Compared to using "secretRef", - using this field means that you don't rely on statically bound tokens. To - use this field, you must configure an RBAC rule to let cert-manager - request a token. - properties: - audiences: - description: |- - TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token - consisting of the issuer's namespace and name is always included. - items: - type: string - type: array - x-kubernetes-list-type: atomic - name: - description: Name of the ServiceAccount used to request a token. - type: string - required: - - name - type: object - required: - - role - type: object - tokenSecretRef: - description: TokenSecretRef authenticates with Vault by presenting a token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - type: object - caBundle: - description: |- - Base64-encoded bundle of PEM CAs which will be used to validate the certificate - chain presented by Vault. Only used if using HTTPS to connect to Vault and - ignored for HTTP connections. - Mutually exclusive with CABundleSecretRef. - If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in - the cert-manager controller container is used to validate the TLS connection. - format: byte - type: string - caBundleSecretRef: - description: |- - Reference to a Secret containing a bundle of PEM-encoded CAs to use when - verifying the certificate chain presented by Vault when using HTTPS. - Mutually exclusive with CABundle. - If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in - the cert-manager controller container is used to validate the TLS connection. - If no key for the Secret is specified, cert-manager will default to 'ca.crt'. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientCertSecretRef: - description: |- - Reference to a Secret containing a PEM-encoded Client Certificate to use when the - Vault server requires mTLS. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - clientKeySecretRef: - description: |- - Reference to a Secret containing a PEM-encoded Client Private Key to use when the - Vault server requires mTLS. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - namespace: - description: |- - Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" - More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces - type: string - path: - description: |- - Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: - "my_pki_mount/sign/my-role-name". - type: string - server: - description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' - type: string - serverName: - description: |- - ServerName is used to verify the hostname on the returned certificates - by the Vault server. - type: string - required: - - auth - - path - - server - type: object - venafi: - description: |- - Venafi configures this issuer to sign certificates using a Venafi TPP - or Venafi Cloud policy zone. - properties: - cloud: - description: |- - Cloud specifies the Venafi cloud configuration settings. - Only one of TPP or Cloud may be specified. - properties: - apiTokenSecretRef: - description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - url: - description: |- - URL is the base URL for Venafi Cloud. - Defaults to "https://api.venafi.cloud/". - type: string - required: - - apiTokenSecretRef - type: object - tpp: - description: |- - TPP specifies Trust Protection Platform configuration settings. - Only one of TPP or Cloud may be specified. - properties: - caBundle: - description: |- - Base64-encoded bundle of PEM CAs which will be used to validate the certificate - chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. - If undefined, the certificate bundle in the cert-manager controller container - is used to validate the chain. - format: byte - type: string - caBundleSecretRef: - description: |- - Reference to a Secret containing a base64-encoded bundle of PEM CAs - which will be used to validate the certificate chain presented by the TPP server. - Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. - If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in - the cert-manager controller container is used to validate the TLS connection. - properties: - key: - description: |- - The key of the entry in the Secret resource's `data` field to be used. - Some instances of this field may be defaulted, in others it may be - required. - type: string - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - credentialsRef: - description: |- - CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. - The secret must contain the key 'access-token' for the Access Token Authentication, - or two keys, 'username' and 'password' for the API Keys Authentication. - properties: - name: - description: |- - Name of the resource being referred to. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - url: - description: |- - URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, - for example: "https://tpp.example.com/vedsdk". - type: string - required: - - credentialsRef - - url - type: object - zone: - description: |- - Zone is the Venafi Policy Zone to use for this issuer. - All requests made to the Venafi platform will be restricted by the named - zone policy. - This field is required. - type: string - required: - - zone - type: object - type: object - status: - description: Status of the Issuer. This is set and managed automatically. - properties: - acme: - description: |- - ACME specific status options. - This field should only be set if the Issuer is configured to use an ACME - server to issue certificates. - properties: - lastPrivateKeyHash: - description: |- - LastPrivateKeyHash is a hash of the private key associated with the latest - registered ACME account, in order to track changes made to registered account - associated with the Issuer - type: string - lastRegisteredEmail: - description: |- - LastRegisteredEmail is the email associated with the latest registered - ACME account, in order to track changes made to registered account - associated with the Issuer - type: string - uri: - description: |- - URI is the unique account identifier, which can also be used to retrieve - account details from the CA - type: string - type: object - conditions: - description: |- - List of status conditions to indicate the status of a CertificateRequest. - Known condition types are `Ready`. - items: - description: IssuerCondition contains condition information for an Issuer. - properties: - lastTransitionTime: - description: |- - LastTransitionTime is the timestamp corresponding to the last status - change of this condition. - format: date-time - type: string - message: - description: |- - Message is a human readable description of the details of the last - transition, complementing reason. - type: string - observedGeneration: - description: |- - If set, this represents the .metadata.generation that the condition was - set based upon. - For instance, if .metadata.generation is currently 12, but the - .status.condition[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the Issuer. - format: int64 - type: integer - reason: - description: |- - Reason is a brief machine readable explanation for the condition's last - transition. - type: string - status: - description: Status of the condition, one of (`True`, `False`, `Unknown`). - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: Type of the condition, known values are (`Ready`). - type: string - required: - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} -{{- end }} diff --git a/packages/system/cert-manager-crds/values.yaml b/packages/system/cert-manager-crds/values.yaml index 15136853..0b21fc93 100644 --- a/packages/system/cert-manager-crds/values.yaml +++ b/packages/system/cert-manager-crds/values.yaml @@ -1,8 +1,2 @@ -global: - commonLabels: {} - -creator: helm - -crds: - enabled: true - keep: true +cert-manager: + installCRDs: true diff --git a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml index 3b582082..e93f3f67 100644 --- a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml +++ b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml @@ -1,7 +1,6 @@ -{{- $solver := (index .Values._cluster "solver") | default "http01" }} -{{- $exposeIngress := (index .Values._cluster "expose-ingress") | default "tenant-root" }} +{{- $issuerType := (index .Values._cluster "clusterissuer") | default "http01" }} -apiVersion: cert-manager.io/v1 +apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod @@ -11,16 +10,16 @@ spec: name: letsencrypt-prod server: https://acme-v02.api.letsencrypt.org/directory solvers: - - {{- if eq $solver "dns01" }} + - {{- if eq $issuerType "cloudflare" }} dns01: cloudflare: apiTokenSecretRef: name: cloudflare-api-token-secret key: api-token {{- else }} - http01: - ingress: - ingressClassName: {{ $exposeIngress }} + http01: + ingress: + class: nginx {{- end }} --- @@ -35,16 +34,16 @@ spec: name: letsencrypt-stage server: https://acme-staging-v02.api.letsencrypt.org/directory solvers: - - {{- if eq $solver "dns01" }} + - {{- if eq $issuerType "cloudflare" }} dns01: cloudflare: apiTokenSecretRef: name: cloudflare-api-token-secret key: api-token {{- else }} - http01: - ingress: - ingressClassName: {{ $exposeIngress }} + http01: + ingress: + class: nginx {{- end }} --- diff --git a/packages/system/cert-manager/Makefile b/packages/system/cert-manager/Makefile index c3ff574b..2d256086 100644 --- a/packages/system/cert-manager/Makefile +++ b/packages/system/cert-manager/Makefile @@ -8,6 +8,3 @@ update: helm repo add jetstack https://charts.jetstack.io helm repo update jetstack helm pull jetstack/cert-manager --untar --untardir charts - rm -rf ../cert-manager-crds/templates/* - mv charts/cert-manager/templates/crd-*.yaml ../cert-manager-crds/templates/ - cp charts/cert-manager/templates/_helpers.tpl ../cert-manager-crds/templates/ diff --git a/packages/system/cert-manager/charts/cert-manager/Chart.yaml b/packages/system/cert-manager/charts/cert-manager/Chart.yaml index 2756247d..2a49d00c 100644 --- a/packages/system/cert-manager/charts/cert-manager/Chart.yaml +++ b/packages/system/cert-manager/charts/cert-manager/Chart.yaml @@ -6,7 +6,7 @@ annotations: fingerprint: 1020CF3C033D4F35BAE1C19E1226061C665DF13E url: https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg apiVersion: v2 -appVersion: v1.19.3 +appVersion: v1.17.2 description: A Helm chart for cert-manager home: https://cert-manager.io icon: https://raw.githubusercontent.com/cert-manager/community/4d35a69437d21b76322157e6284be4cd64e6d2b7/logo/logo-small.png @@ -23,4 +23,4 @@ maintainers: name: cert-manager sources: - https://github.com/cert-manager/cert-manager -version: v1.19.3 +version: v1.17.2 diff --git a/packages/system/cert-manager/charts/cert-manager/README.md b/packages/system/cert-manager/charts/cert-manager/README.md index 456e740d..1d502429 100644 --- a/packages/system/cert-manager/charts/cert-manager/README.md +++ b/packages/system/cert-manager/charts/cert-manager/README.md @@ -1,10 +1,10 @@ # cert-manager -cert-manager creates TLS certificates for workloads in your Kubernetes or OpenShift cluster and renews the certificates before they expire. +cert-manager is a Kubernetes addon to automate the management and issuance of +TLS certificates from various issuing sources. -cert-manager can obtain certificates from a [variety of certificate authorities](https://cert-manager.io/docs/configuration/issuers/), including: -[Let's Encrypt](https://cert-manager.io/docs/configuration/acme/), [HashiCorp Vault](https://cert-manager.io/docs/configuration/vault/), -[Venafi](https://cert-manager.io/docs/configuration/venafi/) and [private PKI](https://cert-manager.io/docs/configuration/ca/). +It will ensure certificates are valid and up to date periodically, and attempt +to renew certificates at an appropriate time before expiry. ## Prerequisites @@ -13,21 +13,23 @@ cert-manager can obtain certificates from a [variety of certificate authorities] ## Installing the Chart Full installation instructions, including details on how to configure extra -functionality in cert-manager can be found in the [installation docs](https://cert-manager.io/docs/installation/helm/). +functionality in cert-manager can be found in the [installation docs](https://cert-manager.io/docs/installation/kubernetes/). + +Before installing the chart, you must first install the cert-manager CustomResourceDefinition resources. +This is performed in a separate step to allow you to easily uninstall and reinstall cert-manager without deleting your installed custom resources. + +```bash +$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.crds.yaml +``` To install the chart with the release name `cert-manager`: ```console -# Add the Jetstack Helm repository -helm repo add jetstack https://charts.jetstack.io --force-update +## Add the Jetstack Helm repository +$ helm repo add jetstack https://charts.jetstack.io --force-update -# Install the cert-manager helm chart -helm install \ - cert-manager jetstack/cert-manager \ - --namespace cert-manager \ - --create-namespace \ - --version v1.19.3 \ - --set crds.enabled=true +## Install the cert-manager helm chart +$ helm install cert-manager --namespace cert-manager --version v1.17.2 jetstack/cert-manager ``` In order to begin issuing certificates, you will need to set up a ClusterIssuer @@ -54,25 +56,17 @@ are documented in our full [upgrading guide](https://cert-manager.io/docs/instal To uninstall/delete the `cert-manager` deployment: ```console -helm delete cert-manager --namespace cert-manager +$ helm delete cert-manager --namespace cert-manager ``` The command removes all the Kubernetes components associated with the chart and deletes the release. If you want to completely uninstall cert-manager from your cluster, you will also need to -delete the previously installed CustomResourceDefinition resources. +delete the previously installed CustomResourceDefinition resources: -> ☢️ This will remove all `Issuer`,`ClusterIssuer`,`Certificate`,`CertificateRequest`,`Order` and `Challenge` resources from the cluster: -> -> ```console -> kubectl delete crd \ -> issuers.cert-manager.io \ -> clusterissuers.cert-manager.io \ -> certificates.cert-manager.io \ -> certificaterequests.cert-manager.io \ -> orders.acme.cert-manager.io \ -> challenges.acme.cert-manager.io -> ``` +```console +$ kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.crds.yaml +``` ## Configuration @@ -93,18 +87,6 @@ For example: imagePullSecrets: - name: "image-pull-secret" ``` -#### **global.nodeSelector** ~ `object` -> Default value: -> ```yaml -> {} -> ``` - -Global node selector - -The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). - -If a component-specific nodeSelector is also set, it will be merged and take precedence. - #### **global.commonLabels** ~ `object` > Default value: > ```yaml @@ -126,18 +108,6 @@ The number of old ReplicaSets to retain to allow rollback (if not set, the defau > ``` The optional priority class to be used for the cert-manager pods. -#### **global.hostUsers** ~ `bool` - -Set all pods to run in a user namespace without host access. Experimental: may be removed once the Kubernetes User Namespaces feature is GA. - -Requirements: - - Kubernetes ≥ 1.33, or - - Kubernetes 1.27–1.32 with UserNamespacesSupport feature gate enabled. - -Set to false to run pods in a user namespace without host access. - -See [limitations](https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/#limitations) for details. - #### **global.rbac.create** ~ `bool` > Default value: > ```yaml @@ -260,13 +230,13 @@ This prevents downtime during voluntary disruptions such as during a Node upgrad Pod is currently running. #### **podDisruptionBudget.minAvailable** ~ `unknown` -This configures the minimum available pods for disruptions. It can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%). +This configures the minimum available pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). It cannot be used if `maxUnavailable` is set. #### **podDisruptionBudget.maxUnavailable** ~ `unknown` -This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%). it cannot be used if `minAvailable` is set. +This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). it cannot be used if `minAvailable` is set. #### **featureGates** ~ `string` @@ -330,7 +300,7 @@ Override the "cert-manager.fullname" value. This value is used as part of most o #### **nameOverride** ~ `string` -Override the "cert-manager.name" value, which is used to annotate some of the resources that are created by this Chart (using "app.kubernetes.io/name"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use, e.g., "cainjector.name" which resolves to the value "cainjector"). +Override the "cert-manager.name" value, which is used to annotate some of the resources that are created by this Chart (using "app.kubernetes.io/name"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use eg. "cainjector.name" which resolves to the value "cainjector"). #### **serviceAccount.create** ~ `bool` > Default value: @@ -401,10 +371,10 @@ config: kubernetesAPIBurst: 9000 numberOfConcurrentWorkers: 200 enableGatewayAPI: true - # Feature gates as of v1.18.1. Listed with their default values. + # Feature gates as of v1.17.0. Listed with their default values. # See https://cert-manager.io/docs/cli/controller/ featureGates: - AdditionalCertificateOutputFormats: true # GA - default=true + AdditionalCertificateOutputFormats: true # BETA - default=true AllAlpha: false # ALPHA - default=false AllBeta: false # BETA - default=false ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false @@ -416,10 +386,8 @@ config: ServerSideApply: false # ALPHA - default=false StableCertificateRequestName: true # BETA - default=true UseCertificateRequestBasicConstraints: false # ALPHA - default=false - UseDomainQualifiedFinalizer: true # GA - default=true + UseDomainQualifiedFinalizer: true # BETA - default=false ValidateCAA: false # ALPHA - default=false - DefaultPrivateKeyRotationPolicyAlways: true # BETA - default=true - ACMEHTTP01IngressPathTypeExact: true # BETA - default=true # Configure the metrics server for TLS # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls metricsTLSConfig: @@ -457,7 +425,7 @@ Option to disable cert-manager's build-in auto-approver. The auto-approver appro > - clusterissuers.cert-manager.io/* > ``` -List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because, e.g., you are using approver-policy, you can enable 'disableAutoApproval'. +List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because eg. you are using approver-policy, you can enable 'disableAutoApproval'. ref: https://cert-manager.io/docs/concepts/certificaterequest/#approval #### **extraArgs** ~ `array` @@ -716,7 +684,7 @@ enableServiceLinks indicates whether information about services should be inject Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a ServiceMonitor resource. -Otherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you cannot enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. +Otherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. #### **prometheus.servicemonitor.enabled** ~ `bool` > Default value: > ```yaml @@ -735,14 +703,13 @@ The namespace that the service monitor should live in, defaults to the cert-mana > ``` Specifies the `prometheus` label on the created ServiceMonitor. This is used when different Prometheus instances have label selectors matching different ServiceMonitors. -#### **prometheus.servicemonitor.targetPort** ~ `string,integer` +#### **prometheus.servicemonitor.targetPort** ~ `number` > Default value: > ```yaml -> http-metrics +> 9402 > ``` The target port to set on the ServiceMonitor. This must match the port that the cert-manager controller is listening on for metrics. - #### **prometheus.servicemonitor.path** ~ `string` > Default value: > ```yaml @@ -1002,13 +969,13 @@ This prevents downtime during voluntary disruptions such as during a Node upgrad Pod is currently running. #### **webhook.podDisruptionBudget.minAvailable** ~ `unknown` -This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%). +This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). It cannot be used if `maxUnavailable` is set. #### **webhook.podDisruptionBudget.maxUnavailable** ~ `unknown` -This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%). +This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). It cannot be used if `minAvailable` is set. @@ -1326,8 +1293,6 @@ Create network policies for the webhooks. > - from: > - ipBlock: > cidr: 0.0.0.0/0 -> - ipBlock: -> cidr: ::/0 > ``` Ingress rule for the webhook network policy. By default, it allows all inbound traffic. @@ -1349,8 +1314,6 @@ Ingress rule for the webhook network policy. By default, it allows all inbound t > to: > - ipBlock: > cidr: 0.0.0.0/0 -> - ipBlock: -> cidr: ::/0 > ``` Egress rule for the webhook network policy. By default, it allows all outbound traffic to ports 80 and 443, as well as DNS ports. @@ -1479,14 +1442,14 @@ Pod is currently running. #### **cainjector.podDisruptionBudget.minAvailable** ~ `unknown` `minAvailable` configures the minimum available pods for disruptions. It can either be set to -an integer (e.g., 1) or a percentage value (e.g., 25%). +an integer (e.g. 1) or a percentage value (e.g. 25%). Cannot be used if `maxUnavailable` is set. #### **cainjector.podDisruptionBudget.maxUnavailable** ~ `unknown` `maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to -an integer (e.g., 1) or a percentage value (e.g., 25%). +an integer (e.g. 1) or a percentage value (e.g. 25%). Cannot be used if `minAvailable` is set. diff --git a/packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt b/packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt index 4d0b4b60..341d1012 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt +++ b/packages/system/cert-manager/charts/cert-manager/templates/NOTES.txt @@ -1,12 +1,6 @@ {{- if .Values.installCRDs }} ⚠️ WARNING: `installCRDs` is deprecated, use `crds.enabled` instead. - {{- end }} -⚠️ WARNING: New default private key rotation policy for Certificate resources. -The default private key rotation policy for Certificate resources was -changed to `Always` in cert-manager >= v1.18.0. -Learn more in the [1.18 release notes](https://cert-manager.io/docs/releases/release-notes/release-notes-1.18). - cert-manager {{ .Chart.AppVersion }} has been deployed successfully! In order to begin issuing certificates, you will need to set up a ClusterIssuer diff --git a/packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl b/packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl index f85373f3..e15fa191 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl +++ b/packages/system/cert-manager/charts/cert-manager/templates/_helpers.tpl @@ -187,17 +187,6 @@ See https://github.com/cert-manager/cert-manager/issues/6329 for a list of linke {{- end }} {{- end }} -{{/* -Labels for the CRD resources. -*/}} -{{- define "cert-manager.crd-labels" -}} -app: "{{ template "cert-manager.name" . }}" -app.kubernetes.io/name: "{{ template "cert-manager.name" . }}" -app.kubernetes.io/instance: "{{ .Release.Name }}" -app.kubernetes.io/component: "crds" -{{ include "labels" . }} -{{- end -}} - {{/* Check that the user has not set both .installCRDs and .crds.enabled or set .installCRDs and disabled .crds.keep. diff --git a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml index b5434caa..dc14ab02 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/cainjector-deployment.yaml @@ -67,9 +67,6 @@ spec: {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} - {{- if (hasKey .Values.global "hostUsers") }} - hostUsers: {{ .Values.global.hostUsers }} - {{- end }} {{- with .Values.cainjector.securityContext }} securityContext: {{- toYaml . | nindent 8 }} @@ -139,13 +136,9 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} {{- end }} - {{- $nodeSelector := .Values.global.nodeSelector | default dict }} - {{- $nodeSelector = merge $nodeSelector (.Values.cainjector.nodeSelector | default dict) }} - {{- with $nodeSelector }} + {{- with .Values.cainjector.nodeSelector }} nodeSelector: - {{- range $key, $value := . }} - {{ $key }}: {{ $value | quote }} - {{- end }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.cainjector.affinity }} affinity: diff --git a/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml b/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml new file mode 100644 index 00000000..f5f8ec43 --- /dev/null +++ b/packages/system/cert-manager/charts/cert-manager/templates/crds.yaml @@ -0,0 +1,12036 @@ +# {{- include "cert-manager.crd-check" . }} +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificaterequests.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: CertificateRequest + listKind: CertificateRequestList + plural: certificaterequests + shortNames: + - cr + - crs + singular: certificaterequest + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Approved")].status + name: Approved + type: string + - jsonPath: .status.conditions[?(@.type=="Denied")].status + name: Denied + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + type: string + - jsonPath: .spec.username + name: Requester + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A CertificateRequest is used to request a signed certificate from one of the + configured issuers. + + All fields within the CertificateRequest's `spec` are immutable after creation. + A CertificateRequest will either succeed or fail, as denoted by its `Ready` status + condition and its `status.failureTime` field. + + A CertificateRequest is a one-shot resource, meaning it represents a single + point in time request for a certificate and cannot be re-used. + type: object + 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: |- + Specification of the desired state of the CertificateRequest resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - request + properties: + duration: + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + type: string + extra: + description: |- + Extra contains extra attributes of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: object + additionalProperties: + type: array + items: + type: string + groups: + description: |- + Groups contains group membership of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: array + items: + type: string + x-kubernetes-list-type: atomic + isCA: + description: |- + Requested basic constraints isCA value. Note that the issuer may choose + to ignore the requested isCA value, just like any other requested attribute. + + NOTE: If the CSR in the `Request` field has a BasicConstraints extension, + it must have the same isCA value as specified here. + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. + type: boolean + issuerRef: + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + The `name` field of the reference must always be specified. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: |- + The PEM-encoded X.509 certificate signing request to be submitted to the + issuer for signing. + + If the CSR has a BasicConstraints extension, its isCA attribute must + match the `isCA` value of this CertificateRequest. + If the CSR has a KeyUsage extension, its key usages must match the + key usages in the `usages` field of this CertificateRequest. + If the CSR has a ExtKeyUsage extension, its extended key usages + must match the extended key usages in the `usages` field of this + CertificateRequest. + type: string + format: byte + uid: + description: |- + UID contains the uid of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: string + usages: + description: |- + Requested key usages and extended key usages. + + NOTE: If the CSR in the `Request` field has uses the KeyUsage or + ExtKeyUsage extension, these extensions must have the same values + as specified here without any additional values. + + If unset, defaults to `digital signature` and `key encipherment`. + type: array + items: + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + username: + description: |- + Username contains the name of the user that created the CertificateRequest. + Populated by the cert-manager webhook on creation and immutable. + type: string + status: + description: |- + Status of the CertificateRequest. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + properties: + ca: + description: |- + The PEM encoded X.509 certificate of the signer, also known as the CA + (Certificate Authority). + This is set on a best-effort basis by different issuers. + If not set, the CA is assumed to be unknown/not available. + type: string + format: byte + certificate: + description: |- + The PEM encoded X.509 certificate resulting from the certificate + signing request. + If not set, the CertificateRequest has either not been completed or has + failed. More information on failure can be found by checking the + `conditions` field. + type: string + format: byte + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`, `InvalidRequest`, `Approved` and `Denied`. + type: array + items: + description: CertificateRequestCondition contains condition information for a CertificateRequest. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: |- + Type of the condition, known values are (`Ready`, `InvalidRequest`, + `Approved`, `Denied`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failureTime: + description: |- + FailureTime stores the time that this CertificateRequest failed. This is + used to influence garbage collection and back-off. + type: string + format: date-time + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: certificates.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Certificate + listKind: CertificateList + plural: certificates + shortNames: + - cert + - certs + singular: certificate + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .spec.secretName + name: Secret + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A Certificate resource should be created to ensure an up to date and signed + X.509 certificate is stored in the Kubernetes Secret resource named in `spec.secretName`. + + The stored certificate will be renewed before it expires (as configured by `spec.renewBefore`). + type: object + 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: |- + Specification of the desired state of the Certificate resource. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + required: + - issuerRef + - secretName + properties: + additionalOutputFormats: + description: |- + Defines extra output formats of the private key and signed certificate chain + to be written to this Certificate's target Secret. + + This is a Beta Feature enabled by default. It can be disabled with the + `--feature-gates=AdditionalCertificateOutputFormats=false` option set on both + the controller and webhook components. + type: array + items: + description: |- + CertificateAdditionalOutputFormat defines an additional output format of a + Certificate resource. These contain supplementary data formats of the signed + certificate chain and paired private key. + type: object + required: + - type + properties: + type: + description: |- + Type is the name of the format type that should be written to the + Certificate's target Secret. + type: string + enum: + - DER + - CombinedPEM + commonName: + description: |- + Requested common name X509 certificate subject attribute. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + NOTE: TLS clients will ignore this value when any subject alternative name is + set (see https://tools.ietf.org/html/rfc6125#section-6.4.4). + + Should have a length of 64 characters or fewer to avoid generating invalid CSRs. + Cannot be set if the `literalSubject` field is set. + type: string + dnsNames: + description: Requested DNS subject alternative names. + type: array + items: + type: string + duration: + description: |- + Requested 'duration' (i.e. lifetime) of the Certificate. Note that the + issuer may choose to ignore the requested duration, just like any other + requested attribute. + + If unset, this defaults to 90 days. + Minimum accepted duration is 1 hour. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. + type: string + emailAddresses: + description: Requested email subject alternative names. + type: array + items: + type: string + encodeUsagesInRequest: + description: |- + Whether the KeyUsage and ExtKeyUsage extensions should be set in the encoded CSR. + + This option defaults to true, and should only be disabled if the target + issuer does not support CSRs with these X509 KeyUsage/ ExtKeyUsage extensions. + type: boolean + ipAddresses: + description: Requested IP address subject alternative names. + type: array + items: + type: string + isCA: + description: |- + Requested basic constraints isCA value. + The isCA value is used to set the `isCA` field on the created CertificateRequest + resources. Note that the issuer may choose to ignore the requested isCA value, just + like any other requested attribute. + + If true, this will automatically add the `cert sign` usage to the list + of requested `usages`. + type: boolean + issuerRef: + description: |- + Reference to the issuer responsible for issuing the certificate. + If the issuer is namespace-scoped, it must be in the same namespace + as the Certificate. If the issuer is cluster-scoped, it can be used + from any namespace. + + The `name` field of the reference must always be specified. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + keystores: + description: Additional keystore output formats to be stored in the Certificate's Secret. + type: object + properties: + jks: + description: |- + JKS configures options for storing a JKS keystore in the + `spec.secretName` Secret resource. + type: object + required: + - create + properties: + alias: + description: |- + Alias specifies the alias of the key in the keystore, required by the JKS format. + If not provided, the default alias `certificate` will be used. + type: string + create: + description: |- + Create enables JKS keystore creation for the Certificate. + If true, a file named `keystore.jks` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef` or `password`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.jks` + will also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` + containing the issuing Certificate Authority + type: boolean + password: + description: |- + Password provides a literal password used to encrypt the JKS keystore. + Mutually exclusive with passwordSecretRef. + One of password or passwordSecretRef must provide a password with a non-zero length. + type: string + passwordSecretRef: + description: |- + PasswordSecretRef is a reference to a non-empty key in a Secret resource + containing the password used to encrypt the JKS keystore. + Mutually exclusive with password. + One of password or passwordSecretRef must provide a password with a non-zero length. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + pkcs12: + description: |- + PKCS12 configures options for storing a PKCS12 keystore in the + `spec.secretName` Secret resource. + type: object + required: + - create + properties: + create: + description: |- + Create enables PKCS12 keystore creation for the Certificate. + If true, a file named `keystore.p12` will be created in the target + Secret resource, encrypted using the password stored in + `passwordSecretRef` or in `password`. + The keystore file will be updated immediately. + If the issuer provided a CA certificate, a file named `truststore.p12` will + also be created in the target Secret resource, encrypted using the + password stored in `passwordSecretRef` containing the issuing Certificate + Authority + type: boolean + password: + description: |- + Password provides a literal password used to encrypt the PKCS#12 keystore. + Mutually exclusive with passwordSecretRef. + One of password or passwordSecretRef must provide a password with a non-zero length. + type: string + passwordSecretRef: + description: |- + PasswordSecretRef is a reference to a non-empty key in a Secret resource + containing the password used to encrypt the PKCS#12 keystore. + Mutually exclusive with password. + One of password or passwordSecretRef must provide a password with a non-zero length. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + profile: + description: |- + Profile specifies the key and certificate encryption algorithms and the HMAC algorithm + used to create the PKCS12 keystore. Default value is `LegacyRC2` for backward compatibility. + + If provided, allowed values are: + `LegacyRC2`: Deprecated. Not supported by default in OpenSSL 3 or Java 20. + `LegacyDES`: Less secure algorithm. Use this option for maximal compatibility. + `Modern2023`: Secure algorithm. Use this option in case you have to always use secure algorithms + (eg. because of company policy). Please note that the security of the algorithm is not that important + in reality, because the unencrypted certificate and private key are also stored in the Secret. + type: string + enum: + - LegacyRC2 + - LegacyDES + - Modern2023 + literalSubject: + description: |- + Requested X.509 certificate subject, represented using the LDAP "String + Representation of a Distinguished Name" [1]. + Important: the LDAP string format also specifies the order of the attributes + in the subject, this is important when issuing certs for LDAP authentication. + Example: `CN=foo,DC=corp,DC=example,DC=com` + More info [1]: https://datatracker.ietf.org/doc/html/rfc4514 + More info: https://github.com/cert-manager/cert-manager/issues/3203 + More info: https://github.com/cert-manager/cert-manager/issues/4424 + + Cannot be set if the `subject` or `commonName` field is set. + type: string + nameConstraints: + description: |- + x.509 certificate NameConstraint extension which MUST NOT be used in a non-CA certificate. + More Info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10 + + This is an Alpha Feature and is only enabled with the + `--feature-gates=NameConstraints=true` option set on both + the controller and webhook components. + type: object + properties: + critical: + description: if true then the name constraints are marked critical. + type: boolean + excluded: + description: |- + Excluded contains the constraints which must be disallowed. Any name matching a + restriction in the excluded field is invalid regardless + of information appearing in the permitted + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + permitted: + description: Permitted contains the constraints in which the names must be located. + type: object + properties: + dnsDomains: + description: DNSDomains is a list of DNS domains that are permitted or excluded. + type: array + items: + type: string + emailAddresses: + description: EmailAddresses is a list of Email Addresses that are permitted or excluded. + type: array + items: + type: string + ipRanges: + description: |- + IPRanges is a list of IP Ranges that are permitted or excluded. + This should be a valid CIDR notation. + type: array + items: + type: string + uriDomains: + description: URIDomains is a list of URI domains that are permitted or excluded. + type: array + items: + type: string + otherNames: + description: |- + `otherNames` is an escape hatch for SAN that allows any type. We currently restrict the support to string like otherNames, cf RFC 5280 p 37 + Any UTF8 String valued otherName can be passed with by setting the keys oid: x.x.x.x and UTF8Value: somevalue for `otherName`. + Most commonly this would be UPN set with oid: 1.3.6.1.4.1.311.20.2.3 + You should ensure that any OID passed is valid for the UTF8String type as we do not explicitly validate this. + type: array + items: + type: object + properties: + oid: + description: |- + OID is the object identifier for the otherName SAN. + The object identifier must be expressed as a dotted string, for + example, "1.2.840.113556.1.4.221". + type: string + utf8Value: + description: |- + utf8Value is the string value of the otherName SAN. + The utf8Value accepts any valid UTF8 string to set as value for the otherName SAN. + type: string + privateKey: + description: |- + Private key options. These include the key algorithm and size, the used + encoding and the rotation policy. + type: object + properties: + algorithm: + description: |- + Algorithm is the private key algorithm of the corresponding private key + for this certificate. + + If provided, allowed values are either `RSA`, `ECDSA` or `Ed25519`. + If `algorithm` is specified and `size` is not provided, + key size of 2048 will be used for `RSA` key algorithm and + key size of 256 will be used for `ECDSA` key algorithm. + key size is ignored when using the `Ed25519` key algorithm. + type: string + enum: + - RSA + - ECDSA + - Ed25519 + encoding: + description: |- + The private key cryptography standards (PKCS) encoding for this + certificate's private key to be encoded in. + + If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 + and PKCS#8, respectively. + Defaults to `PKCS1` if not specified. + type: string + enum: + - PKCS1 + - PKCS8 + rotationPolicy: + description: |- + RotationPolicy controls how private keys should be regenerated when a + re-issuance is being processed. + + If set to `Never`, a private key will only be generated if one does not + already exist in the target `spec.secretName`. If one does exist but it + does not have the correct algorithm or size, a warning will be raised + to await user intervention. + If set to `Always`, a private key matching the specified requirements + will be generated whenever a re-issuance occurs. + Default is `Never` for backward compatibility. + type: string + enum: + - Never + - Always + size: + description: |- + Size is the key bit size of the corresponding private key for this certificate. + + If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, + and will default to `2048` if not specified. + If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, + and will default to `256` if not specified. + If `algorithm` is set to `Ed25519`, Size is ignored. + No other values are allowed. + type: integer + renewBefore: + description: |- + How long before the currently issued certificate's expiry cert-manager should + renew the certificate. For example, if a certificate is valid for 60 minutes, + and `renewBefore=10m`, cert-manager will begin to attempt to renew the certificate + 50 minutes after it was issued (i.e. when there are 10 minutes remaining until + the certificate is no longer valid). + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + If unset, this defaults to 1/3 of the issued certificate's lifetime. + Minimum accepted value is 5 minutes. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration. + Cannot be set if the `renewBeforePercentage` field is set. + type: string + renewBeforePercentage: + description: |- + `renewBeforePercentage` is like `renewBefore`, except it is a relative percentage + rather than an absolute duration. For example, if a certificate is valid for 60 + minutes, and `renewBeforePercentage=25`, cert-manager will begin to attempt to + renew the certificate 45 minutes after it was issued (i.e. when there are 15 + minutes (25%) remaining until the certificate is no longer valid). + + NOTE: The actual lifetime of the issued certificate is used to determine the + renewal time. If an issuer returns a certificate with a different lifetime than + the one requested, cert-manager will use the lifetime of the issued certificate. + + Value must be an integer in the range (0,100). The minimum effective + `renewBefore` derived from the `renewBeforePercentage` and `duration` fields is 5 + minutes. + Cannot be set if the `renewBefore` field is set. + type: integer + format: int32 + revisionHistoryLimit: + description: |- + The maximum number of CertificateRequest revisions that are maintained in + the Certificate's history. Each revision represents a single `CertificateRequest` + created by this Certificate, either when it was created, renewed, or Spec + was changed. Revisions will be removed by oldest first if the number of + revisions exceeds this number. + + If set, revisionHistoryLimit must be a value of `1` or greater. + If unset (`nil`), revisions will not be garbage collected. + Default value is `nil`. + type: integer + format: int32 + secretName: + description: |- + Name of the Secret resource that will be automatically created and + managed by this Certificate resource. It will be populated with a + private key and certificate, signed by the denoted issuer. The Secret + resource lives in the same namespace as the Certificate resource. + type: string + secretTemplate: + description: |- + Defines annotations and labels to be copied to the Certificate's Secret. + Labels and annotations on the Secret will be changed as they appear on the + SecretTemplate when added or removed. SecretTemplate annotations are added + in conjunction with, and cannot overwrite, the base set of annotations + cert-manager sets on the Certificate's Secret. + type: object + properties: + annotations: + description: Annotations is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + labels: + description: Labels is a key value map to be copied to the target Kubernetes Secret. + type: object + additionalProperties: + type: string + subject: + description: |- + Requested set of X509 certificate subject attributes. + More info: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6 + + The common name attribute is specified separately in the `commonName` field. + Cannot be set if the `literalSubject` field is set. + type: object + properties: + countries: + description: Countries to be used on the Certificate. + type: array + items: + type: string + localities: + description: Cities to be used on the Certificate. + type: array + items: + type: string + organizationalUnits: + description: Organizational Units to be used on the Certificate. + type: array + items: + type: string + organizations: + description: Organizations to be used on the Certificate. + type: array + items: + type: string + postalCodes: + description: Postal codes to be used on the Certificate. + type: array + items: + type: string + provinces: + description: State/Provinces to be used on the Certificate. + type: array + items: + type: string + serialNumber: + description: Serial number to be used on the Certificate. + type: string + streetAddresses: + description: Street addresses to be used on the Certificate. + type: array + items: + type: string + uris: + description: Requested URI subject alternative names. + type: array + items: + type: string + usages: + description: |- + Requested key usages and extended key usages. + These usages are used to set the `usages` field on the created CertificateRequest + resources. If `encodeUsagesInRequest` is unset or set to `true`, the usages + will additionally be encoded in the `request` field which contains the CSR blob. + + If unset, defaults to `digital signature` and `key encipherment`. + type: array + items: + description: |- + KeyUsage specifies valid usage contexts for keys. + See: + https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + + Valid KeyUsage values are as follows: + "signing", + "digital signature", + "content commitment", + "key encipherment", + "key agreement", + "data encipherment", + "cert sign", + "crl sign", + "encipher only", + "decipher only", + "any", + "server auth", + "client auth", + "code signing", + "email protection", + "s/mime", + "ipsec end system", + "ipsec tunnel", + "ipsec user", + "timestamping", + "ocsp signing", + "microsoft sgc", + "netscape sgc" + type: string + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + status: + description: |- + Status of the Certificate. + This is set and managed automatically. + Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + type: object + properties: + conditions: + description: |- + List of status conditions to indicate the status of certificates. + Known condition types are `Ready` and `Issuing`. + type: array + items: + description: CertificateCondition contains condition information for a Certificate. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Certificate. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`, `Issuing`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failedIssuanceAttempts: + description: |- + The number of continuous failed issuance attempts up till now. This + field gets removed (if set) on a successful issuance and gets set to + 1 if unset and an issuance has failed. If an issuance has failed, the + delay till the next issuance will be calculated using formula + time.Hour * 2 ^ (failedIssuanceAttempts - 1). + type: integer + lastFailureTime: + description: |- + LastFailureTime is set only if the latest issuance for this + Certificate failed and contains the time of the failure. If an + issuance has failed, the delay till the next issuance will be + calculated using formula time.Hour * 2 ^ (failedIssuanceAttempts - + 1). If the latest issuance has succeeded this field will be unset. + type: string + format: date-time + nextPrivateKeySecretName: + description: |- + The name of the Secret resource containing the private key to be used + for the next certificate iteration. + The keymanager controller will automatically set this field if the + `Issuing` condition is set to `True`. + It will automatically unset this field when the Issuing condition is + not set or False. + type: string + notAfter: + description: |- + The expiration time of the certificate stored in the secret named + by this resource in `spec.secretName`. + type: string + format: date-time + notBefore: + description: |- + The time after which the certificate stored in the secret named + by this resource in `spec.secretName` is valid. + type: string + format: date-time + renewalTime: + description: |- + RenewalTime is the time at which the certificate will be next + renewed. + If not set, no upcoming renewal is scheduled. + type: string + format: date-time + revision: + description: |- + The current 'revision' of the certificate as issued. + + When a CertificateRequest resource is created, it will have the + `cert-manager.io/certificate-revision` set to one greater than the + current value of this field. + + Upon issuance, this field will be set to the value of the annotation + on the CertificateRequest resource used to issue the certificate. + + Persisting the value on the CertificateRequest resource allows the + certificates controller to know whether a request is part of an old + issuance or if it is part of the ongoing revision's issuance by + checking if the revision value in the annotation is greater than this + field. + type: integer + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: challenges.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Challenge + listKind: ChallengeList + plural: challenges + singular: challenge + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.dnsName + name: Domain + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: Challenge is a type to represent a Challenge request with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - authorizationURL + - dnsName + - issuerRef + - key + - solver + - token + - type + - url + properties: + authorizationURL: + description: |- + The URL to the ACME Authorization resource that this + challenge is a part of. + type: string + dnsName: + description: |- + dnsName is the identifier that this challenge is for, e.g. example.com. + If the requested DNSName is a 'wildcard', this field MUST be set to the + non-wildcard domain, e.g. for `*.example.com`, it must be `example.com`. + type: string + issuerRef: + description: |- + References a properly configured ACME-type Issuer which should + be used to create this Challenge. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Challenge will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + key: + description: |- + The ACME challenge key for this challenge + For HTTP01 challenges, this is the value that must be responded with to + complete the HTTP01 challenge in the format: + `.`. + For DNS01 challenges, this is the base64 encoded SHA256 sum of the + `.` + text that must be set as the TXT record content. + type: string + solver: + description: |- + Contains the domain solving configuration that should be used to + solve this challenge resource. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + tenantID: + description: tenant ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + token: + description: |- + The ACME challenge token for this challenge. + This is the raw value returned from the ACME server. + type: string + type: + description: |- + The type of ACME challenge this resource represents. + One of "HTTP-01" or "DNS-01". + type: string + enum: + - HTTP-01 + - DNS-01 + url: + description: |- + The URL of the ACME Challenge resource for this challenge. + This can be used to lookup details about the status of this challenge. + type: string + wildcard: + description: |- + wildcard will be true if this challenge is for a wildcard identifier, + for example '*.example.com'. + type: boolean + status: + type: object + properties: + presented: + description: |- + presented will be set to true if the challenge values for this challenge + are currently 'presented'. + This *does not* imply the self check is passing. Only that the values + have been 'submitted' for the appropriate challenge mechanism (i.e. the + DNS01 TXT record has been presented, or the HTTP01 configuration has been + configured). + type: boolean + processing: + description: |- + Used to denote whether this challenge should be processed or not. + This field will only be set to true by the 'scheduling' component. + It will only be set to false by the 'challenges' controller, after the + challenge has reached a final state or timed out. + If this field is set to false, the challenge controller will not take + any more action. + type: boolean + reason: + description: |- + Contains human readable information on why the Challenge is in the + current state. + type: string + state: + description: |- + Contains the current 'state' of the challenge. + If not set, the state of the challenge is unknown. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + served: true + storage: true + subresources: + status: {} + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterissuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: ClusterIssuer + listKind: ClusterIssuerList + plural: clusterissuers + singular: clusterissuer + categories: + - cert-manager + scope: Cluster + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + A ClusterIssuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is similar to an Issuer, however it is cluster-scoped and therefore can + be referenced by resources that exist in *any* namespace, not just the same + namespace as the referent. + type: object + required: + - spec + 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: Desired state of the ClusterIssuer resource. + type: object + properties: + acme: + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. + type: boolean + email: + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. + type: boolean + externalAccountBinding: + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + preferredChain: + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. + type: string + maxLength: 64 + privateKeySecretRef: + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + server: + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. + type: string + skipTLSVerify: + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. + type: boolean + solvers: + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ + type: array + items: + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + tenantID: + description: tenant ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". + type: array + items: + type: string + ocspServers: + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. + type: string + selfSigned: + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertificate: + description: |- + ClientCertificate authenticates with Vault by presenting a client + certificate during the request's TLS handshake. + Works only when using HTTPS protocol. + type: object + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/cert" will be used. + type: string + name: + description: |- + Name of the certificate role to authenticate against. + If not set, matching any certificate role, if available. + type: string + secretName: + description: |- + Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing + tls.crt and tls.key) used to authenticate to Vault using TLS client + authentication. + type: string + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a base64-encoded bundle of PEM CAs + which will be used to validate the certificate chain presented by the TPP server. + Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + credentialsRef: + description: |- + CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + The secret must contain the key 'access-token' for the Access Token Authentication, + or two keys, 'username' and 'password' for the API Keys Authentication. + type: object + required: + - name + properties: + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". + type: string + zone: + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. + type: string + status: + description: Status of the ClusterIssuer. This is set and managed automatically. + type: object + properties: + acme: + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + lastRegisteredEmail: + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + uri: + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA + type: string + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: issuers.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: cert-manager.io + names: + kind: Issuer + listKind: IssuerList + plural: issuers + singular: issuer + categories: + - cert-manager + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: |- + An Issuer represents a certificate issuing authority which can be + referenced as part of `issuerRef` fields. + It is scoped to a single namespace and can therefore only be referenced by + resources within the same namespace. + type: object + required: + - spec + 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: Desired state of the Issuer resource. + type: object + properties: + acme: + description: |- + ACME configures this issuer to communicate with a RFC8555 (ACME) server + to obtain signed x509 certificates. + type: object + required: + - privateKeySecretRef + - server + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which can be used to validate the certificate + chain presented by the ACME server. + Mutually exclusive with SkipTLSVerify; prefer using CABundle to prevent various + kinds of security vulnerabilities. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + type: string + format: byte + disableAccountKeyGeneration: + description: |- + Enables or disables generating a new ACME account key. + If true, the Issuer resource will *not* request a new account but will expect + the account key to be supplied via an existing secret. + If false, the cert-manager system will generate a new ACME account key + for the Issuer. + Defaults to false. + type: boolean + email: + description: |- + Email is the email address to be associated with the ACME account. + This field is optional, but it is strongly recommended to be set. + It will be used to contact you in case of issues with your account or + certificates, including expiry notification emails. + This field may be updated after the account is initially registered. + type: string + enableDurationFeature: + description: |- + Enables requesting a Not After date on certificates that matches the + duration of the certificate. This is not supported by all ACME servers + like Let's Encrypt. If set to true when the ACME server does not support + it, it will create an error on the Order. + Defaults to false. + type: boolean + externalAccountBinding: + description: |- + ExternalAccountBinding is a reference to a CA external account of the ACME + server. + If set, upon registration cert-manager will attempt to associate the given + external account credentials with the registered ACME account. + type: object + required: + - keyID + - keySecretRef + properties: + keyAlgorithm: + description: |- + Deprecated: keyAlgorithm field exists for historical compatibility + reasons and should not be used. The algorithm is now hardcoded to HS256 + in golang/x/crypto/acme. + type: string + enum: + - HS256 + - HS384 + - HS512 + keyID: + description: keyID is the ID of the CA key that the External Account is bound to. + type: string + keySecretRef: + description: |- + keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes + Secret which holds the symmetric MAC key of the External Account Binding. + The `key` is the index string that is paired with the key data in the + Secret and should not be confused with the key data itself, or indeed with + the External Account Binding keyID above. + The secret key stored in the Secret **must** be un-padded, base64 URL + encoded data. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + preferredChain: + description: |- + PreferredChain is the chain to use if the ACME server outputs multiple. + PreferredChain is no guarantee that this one gets delivered by the ACME + endpoint. + For example, for Let's Encrypt's DST crosssign you would use: + "DST Root CA X3" or "ISRG Root X1" for the newer Let's Encrypt root CA. + This value picks the first certificate bundle in the combined set of + ACME default and alternative chains that has a root-most certificate with + this value as its issuer's commonname. + type: string + maxLength: 64 + privateKeySecretRef: + description: |- + PrivateKey is the name of a Kubernetes Secret resource that will be used to + store the automatically generated ACME account private key. + Optionally, a `key` may be specified to select a specific entry within + the named Secret resource. + If `key` is not specified, a default of `tls.key` will be used. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + server: + description: |- + Server is the URL used to access the ACME server's 'directory' endpoint. + For example, for Let's Encrypt's staging endpoint, you would use: + "https://acme-staging-v02.api.letsencrypt.org/directory". + Only ACME v2 endpoints (i.e. RFC 8555) are supported. + type: string + skipTLSVerify: + description: |- + INSECURE: Enables or disables validation of the ACME server TLS certificate. + If true, requests to the ACME server will not have the TLS certificate chain + validated. + Mutually exclusive with CABundle; prefer using CABundle to prevent various + kinds of security vulnerabilities. + Only enable this option in development environments. + If CABundle and SkipTLSVerify are unset, the system certificate bundle inside + the container is used to validate the TLS connection. + Defaults to false. + type: boolean + solvers: + description: |- + Solvers is a list of challenge solvers that will be used to solve + ACME challenges for the matching domains. + Solver configurations must be provided in order to obtain certificates + from an ACME server. + For more information, see: https://cert-manager.io/docs/configuration/acme/ + type: array + items: + description: |- + An ACMEChallengeSolver describes how to solve ACME challenges for the issuer it is part of. + A selector may be provided to use different solving strategies for different DNS names. + Only one of HTTP01 or DNS01 must be provided. + type: object + properties: + dns01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the DNS01 challenge flow. + type: object + properties: + acmeDNS: + description: |- + Use the 'ACME DNS' (https://github.com/joohoi/acme-dns) API to manage + DNS01 challenge records. + type: object + required: + - accountSecretRef + - host + properties: + accountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + host: + type: string + akamai: + description: Use the Akamai DNS zone management API to manage DNS01 challenge records. + type: object + required: + - accessTokenSecretRef + - clientSecretSecretRef + - clientTokenSecretRef + - serviceConsumerDomain + properties: + accessTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientSecretSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientTokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceConsumerDomain: + type: string + azureDNS: + description: Use the Microsoft Azure DNS API to manage DNS01 challenge records. + type: object + required: + - resourceGroupName + - subscriptionID + properties: + clientID: + description: |- + Auth: Azure Service Principal: + The ClientID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientSecret and TenantID must also be set. + type: string + clientSecretSecretRef: + description: |- + Auth: Azure Service Principal: + A reference to a Secret containing the password associated with the Service Principal. + If set, ClientID and TenantID must also be set. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + environment: + description: name of the Azure environment (default AzurePublicCloud) + type: string + enum: + - AzurePublicCloud + - AzureChinaCloud + - AzureGermanCloud + - AzureUSGovernmentCloud + hostedZoneName: + description: name of the DNS zone that should be used + type: string + managedIdentity: + description: |- + Auth: Azure Workload Identity or Azure Managed Service Identity: + Settings to enable Azure Workload Identity or Azure Managed Service Identity + If set, ClientID, ClientSecret and TenantID must not be set. + type: object + properties: + clientID: + description: client ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceID: + description: |- + resource ID of the managed identity, can not be used at the same time as clientID + Cannot be used for Azure Managed Service Identity + type: string + tenantID: + description: tenant ID of the managed identity, can not be used at the same time as resourceID + type: string + resourceGroupName: + description: resource group the DNS zone is located in + type: string + subscriptionID: + description: ID of the Azure subscription + type: string + tenantID: + description: |- + Auth: Azure Service Principal: + The TenantID of the Azure Service Principal used to authenticate with Azure DNS. + If set, ClientID and ClientSecret must also be set. + type: string + cloudDNS: + description: Use the Google Cloud DNS API to manage DNS01 challenge records. + type: object + required: + - project + properties: + hostedZoneName: + description: |- + HostedZoneName is an optional field that tells cert-manager in which + Cloud DNS zone the challenge record has to be created. + If left empty cert-manager will automatically choose a zone. + type: string + project: + type: string + serviceAccountSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + cloudflare: + description: Use the Cloudflare API to manage DNS01 challenge records. + type: object + properties: + apiKeySecretRef: + description: |- + API key to use to authenticate with Cloudflare. + Note: using an API token to authenticate is now the recommended method + as it allows greater control of permissions. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + apiTokenSecretRef: + description: API token used to authenticate with Cloudflare. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + email: + description: Email of the account, only required when using API key based authentication. + type: string + cnameStrategy: + description: |- + CNAMEStrategy configures how the DNS01 provider should handle CNAME + records when found in DNS zones. + type: string + enum: + - None + - Follow + digitalocean: + description: Use the DigitalOcean DNS API to manage DNS01 challenge records. + type: object + required: + - tokenSecretRef + properties: + tokenSecretRef: + description: |- + A reference to a specific 'key' within a Secret resource. + In some instances, `key` is a required field. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + rfc2136: + description: |- + Use RFC2136 ("Dynamic Updates in the Domain Name System") (https://datatracker.ietf.org/doc/rfc2136/) + to manage DNS01 challenge records. + type: object + required: + - nameserver + properties: + nameserver: + description: |- + The IP address or hostname of an authoritative DNS server supporting + RFC2136 in the form host:port. If the host is an IPv6 address it must be + enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + This field is required. + type: string + tsigAlgorithm: + description: |- + The TSIG Algorithm configured in the DNS supporting RFC2136. Used only + when ``tsigSecretSecretRef`` and ``tsigKeyName`` are defined. + Supported values are (case-insensitive): ``HMACMD5`` (default), + ``HMACSHA1``, ``HMACSHA256`` or ``HMACSHA512``. + type: string + tsigKeyName: + description: |- + The TSIG Key name configured in the DNS. + If ``tsigSecretSecretRef`` is defined, this field is required. + type: string + tsigSecretSecretRef: + description: |- + The name of the secret containing the TSIG value. + If ``tsigKeyName`` is defined, this field is required. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + route53: + description: Use the AWS Route53 API to manage DNS01 challenge records. + type: object + properties: + accessKeyID: + description: |- + The AccessKeyID is used for authentication. + Cannot be set when SecretAccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: string + accessKeyIDSecretRef: + description: |- + The SecretAccessKey is used for authentication. If set, pull the AWS + access key ID from a key within a Kubernetes Secret. + Cannot be set when AccessKeyID is set. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + auth: + description: Auth configures how cert-manager authenticates. + type: object + required: + - kubernetes + properties: + kubernetes: + description: |- + Kubernetes authenticates with Route53 using AssumeRoleWithWebIdentity + by passing a bound ServiceAccount token. + type: object + required: + - serviceAccountRef + properties: + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). To use this field, you must + configure an RBAC rule to let cert-manager request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of audiences to include in the + token passed to AWS. The default token consisting of the issuer's namespace + and name is always included. + If unset the audience defaults to `sts.amazonaws.com`. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + hostedZoneID: + description: If set, the provider will manage only this zone in Route53 and will not do a lookup using the route53:ListHostedZonesByName api call. + type: string + region: + description: |- + Override the AWS region. + + Route53 is a global service and does not have regional endpoints but the + region specified here (or via environment variables) is used as a hint to + help compute the correct AWS credential scope and partition when it + connects to Route53. See: + - [Amazon Route 53 endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/r53.html) + - [Global services](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html) + + If you omit this region field, cert-manager will use the region from + AWS_REGION and AWS_DEFAULT_REGION environment variables, if they are set + in the cert-manager controller Pod. + + The `region` field is not needed if you use [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Webhook](https://github.com/aws/amazon-eks-pod-identity-webhook). + In this case this `region` field value is ignored. + + The `region` field is not needed if you use [EKS Pod Identities](https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html). + Instead an AWS_REGION environment variable is added to the cert-manager controller Pod by: + [Amazon EKS Pod Identity Agent](https://github.com/aws/eks-pod-identity-agent), + In this case this `region` field value is ignored. + type: string + role: + description: |- + Role is a Role ARN which the Route53 provider will assume using either the explicit credentials AccessKeyID/SecretAccessKey + or the inferred credentials from environment variables, shared credentials file or AWS Instance metadata + type: string + secretAccessKeySecretRef: + description: |- + The SecretAccessKey is used for authentication. + If neither the Access Key nor Key ID are set, we fall-back to using env + vars, shared credentials file or AWS Instance metadata, + see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + webhook: + description: |- + Configure an external webhook based DNS01 challenge solver to manage + DNS01 challenge records. + type: object + required: + - groupName + - solverName + properties: + config: + description: |- + Additional configuration that should be passed to the webhook apiserver + when challenges are processed. + This can contain arbitrary JSON data. + Secret values should not be specified in this stanza. + If secret values are needed (e.g. credentials for a DNS service), you + should use a SecretKeySelector to reference a Secret resource. + For details on the schema of this field, consult the webhook provider + implementation's documentation. + x-kubernetes-preserve-unknown-fields: true + groupName: + description: |- + The API group name that should be used when POSTing ChallengePayload + resources to the webhook apiserver. + This should be the same as the GroupName specified in the webhook + provider implementation. + type: string + solverName: + description: |- + The name of the solver to use, as defined in the webhook provider + implementation. + This will typically be the name of the provider, e.g. 'cloudflare'. + type: string + http01: + description: |- + Configures cert-manager to attempt to complete authorizations by + performing the HTTP01 challenge flow. + It is not possible to obtain certificates for wildcard domain names + (e.g. `*.example.com`) using the HTTP01 challenge mechanism. + type: object + properties: + gatewayHTTPRoute: + description: |- + The Gateway API is a sig-network community API that models service networking + in Kubernetes (https://gateway-api.sigs.k8s.io/). The Gateway solver will + create HTTPRoutes with the specified labels in the same namespace as the challenge. + This solver is experimental, and fields / behaviour may change in the future. + type: object + properties: + labels: + description: |- + Custom labels that will be applied to HTTPRoutes created by cert-manager + while solving HTTP-01 challenges. + type: object + additionalProperties: + type: string + parentRefs: + description: |- + When solving an HTTP-01 challenge, cert-manager creates an HTTPRoute. + cert-manager needs to know which parentRefs should be used when creating + the HTTPRoute. Usually, the parentRef references a Gateway. See: + https://gateway-api.sigs.k8s.io/api-types/httproute/#attaching-to-gateways + type: array + items: + description: |- + ParentReference identifies an API object (usually a Gateway) that can be considered + a parent of this resource (usually a route). There are two kinds of parent resources + with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + This API may be extended in the future to support additional kinds of parent + resources. + + The API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid. + type: object + required: + - name + properties: + group: + description: |- + Group is the group of the referent. + When unspecified, "gateway.networking.k8s.io" is inferred. + To set the core API group (such as for a "Service" kind referent), + Group must be explicitly set to "" (empty string). + + Support: Core + type: string + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + kind: + description: |- + Kind is kind of the referent. + + There are two kinds of parent resources with "Core" support: + + * Gateway (Gateway conformance profile) + * Service (Mesh conformance profile, ClusterIP Services only) + + Support for other resources is Implementation-Specific. + type: string + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + name: + description: |- + Name is the name of the referent. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + namespace: + description: |- + Namespace is the namespace of the referent. When unspecified, this refers + to the local namespace of the Route. + + Note that there are specific rules for ParentRefs which cross namespace + boundaries. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For example: + Gateway has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + + + ParentRefs from a Route to a Service in the same namespace are "producer" + routes, which apply default routing rules to inbound connections from + any namespace to the Service. + + ParentRefs from a Route to a Service in a different namespace are + "consumer" routes, and these routing rules are only applied to outbound + connections originating from the same namespace as the Route, for which + the intended destination of the connections are a Service targeted as a + ParentRef of the Route. + + + Support: Core + type: string + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + port: + description: |- + Port is the network port this Route targets. It can be interpreted + differently based on the type of parent resource. + + When the parent resource is a Gateway, this targets all listeners + listening on the specified port that also support this kind of Route(and + select this Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to a specific port + as opposed to a listener(s) whose port(s) may be changed. When both Port + and SectionName are specified, the name and port of the selected listener + must match both specified values. + + + When the parent resource is a Service, this targets a specific port in the + Service spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified values. + + + Implementations MAY choose to support other parent resources. + Implementations supporting other types of parent resources MUST clearly + document how/if Port is interpreted. + + For the purpose of status, an attachment is considered successful as + long as the parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + + Support: Extended + type: integer + format: int32 + maximum: 65535 + minimum: 1 + sectionName: + description: |- + SectionName is the name of a section within the target resource. In the + following resources, SectionName is interpreted as the following: + + * Gateway: Listener name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + * Service: Port name. When both Port (experimental) and SectionName + are specified, the name and port of the selected listener must match + both specified values. + + Implementations MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName is + interpreted. + + When unspecified (empty string), this will reference the entire resource. + For the purpose of status, an attachment is considered successful if at + least one section in the parent resource accepts it. For example, Gateway + listeners can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this Route, the + Route MUST be considered detached from the Gateway. + + Support: Core + type: string + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + ingress: + description: |- + The ingress based HTTP01 challenge solver will solve challenges by + creating or modifying Ingress resources in order to route requests for + '/.well-known/acme-challenge/XYZ' to 'challenge solver' pods that are + provisioned by cert-manager for each Challenge to be completed. + type: object + properties: + class: + description: |- + This field configures the annotation `kubernetes.io/ingress.class` when + creating Ingress resources to solve ACME challenges that use this + challenge solver. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + ingressClassName: + description: |- + This field configures the field `ingressClassName` on the created Ingress + resources used to solve ACME challenges that use this challenge solver. + This is the recommended way of configuring the ingress class. Only one of + `class`, `name` or `ingressClassName` may be specified. + type: string + ingressTemplate: + description: |- + Optional ingress template used to configure the ACME challenge solver + ingress used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the ingress used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver ingress. + type: object + additionalProperties: + type: string + name: + description: |- + The name of the ingress resource that should have ACME challenge solving + routes inserted into it in order to solve HTTP01 challenges. + This is typically used in conjunction with ingress controllers like + ingress-gce, which maintains a 1:1 mapping between external IPs and + ingress resources. Only one of `class`, `name` or `ingressClassName` may + be specified. + type: string + podTemplate: + description: |- + Optional pod template used to configure the ACME challenge solver pods + used for HTTP01 challenges. + type: object + properties: + metadata: + description: |- + ObjectMeta overrides for the pod used to solve HTTP01 challenges. + Only the 'labels' and 'annotations' fields may be set. + If labels or annotations overlap with in-built values, the values here + will override the in-built values. + type: object + properties: + annotations: + description: Annotations that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + labels: + description: Labels that should be added to the created ACME HTTP01 solver pods. + type: object + additionalProperties: + type: string + spec: + description: |- + PodSpec defines overrides for the HTTP01 challenge solver pod. + Check ACMEChallengeSolverHTTP01IngressPodSpec to find out currently supported fields. + All other fields will be ignored. + type: object + properties: + affinity: + description: If specified, the pod's scheduling constraints + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + 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. + type: array + 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). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + 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. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + 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. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + x-kubernetes-list-type: atomic + x-kubernetes-map-type: atomic + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + 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)). + type: object + 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 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. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + type: integer + format: int32 + 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. + type: array + 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 + type: object + required: + - topologyKey + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). + type: array + items: + type: string + 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. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + 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. + type: array + items: + type: string + x-kubernetes-list-type: atomic + x-kubernetes-list-type: atomic + matchLabels: + 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 + additionalProperties: + type: string + 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". + type: array + items: + type: string + 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 + x-kubernetes-list-type: atomic + imagePullSecrets: + description: If specified, the pod's imagePullSecrets + type: array + items: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + type: object + properties: + name: + 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 + default: "" + x-kubernetes-map-type: atomic + nodeSelector: + description: |- + NodeSelector is a selector which must be true for the pod to fit on a node. + Selector which must match a node's labels for the pod to be scheduled on that node. + More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + type: object + additionalProperties: + type: string + priorityClassName: + description: If specified, the pod's priorityClassName. + type: string + securityContext: + description: If specified, the pod's security context + type: object + properties: + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + type: integer + format: int64 + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + type: object + required: + - type + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container process. If unspecified, + no additional groups are added to any container. Note that group memberships + defined in the container image for the uid of the container process are still effective, + even if they are not included in this list. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + type: integer + format: int64 + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + type: array + items: + description: Sysctl defines a kernel parameter to be set + type: object + required: + - name + - value + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + serviceAccountName: + description: If specified, the pod's service account + type: string + tolerations: + description: If specified, the pod's tolerations. + type: array + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + type: object + 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. + type: integer + format: int64 + 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 + serviceType: + description: |- + Optional service type for Kubernetes solver service. Supported values + are NodePort or ClusterIP. If unset, defaults to NodePort. + type: string + selector: + description: |- + Selector selects a set of DNSNames on the Certificate resource that + should be solved using this challenge solver. + If not specified, the solver will be treated as the 'default' solver + with the lowest priority, i.e. if any other solver has a more specific + match, it will be used instead. + type: object + properties: + dnsNames: + description: |- + List of DNSNames that this solver will be used to solve. + If specified and a match is found, a dnsNames selector will take + precedence over a dnsZones selector. + If multiple solvers match with the same dnsNames value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + dnsZones: + description: |- + List of DNSZones that this solver will be used to solve. + The most specific DNS zone match specified here will take precedence + over other DNS zone matches, so a solver specifying sys.example.com + will be selected over one specifying example.com for the domain + www.sys.example.com. + If multiple solvers match with the same dnsZones value, the solver + with the most matching labels in matchLabels will be selected. + If neither has more matches, the solver defined earlier in the list + will be selected. + type: array + items: + type: string + matchLabels: + description: |- + A label selector that is used to refine the set of certificate's that + this challenge solver will apply to. + type: object + additionalProperties: + type: string + ca: + description: |- + CA configures this issuer to sign certificates using a signing CA keypair + stored in a Secret resource. + This is used to build internal PKIs that are managed by cert-manager. + type: object + required: + - secretName + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set, certificates will be issued without distribution points set. + type: array + items: + type: string + issuingCertificateURLs: + description: |- + IssuingCertificateURLs is a list of URLs which this issuer should embed into certificates + it creates. See https://www.rfc-editor.org/rfc/rfc5280#section-4.2.2.1 for more details. + As an example, such a URL might be "http://ca.domain.com/ca.crt". + type: array + items: + type: string + ocspServers: + description: |- + The OCSP server list is an X.509 v3 extension that defines a list of + URLs of OCSP responders. The OCSP responders can be queried for the + revocation status of an issued certificate. If not set, the + certificate will be issued with no OCSP servers set. For example, an + OCSP server URL could be "http://ocsp.int-x3.letsencrypt.org". + type: array + items: + type: string + secretName: + description: |- + SecretName is the name of the secret used to sign Certificates issued + by this Issuer. + type: string + selfSigned: + description: |- + SelfSigned configures this issuer to 'self sign' certificates using the + private key used to create the CertificateRequest object. + type: object + properties: + crlDistributionPoints: + description: |- + The CRL distribution points is an X.509 v3 certificate extension which identifies + the location of the CRL from which the revocation of this certificate can be checked. + If not set certificate will be issued without CDP. Values are strings. + type: array + items: + type: string + vault: + description: |- + Vault configures this issuer to sign certificates using a HashiCorp Vault + PKI backend. + type: object + required: + - auth + - path + - server + properties: + auth: + description: Auth configures how cert-manager authenticates with the Vault server. + type: object + properties: + appRole: + description: |- + AppRole authenticates with Vault using the App Role auth mechanism, + with the role and secret stored in a Kubernetes Secret resource. + type: object + required: + - path + - roleId + - secretRef + properties: + path: + description: |- + Path where the App Role authentication backend is mounted in Vault, e.g: + "approle" + type: string + roleId: + description: |- + RoleID configured in the App Role authentication backend when setting + up the authentication backend in Vault. + type: string + secretRef: + description: |- + Reference to a key in a Secret that contains the App Role secret used + to authenticate with Vault. + The `key` field must be specified and denotes which entry within the Secret + resource is used as the app role secret. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertificate: + description: |- + ClientCertificate authenticates with Vault by presenting a client + certificate during the request's TLS handshake. + Works only when using HTTPS protocol. + type: object + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/cert" will be used. + type: string + name: + description: |- + Name of the certificate role to authenticate against. + If not set, matching any certificate role, if available. + type: string + secretName: + description: |- + Reference to Kubernetes Secret of type "kubernetes.io/tls" (hence containing + tls.crt and tls.key) used to authenticate to Vault using TLS client + authentication. + type: string + kubernetes: + description: |- + Kubernetes authenticates with Vault by passing the ServiceAccount + token stored in the named Secret resource to the Vault server. + type: object + required: + - role + properties: + mountPath: + description: |- + The Vault mountPath here is the mount path to use when authenticating with + Vault. For example, setting a value to `/v1/auth/foo`, will use the path + `/v1/auth/foo/login` to authenticate with Vault. If unspecified, the + default value "/v1/auth/kubernetes" will be used. + type: string + role: + description: |- + A required field containing the Vault Role to assume. A Role binds a + Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: |- + The required Secret field containing a Kubernetes ServiceAccount JWT used + for authenticating with Vault. Use of 'ambient credentials' is not + supported. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + serviceAccountRef: + description: |- + A reference to a service account that will be used to request a bound + token (also known as "projected token"). Compared to using "secretRef", + using this field means that you don't rely on statically bound tokens. To + use this field, you must configure an RBAC rule to let cert-manager + request a token. + type: object + required: + - name + properties: + audiences: + description: |- + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token + consisting of the issuer's namespace and name is always included. + type: array + items: + type: string + name: + description: Name of the ServiceAccount used to request a token. + type: string + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by Vault. Only used if using HTTPS to connect to Vault and + ignored for HTTP connections. + Mutually exclusive with CABundleSecretRef. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a bundle of PEM-encoded CAs to use when + verifying the certificate chain presented by Vault when using HTTPS. + Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef are defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + If no key for the Secret is specified, cert-manager will default to 'ca.crt'. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientCertSecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Certificate to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + clientKeySecretRef: + description: |- + Reference to a Secret containing a PEM-encoded Client Private Key to use when the + Vault server requires mTLS. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1" + More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces + type: string + path: + description: |- + Path is the mount path of the Vault PKI backend's `sign` endpoint, e.g: + "my_pki_mount/sign/my-role-name". + type: string + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + venafi: + description: |- + Venafi configures this issuer to sign certificates using a Venafi TPP + or Venafi Cloud policy zone. + type: object + required: + - zone + properties: + cloud: + description: |- + Cloud specifies the Venafi cloud configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - apiTokenSecretRef + properties: + apiTokenSecretRef: + description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for Venafi Cloud. + Defaults to "https://api.venafi.cloud/v1". + type: string + tpp: + description: |- + TPP specifies Trust Protection Platform configuration settings. + Only one of TPP or Cloud may be specified. + type: object + required: + - credentialsRef + - url + properties: + caBundle: + description: |- + Base64-encoded bundle of PEM CAs which will be used to validate the certificate + chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + If undefined, the certificate bundle in the cert-manager controller container + is used to validate the chain. + type: string + format: byte + caBundleSecretRef: + description: |- + Reference to a Secret containing a base64-encoded bundle of PEM CAs + which will be used to validate the certificate chain presented by the TPP server. + Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. + If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in + the cert-manager controller container is used to validate the TLS connection. + type: object + required: + - name + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. + Some instances of this field may be defaulted, in others it may be + required. + type: string + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + credentialsRef: + description: |- + CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + The secret must contain the key 'access-token' for the Access Token Authentication, + or two keys, 'username' and 'password' for the API Keys Authentication. + type: object + required: + - name + properties: + name: + description: |- + Name of the resource being referred to. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + url: + description: |- + URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + for example: "https://tpp.example.com/vedsdk". + type: string + zone: + description: |- + Zone is the Venafi Policy Zone to use for this issuer. + All requests made to the Venafi platform will be restricted by the named + zone policy. + This field is required. + type: string + status: + description: Status of the Issuer. This is set and managed automatically. + type: object + properties: + acme: + description: |- + ACME specific status options. + This field should only be set if the Issuer is configured to use an ACME + server to issue certificates. + type: object + properties: + lastPrivateKeyHash: + description: |- + LastPrivateKeyHash is a hash of the private key associated with the latest + registered ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + lastRegisteredEmail: + description: |- + LastRegisteredEmail is the email associated with the latest registered + ACME account, in order to track changes made to registered account + associated with the Issuer + type: string + uri: + description: |- + URI is the unique account identifier, which can also be used to retrieve + account details from the CA + type: string + conditions: + description: |- + List of status conditions to indicate the status of a CertificateRequest. + Known condition types are `Ready`. + type: array + items: + description: IssuerCondition contains condition information for an Issuer. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. + type: string + format: date-time + message: + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. + type: string + observedGeneration: + description: |- + If set, this represents the .metadata.generation that the condition was + set based upon. + For instance, if .metadata.generation is currently 12, but the + .status.condition[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the Issuer. + type: integer + format: int64 + reason: + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. + type: string + status: + description: Status of the condition, one of (`True`, `False`, `Unknown`). + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: Type of the condition, known values are (`Ready`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + served: true + storage: true + +# END crd {{- end }} + +--- +# START crd {{- if or .Values.crds.enabled .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: orders.acme.cert-manager.io + # START annotations {{- if .Values.crds.keep }} + annotations: + helm.sh/resource-policy: keep + # END annotations {{- end }} + labels: + app: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/name: '{{ template "cert-manager.name" . }}' + app.kubernetes.io/instance: '{{ .Release.Name }}' + app.kubernetes.io/component: "crds" + # Generated labels {{- include "labels" . | nindent 4 }} +spec: + group: acme.cert-manager.io + names: + kind: Order + listKind: OrderList + plural: orders + singular: order + categories: + - cert-manager + - cert-manager-acme + scope: Namespaced + versions: + - name: v1 + subresources: + status: {} + additionalPrinterColumns: + - jsonPath: .status.state + name: State + type: string + - jsonPath: .spec.issuerRef.name + name: Issuer + priority: 1 + type: string + - jsonPath: .status.reason + name: Reason + priority: 1 + type: string + - jsonPath: .metadata.creationTimestamp + description: CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + name: Age + type: date + schema: + openAPIV3Schema: + description: Order is a type to represent an Order with an ACME server + type: object + required: + - metadata + - spec + 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: + type: object + required: + - issuerRef + - request + properties: + commonName: + description: |- + CommonName is the common name as specified on the DER encoded CSR. + If specified, this value must also be present in `dnsNames` or `ipAddresses`. + This field must match the corresponding field on the DER encoded CSR. + type: string + dnsNames: + description: |- + DNSNames is a list of DNS names that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + duration: + description: |- + Duration is the duration for the not after date for the requested certificate. + this is set on order creation as pe the ACME spec. + type: string + ipAddresses: + description: |- + IPAddresses is a list of IP addresses that should be included as part of the Order + validation process. + This field must match the corresponding field on the DER encoded CSR. + type: array + items: + type: string + issuerRef: + description: |- + IssuerRef references a properly configured ACME-type Issuer which should + be used to create this Order. + If the Issuer does not exist, processing will be retried. + If the Issuer is not an 'ACME' Issuer, an error will be returned and the + Order will be marked as failed. + type: object + required: + - name + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + request: + description: |- + Certificate signing request bytes in DER encoding. + This will be used when finalizing the order. + This field must be set on the order. + type: string + format: byte + status: + type: object + properties: + authorizations: + description: |- + Authorizations contains data returned from the ACME server on what + authorizations must be completed in order to validate the DNS names + specified on the Order. + type: array + items: + description: |- + ACMEAuthorization contains data returned from the ACME server on an + authorization that must be completed in order validate a DNS name on an ACME + Order resource. + type: object + required: + - url + properties: + challenges: + description: |- + Challenges specifies the challenge types offered by the ACME server. + One of these challenge types will be selected when validating the DNS + name and an appropriate Challenge resource will be created to perform + the ACME challenge process. + type: array + items: + description: |- + Challenge specifies a challenge offered by the ACME server for an Order. + An appropriate Challenge resource can be created to perform the ACME + challenge process. + type: object + required: + - token + - type + - url + properties: + token: + description: |- + Token is the token that must be presented for this challenge. + This is used to compute the 'key' that must also be presented. + type: string + type: + description: |- + Type is the type of challenge being offered, e.g. 'http-01', 'dns-01', + 'tls-sni-01', etc. + This is the raw value retrieved from the ACME server. + Only 'http-01' and 'dns-01' are supported by cert-manager, other values + will be ignored. + type: string + url: + description: |- + URL is the URL of this challenge. It can be used to retrieve additional + metadata about the Challenge from the ACME server. + type: string + identifier: + description: Identifier is the DNS name to be validated as part of this authorization + type: string + initialState: + description: |- + InitialState is the initial state of the ACME authorization when first + fetched from the ACME server. + If an Authorization is already 'valid', the Order controller will not + create a Challenge resource for the authorization. This will occur when + working with an ACME server that enables 'authz reuse' (such as Let's + Encrypt's production endpoint). + If not set and 'identifier' is set, the state is assumed to be pending + and a Challenge will be created. + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: URL is the URL of the Authorization that must be completed + type: string + wildcard: + description: |- + Wildcard will be true if this authorization is for a wildcard DNS name. + If this is true, the identifier will be the *non-wildcard* version of + the DNS name. + For example, if '*.example.com' is the DNS name being validated, this + field will be 'true' and the 'identifier' field will be 'example.com'. + type: boolean + certificate: + description: |- + Certificate is a copy of the PEM encoded certificate for this Order. + This field will be populated after the order has been successfully + finalized with the ACME server, and the order has transitioned to the + 'valid' state. + type: string + format: byte + failureTime: + description: |- + FailureTime stores the time that this order failed. + This is used to influence garbage collection and back-off. + type: string + format: date-time + finalizeURL: + description: |- + FinalizeURL of the Order. + This is used to obtain certificates for this order once it has been completed. + type: string + reason: + description: |- + Reason optionally provides more information about a why the order is in + the current state. + type: string + state: + description: |- + State contains the current state of this Order resource. + States 'success' and 'expired' are 'final' + type: string + enum: + - valid + - ready + - pending + - processing + - invalid + - expired + - errored + url: + description: |- + URL of the Order. + This will initially be empty when the resource is first created. + The Order controller will populate this field when the Order is first processed. + This field will be immutable after it is initially set. + type: string + served: true + storage: true + +# END crd {{- end }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml index 453e8238..8a4a9734 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/deployment.yaml @@ -66,9 +66,6 @@ spec: {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} - {{- if (hasKey .Values.global "hostUsers") }} - hostUsers: {{ .Values.global.hostUsers }} - {{- end }} {{- with .Values.securityContext }} securityContext: {{- toYaml . | nindent 8 }} @@ -212,13 +209,9 @@ spec: failureThreshold: {{ .failureThreshold }} {{- end }} {{- end }} - {{- $nodeSelector := .Values.global.nodeSelector | default dict }} - {{- $nodeSelector = merge $nodeSelector (.Values.nodeSelector | default dict) }} - {{- with $nodeSelector }} + {{- with .Values.nodeSelector }} nodeSelector: - {{- range $key, $value := . }} - {{ $key }}: {{ $value | quote }} - {{- end }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.affinity }} affinity: @@ -241,4 +234,4 @@ spec: {{- end }} {{- with .Values.hostAliases }} hostAliases: {{ toYaml . | nindent 8 }} - {{- end }} + {{- end }} \ No newline at end of file diff --git a/packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml b/packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml index 7acd5711..baae425f 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/rbac.yaml @@ -49,7 +49,7 @@ subjects: apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: {{ template "cert-manager.fullname" . }}-tokenrequest + name: {{ template "cert-manager.serviceAccountName" . }}-tokenrequest namespace: {{ include "cert-manager.namespace" . }} labels: app: {{ include "cert-manager.name" . }} @@ -69,7 +69,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ include "cert-manager.fullname" . }}-tokenrequest + name: {{ include "cert-manager.fullname" . }}-{{ template "cert-manager.serviceAccountName" . }}-tokenrequest namespace: {{ include "cert-manager.namespace" . }} labels: app: {{ include "cert-manager.name" . }} @@ -80,7 +80,7 @@ metadata: roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: {{ template "cert-manager.fullname" . }}-tokenrequest + name: {{ template "cert-manager.serviceAccountName" . }}-tokenrequest subjects: - kind: ServiceAccount name: {{ template "cert-manager.serviceAccountName" . }} @@ -256,8 +256,8 @@ rules: - apiGroups: ["networking.k8s.io"] resources: ["ingresses"] verbs: ["get", "list", "watch", "create", "delete", "update"] - - apiGroups: ["gateway.networking.k8s.io"] - resources: ["httproutes"] + - apiGroups: [ "gateway.networking.k8s.io" ] + resources: [ "httproutes" ] verbs: ["get", "list", "watch", "create", "delete", "update"] # We require the ability to specify a custom hostname when we are creating # new ingress resources. diff --git a/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml b/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml index fac93d0a..698ddef8 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/serviceaccount.yaml @@ -12,8 +12,7 @@ metadata: {{- with .Values.serviceAccount.annotations }} annotations: {{- range $k, $v := . }} - {{- $value := $v | quote }} - {{- printf "%s: %s" (tpl $k $) (tpl $value $) | nindent 4 }} + {{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }} {{- end }} {{- end }} labels: diff --git a/packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml b/packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml index a29f3c6a..dd1beec8 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/servicemonitor.yaml @@ -16,9 +16,7 @@ metadata: app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/component: "controller" {{- include "labels" . | nindent 4 }} - {{- if .Values.prometheus.servicemonitor.prometheusInstance }} prometheus: {{ .Values.prometheus.servicemonitor.prometheusInstance }} - {{- end }} {{- with .Values.prometheus.servicemonitor.labels }} {{- toYaml . | nindent 4 }} {{- end }} @@ -56,12 +54,8 @@ spec: endpoints: - targetPort: {{ .Values.prometheus.servicemonitor.targetPort }} path: {{ .Values.prometheus.servicemonitor.path }} - {{- if .Values.prometheus.servicemonitor.interval }} interval: {{ .Values.prometheus.servicemonitor.interval }} - {{- end }} - {{- if .Values.prometheus.servicemonitor.scrapeTimeout }} scrapeTimeout: {{ .Values.prometheus.servicemonitor.scrapeTimeout }} - {{- end }} honorLabels: {{ .Values.prometheus.servicemonitor.honorLabels }} {{- with .Values.prometheus.servicemonitor.endpointAdditionalProperties }} {{- toYaml . | nindent 4 }} diff --git a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml index f68d5409..183cff4e 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/startupapicheck-job.yaml @@ -41,9 +41,6 @@ spec: {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} - {{- if (hasKey .Values.global "hostUsers") }} - hostUsers: {{ .Values.global.hostUsers }} - {{- end }} {{- with .Values.startupapicheck.securityContext }} securityContext: {{- toYaml . | nindent 8 }} @@ -79,13 +76,9 @@ spec: volumeMounts: {{- toYaml . | nindent 12 }} {{- end }} - {{- $nodeSelector := .Values.global.nodeSelector | default dict }} - {{- $nodeSelector = merge $nodeSelector (.Values.startupapicheck.nodeSelector | default dict) }} - {{- with $nodeSelector }} + {{- with .Values.startupapicheck.nodeSelector }} nodeSelector: - {{- range $key, $value := . }} - {{ $key }}: {{ $value | quote }} - {{- end }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.startupapicheck.affinity }} affinity: diff --git a/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml b/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml index d2b10ae8..857cf353 100644 --- a/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml +++ b/packages/system/cert-manager/charts/cert-manager/templates/webhook-deployment.yaml @@ -66,9 +66,6 @@ spec: {{- with .Values.global.priorityClassName }} priorityClassName: {{ . | quote }} {{- end }} - {{- if (hasKey .Values.global "hostUsers") }} - hostUsers: {{ .Values.global.hostUsers }} - {{- end }} {{- with .Values.webhook.securityContext }} securityContext: {{- toYaml . | nindent 8 }} @@ -105,7 +102,7 @@ spec: - --dynamic-serving-dns-names={{ template "webhook.fullname" . }} - --dynamic-serving-dns-names={{ template "webhook.fullname" . }}.$(POD_NAMESPACE) - --dynamic-serving-dns-names={{ template "webhook.fullname" . }}.$(POD_NAMESPACE).svc - {{- if .Values.webhook.url.host }} + {{ if .Values.webhook.url.host }} - --dynamic-serving-dns-names={{ .Values.webhook.url.host }} {{- end }} {{- end }} @@ -140,7 +137,11 @@ spec: livenessProbe: httpGet: path: /livez - port: healthcheck + {{- if $config.healthzPort }} + port: {{ $config.healthzPort }} + {{- else }} + port: 6080 + {{- end }} scheme: HTTP initialDelaySeconds: {{ .Values.webhook.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.webhook.livenessProbe.periodSeconds }} @@ -150,7 +151,11 @@ spec: readinessProbe: httpGet: path: /healthz - port: healthcheck + {{- if $config.healthzPort }} + port: {{ $config.healthzPort }} + {{- else }} + port: 6080 + {{- end }} scheme: HTTP initialDelaySeconds: {{ .Values.webhook.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.webhook.readinessProbe.periodSeconds }} @@ -183,13 +188,9 @@ spec: {{- toYaml . | nindent 12 }} {{- end }} {{- end }} - {{- $nodeSelector := .Values.global.nodeSelector | default dict }} - {{- $nodeSelector = merge $nodeSelector (.Values.webhook.nodeSelector | default dict) }} - {{- with $nodeSelector }} + {{- with .Values.webhook.nodeSelector }} nodeSelector: - {{- range $key, $value := . }} - {{ $key }}: {{ $value | quote }} - {{- end }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.webhook.affinity }} affinity: diff --git a/packages/system/cert-manager/charts/cert-manager/values.schema.json b/packages/system/cert-manager/charts/cert-manager/values.schema.json index 7f90b6c3..36d1d0ca 100644 --- a/packages/system/cert-manager/charts/cert-manager/values.schema.json +++ b/packages/system/cert-manager/charts/cert-manager/values.schema.json @@ -236,7 +236,7 @@ "issuers.cert-manager.io/*", "clusterissuers.cert-manager.io/*" ], - "description": "List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because, e.g., you are using approver-policy, you can enable 'disableAutoApproval'.\nref: https://cert-manager.io/docs/concepts/certificaterequest/#approval", + "description": "List of signer names that cert-manager will approve by default. CertificateRequests referencing these signer names will be auto-approved by cert-manager. Defaults to just approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, because eg. you are using approver-policy, you can enable 'disableAutoApproval'.\nref: https://cert-manager.io/docs/concepts/certificaterequest/#approval", "items": {}, "type": "array" }, @@ -461,10 +461,10 @@ "type": "boolean" }, "helm-values.cainjector.podDisruptionBudget.maxUnavailable": { - "description": "`maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to\nan integer (e.g., 1) or a percentage value (e.g., 25%).\nCannot be used if `minAvailable` is set." + "description": "`maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to\nan integer (e.g. 1) or a percentage value (e.g. 25%).\nCannot be used if `minAvailable` is set." }, "helm-values.cainjector.podDisruptionBudget.minAvailable": { - "description": "`minAvailable` configures the minimum available pods for disruptions. It can either be set to\nan integer (e.g., 1) or a percentage value (e.g., 25%).\nCannot be used if `maxUnavailable` is set." + "description": "`minAvailable` configures the minimum available pods for disruptions. It can either be set to\nan integer (e.g. 1) or a percentage value (e.g. 25%).\nCannot be used if `maxUnavailable` is set." }, "helm-values.cainjector.podLabels": { "default": {}, @@ -579,7 +579,7 @@ }, "helm-values.config": { "default": {}, - "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n enableGatewayAPI: true\n # Feature gates as of v1.18.1. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AdditionalCertificateOutputFormats: true # GA - default=true\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: false # ALPHA - default=false\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n UseDomainQualifiedFinalizer: true # GA - default=true\n ValidateCAA: false # ALPHA - default=false\n DefaultPrivateKeyRotationPolicyAlways: true # BETA - default=true\n ACMEHTTP01IngressPathTypeExact: true # BETA - default=true\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", + "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n enableGatewayAPI: true\n # Feature gates as of v1.17.0. Listed with their default values.\n # See https://cert-manager.io/docs/cli/controller/\n featureGates:\n AdditionalCertificateOutputFormats: true # BETA - default=true\n AllAlpha: false # ALPHA - default=false\n AllBeta: false # BETA - default=false\n ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false\n ExperimentalGatewayAPISupport: true # BETA - default=true\n LiteralCertificateSubject: true # BETA - default=true\n NameConstraints: true # BETA - default=true\n OtherNames: false # ALPHA - default=false\n SecretsFilteredCaching: true # BETA - default=true\n ServerSideApply: false # ALPHA - default=false\n StableCertificateRequestName: true # BETA - default=true\n UseCertificateRequestBasicConstraints: false # ALPHA - default=false\n UseDomainQualifiedFinalizer: true # BETA - default=false\n ValidateCAA: false # ALPHA - default=false\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics", "type": "object" }, "helm-values.containerSecurityContext": { @@ -689,9 +689,6 @@ "commonLabels": { "$ref": "#/$defs/helm-values.global.commonLabels" }, - "hostUsers": { - "$ref": "#/$defs/helm-values.global.hostUsers" - }, "imagePullSecrets": { "$ref": "#/$defs/helm-values.global.imagePullSecrets" }, @@ -701,9 +698,6 @@ "logLevel": { "$ref": "#/$defs/helm-values.global.logLevel" }, - "nodeSelector": { - "$ref": "#/$defs/helm-values.global.nodeSelector" - }, "podSecurityPolicy": { "$ref": "#/$defs/helm-values.global.podSecurityPolicy" }, @@ -724,10 +718,6 @@ "description": "Labels to apply to all resources.\nPlease note that this does not add labels to the resources created dynamically by the controllers. For these resources, you have to add the labels in the template in the cert-manager custom resource: For example, podTemplate/ ingressTemplate in ACMEChallengeSolverHTTP01Ingress. For more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#acme.cert-manager.io/v1.ACMEChallengeSolverHTTP01Ingress).\nFor example, secretTemplate in CertificateSpec\nFor more information, see the [cert-manager documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.CertificateSpec).", "type": "object" }, - "helm-values.global.hostUsers": { - "description": "Set all pods to run in a user namespace without host access. Experimental: may be removed once the Kubernetes User Namespaces feature is GA.\n\nRequirements:\n - Kubernetes ≥ 1.33, or\n - Kubernetes 1.27–1.32 with UserNamespacesSupport feature gate enabled.\n\nSet to false to run pods in a user namespace without host access.\n\nSee [limitations](https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/#limitations) for details.", - "type": "boolean" - }, "helm-values.global.imagePullSecrets": { "default": [], "description": "Reference to one or more secrets to be used when pulling images. For more information, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/).\n\nFor example:\nimagePullSecrets:\n - name: \"image-pull-secret\"", @@ -773,11 +763,6 @@ "description": "Set the verbosity of cert-manager. A range of 0 - 6, with 6 being the most verbose.", "type": "number" }, - "helm-values.global.nodeSelector": { - "default": {}, - "description": "Global node selector\n\nThe nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with matching labels. For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).\n\nIf a component-specific nodeSelector is also set, it will be merged and take precedence.", - "type": "object" - }, "helm-values.global.podSecurityPolicy": { "properties": { "enabled": { @@ -936,7 +921,7 @@ "type": "number" }, "helm-values.nameOverride": { - "description": "Override the \"cert-manager.name\" value, which is used to annotate some of the resources that are created by this Chart (using \"app.kubernetes.io/name\"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use, e.g., \"cainjector.name\" which resolves to the value \"cainjector\").", + "description": "Override the \"cert-manager.name\" value, which is used to annotate some of the resources that are created by this Chart (using \"app.kubernetes.io/name\"). NOTE: There are some inconsistencies in the Helm chart when it comes to these annotations (some resources use eg. \"cainjector.name\" which resolves to the value \"cainjector\").", "type": "string" }, "helm-values.namespace": { @@ -980,10 +965,10 @@ "type": "boolean" }, "helm-values.podDisruptionBudget.maxUnavailable": { - "description": "This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%). it cannot be used if `minAvailable` is set." + "description": "This configures the maximum unavailable pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%). it cannot be used if `minAvailable` is set." }, "helm-values.podDisruptionBudget.minAvailable": { - "description": "This configures the minimum available pods for disruptions. It can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%).\nIt cannot be used if `maxUnavailable` is set." + "description": "This configures the minimum available pods for disruptions. It can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `maxUnavailable` is set." }, "helm-values.podDnsConfig": { "description": "Pod DNS configuration. The podDnsConfig field is optional and can work with any podDnsPolicy settings. However, when a Pod's dnsPolicy is set to \"None\", the dnsConfig field has to be specified. For more information, see [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config).", @@ -1015,7 +1000,7 @@ }, "helm-values.prometheus.enabled": { "default": true, - "description": "Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a\nServiceMonitor resource.\nOtherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you cannot enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error.", + "description": "Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a\nServiceMonitor resource.\nOtherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error.", "type": "boolean" }, "helm-values.prometheus.podmonitor": { @@ -1192,8 +1177,9 @@ "type": "string" }, "helm-values.prometheus.servicemonitor.targetPort": { - "default": "http-metrics", - "description": "The target port to set on the ServiceMonitor. This must match the port that the cert-manager controller is listening on for metrics." + "default": 9402, + "description": "The target port to set on the ServiceMonitor. This must match the port that the cert-manager controller is listening on for metrics.", + "type": "number" }, "helm-values.replicaCount": { "default": 1, @@ -1901,11 +1887,6 @@ "ipBlock": { "cidr": "0.0.0.0/0" } - }, - { - "ipBlock": { - "cidr": "::/0" - } } ] } @@ -1927,11 +1908,6 @@ "ipBlock": { "cidr": "0.0.0.0/0" } - }, - { - "ipBlock": { - "cidr": "::/0" - } } ] } @@ -1972,10 +1948,10 @@ "type": "boolean" }, "helm-values.webhook.podDisruptionBudget.maxUnavailable": { - "description": "This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%).\nIt cannot be used if `minAvailable` is set." + "description": "This property configures the maximum unavailable pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `minAvailable` is set." }, "helm-values.webhook.podDisruptionBudget.minAvailable": { - "description": "This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g., 1) or a percentage value (e.g., 25%).\nIt cannot be used if `maxUnavailable` is set." + "description": "This property configures the minimum available pods for disruptions. Can either be set to an integer (e.g. 1) or a percentage value (e.g. 25%).\nIt cannot be used if `maxUnavailable` is set." }, "helm-values.webhook.podLabels": { "default": {}, diff --git a/packages/system/cert-manager/charts/cert-manager/values.yaml b/packages/system/cert-manager/charts/cert-manager/values.yaml index 54257c79..a8c94f8b 100644 --- a/packages/system/cert-manager/charts/cert-manager/values.yaml +++ b/packages/system/cert-manager/charts/cert-manager/values.yaml @@ -12,16 +12,6 @@ global: # - name: "image-pull-secret" imagePullSecrets: [] - # Global node selector - # - # The nodeSelector on Pods tells Kubernetes to schedule Pods on the nodes with - # matching labels. - # For more information, see [Assigning Pods to Nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). - # - # If a component-specific nodeSelector is also set, it will be merged and take precedence. - # +docs:property - nodeSelector: {} - # Labels to apply to all resources. # Please note that this does not add labels to the resources created dynamically by the controllers. # For these resources, you have to add the labels in the template in the cert-manager custom resource: @@ -38,19 +28,6 @@ global: # The optional priority class to be used for the cert-manager pods. priorityClassName: "" - # Set all pods to run in a user namespace without host access. - # Experimental: may be removed once the Kubernetes User Namespaces feature is GA. - # - # Requirements: - # - Kubernetes ≥ 1.33, or - # - Kubernetes 1.27–1.32 with UserNamespacesSupport feature gate enabled. - # - # Set to false to run pods in a user namespace without host access. - # - # See [limitations](https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/#limitations) for details. - # +docs:property - # hostUsers: false - rbac: # Create required ClusterRoles and ClusterRoleBindings for cert-manager. create: true @@ -140,14 +117,14 @@ podDisruptionBudget: enabled: false # This configures the minimum available pods for disruptions. It can either be set to - # an integer (e.g., 1) or a percentage value (e.g., 25%). + # an integer (e.g. 1) or a percentage value (e.g. 25%). # It cannot be used if `maxUnavailable` is set. # +docs:property # +docs:type=unknown # minAvailable: 1 # This configures the maximum unavailable pods for disruptions. It can either be set to - # an integer (e.g., 1) or a percentage value (e.g., 25%). + # an integer (e.g. 1) or a percentage value (e.g. 25%). # it cannot be used if `minAvailable` is set. # +docs:property # +docs:type=unknown @@ -199,7 +176,7 @@ namespace: "" # Override the "cert-manager.name" value, which is used to annotate some of # the resources that are created by this Chart (using "app.kubernetes.io/name"). # NOTE: There are some inconsistencies in the Helm chart when it comes to -# these annotations (some resources use, e.g., "cainjector.name" which resolves +# these annotations (some resources use eg. "cainjector.name" which resolves # to the value "cainjector"). # +docs:property # nameOverride: "my-cert-manager" @@ -254,10 +231,10 @@ enableCertificateOwnerRef: false # kubernetesAPIBurst: 9000 # numberOfConcurrentWorkers: 200 # enableGatewayAPI: true -# # Feature gates as of v1.18.1. Listed with their default values. +# # Feature gates as of v1.17.0. Listed with their default values. # # See https://cert-manager.io/docs/cli/controller/ # featureGates: -# AdditionalCertificateOutputFormats: true # GA - default=true +# AdditionalCertificateOutputFormats: true # BETA - default=true # AllAlpha: false # ALPHA - default=false # AllBeta: false # BETA - default=false # ExperimentalCertificateSigningRequestControllers: false # ALPHA - default=false @@ -269,10 +246,8 @@ enableCertificateOwnerRef: false # ServerSideApply: false # ALPHA - default=false # StableCertificateRequestName: true # BETA - default=true # UseCertificateRequestBasicConstraints: false # ALPHA - default=false -# UseDomainQualifiedFinalizer: true # GA - default=true +# UseDomainQualifiedFinalizer: true # BETA - default=false # ValidateCAA: false # ALPHA - default=false -# DefaultPrivateKeyRotationPolicyAlways: true # BETA - default=true -# ACMEHTTP01IngressPathTypeExact: true # BETA - default=true # # Configure the metrics server for TLS # # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls # metricsTLSConfig: @@ -303,7 +278,7 @@ disableAutoApproval: false # referencing these signer names will be auto-approved by cert-manager. Defaults to just # approving the cert-manager.io Issuer and ClusterIssuer issuers. When set to an empty # array, ALL issuers will be auto-approved by cert-manager. To disable the auto-approval, -# because, e.g., you are using approver-policy, you can enable 'disableAutoApproval'. +# because eg. you are using approver-policy, you can enable 'disableAutoApproval'. # ref: https://cert-manager.io/docs/concepts/certificaterequest/#approval # +docs:property approveSignerNames: @@ -459,6 +434,7 @@ ingressShim: {} # +docs:property # no_proxy: 127.0.0.1,localhost + # A Kubernetes Affinity, if required. For more information, see [Affinity v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core). # # For example: @@ -526,7 +502,7 @@ prometheus: # ServiceMonitor resource. # Otherwise, 'prometheus.io' annotations are added to the cert-manager and # cert-manager-webhook Deployments. - # Note that you cannot enable both PodMonitor and ServiceMonitor as they are + # Note that you can not enable both PodMonitor and ServiceMonitor as they are # mutually exclusive. Enabling both will result in an error. enabled: true @@ -546,8 +522,7 @@ prometheus: # The target port to set on the ServiceMonitor. This must match the port that the # cert-manager controller is listening on for metrics. - # +docs:type=string,integer - targetPort: http-metrics + targetPort: 9402 # The path to scrape for metrics. path: /metrics @@ -581,7 +556,7 @@ prometheus: # +docs:property endpointAdditionalProperties: {} - # Note that you cannot enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. + # Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in an error. podmonitor: # Create a PodMonitor to add cert-manager to Prometheus. enabled: false @@ -731,14 +706,14 @@ webhook: enabled: false # This property configures the minimum available pods for disruptions. Can either be set to - # an integer (e.g., 1) or a percentage value (e.g., 25%). + # an integer (e.g. 1) or a percentage value (e.g. 25%). # It cannot be used if `maxUnavailable` is set. # +docs:property # +docs:type=unknown # minAvailable: 1 # This property configures the maximum unavailable pods for disruptions. Can either be set to - # an integer (e.g., 1) or a percentage value (e.g., 25%). + # an integer (e.g. 1) or a percentage value (e.g. 25%). # It cannot be used if `minAvailable` is set. # +docs:property # +docs:type=unknown @@ -984,8 +959,6 @@ webhook: - from: - ipBlock: cidr: 0.0.0.0/0 - - ipBlock: - cidr: "::/0" # Egress rule for the webhook network policy. By default, it allows all # outbound traffic to ports 80 and 443, as well as DNS ports. @@ -1007,8 +980,6 @@ webhook: to: - ipBlock: cidr: 0.0.0.0/0 - - ipBlock: - cidr: "::/0" # Additional volumes to add to the cert-manager controller pod. volumes: [] @@ -1102,14 +1073,14 @@ cainjector: enabled: false # `minAvailable` configures the minimum available pods for disruptions. It can either be set to - # an integer (e.g., 1) or a percentage value (e.g., 25%). + # an integer (e.g. 1) or a percentage value (e.g. 25%). # Cannot be used if `maxUnavailable` is set. # +docs:property # +docs:type=unknown # minAvailable: 1 # `maxUnavailable` configures the maximum unavailable pods for disruptions. It can either be set to - # an integer (e.g., 1) or a percentage value (e.g., 25%). + # an integer (e.g. 1) or a percentage value (e.g. 25%). # Cannot be used if `minAvailable` is set. # +docs:property # +docs:type=unknown diff --git a/packages/system/cert-manager/values.yaml b/packages/system/cert-manager/values.yaml index e69de29b..5accf95f 100644 --- a/packages/system/cert-manager/values.yaml +++ b/packages/system/cert-manager/values.yaml @@ -0,0 +1,2 @@ +cert-manager: + installCRDs: false diff --git a/packages/system/cilium/Makefile b/packages/system/cilium/Makefile index 71b47a77..267c75cc 100644 --- a/packages/system/cilium/Makefile +++ b/packages/system/cilium/Makefile @@ -10,17 +10,8 @@ update: rm -rf charts helm repo add cilium https://helm.cilium.io/ helm repo update cilium - helm pull cilium/cilium --untar --untardir charts --version 1.19 + helm pull cilium/cilium --untar --untardir charts --version 1.18 $(SED_INPLACE) -e '/Used in iptables/d' -e '/SYS_MODULE/d' charts/cilium/values.yaml - # Drop the whole k8s<1.30 AppArmor annotations block from the cilium-agent - # DaemonSet. Cozystack manages these annotations through cilium.podAnnotations - # in values.yaml on every k8s version, so keeping the upstream block would - # produce duplicate mapping keys on k8s<1.30. - perl -i -0pe 's|\n \{\{- if not \.Values\.securityContext\.privileged \}\}\n \{\{- if semverCompare "<1\.30\.0".*?\n \{\{- end \}\}\n \{\{- end \}\}\n \{\{- end \}\}||s' \ - charts/cilium/templates/cilium-agent/daemonset.yaml - @! grep -q 'container\.apparmor\.security\.beta\.kubernetes\.io' \ - charts/cilium/templates/cilium-agent/daemonset.yaml || \ - { echo 'ERROR: perl patch did not remove the upstream AppArmor block from cilium-agent/daemonset.yaml (upstream template format may have changed)' >&2; exit 1; } version=$$(awk '$$1 == "version:" {print $$2}' charts/cilium/Chart.yaml) && \ $(SED_INPLACE) "s/ARG VERSION=.*/ARG VERSION=v$${version}/" images/cilium/Dockerfile diff --git a/packages/system/cilium/charts/cilium/Chart.yaml b/packages/system/cilium/charts/cilium/Chart.yaml index 5fe2baed..0de0d9c7 100644 --- a/packages/system/cilium/charts/cilium/Chart.yaml +++ b/packages/system/cilium/charts/cilium/Chart.yaml @@ -41,8 +41,11 @@ annotations: namespace context.\n- kind: CiliumNodeConfig\n version: v2\n name: ciliumnodeconfigs.cilium.io\n \ displayName: Cilium Node Configuration\n description: |\n CiliumNodeConfig is a list of configuration key-value pairs. It is applied to\n nodes indicated - by a label selector.\n- kind: CiliumBGPClusterConfig\n version: v2alpha1\n name: - ciliumbgpclusterconfigs.cilium.io\n displayName: Cilium BGP Cluster Config\n + by a label selector.\n- kind: CiliumBGPPeeringPolicy\n version: v2alpha1\n name: + ciliumbgppeeringpolicies.cilium.io\n displayName: Cilium BGP Peering Policy\n + \ description: |\n Cilium BGP Peering Policy instructs Cilium to create specific + BGP peering\n configurations.\n- kind: CiliumBGPClusterConfig\n version: v2alpha1\n + \ name: ciliumbgpclusterconfigs.cilium.io\n displayName: Cilium BGP Cluster Config\n \ description: |\n Cilium BGP Cluster Config instructs Cilium operator to create specific BGP cluster\n configurations.\n- kind: CiliumBGPPeerConfig\n version: v2alpha1\n name: ciliumbgppeerconfigs.cilium.io\n displayName: Cilium BGP Peer @@ -76,7 +79,7 @@ annotations: Cilium Gateway Class Config\n description: |\n CiliumGatewayClassConfig defines a configuration for Gateway API GatewayClass.\n" apiVersion: v2 -appVersion: 1.19.3 +appVersion: 1.18.6 description: eBPF-based Networking, Security, and Observability home: https://cilium.io/ icon: https://cdn.jsdelivr.net/gh/cilium/cilium@main/Documentation/images/logo-solo.svg @@ -92,4 +95,4 @@ kubeVersion: '>= 1.21.0-0' name: cilium sources: - https://github.com/cilium/cilium -version: 1.19.3 +version: 1.18.6 diff --git a/packages/system/cilium/charts/cilium/README.md b/packages/system/cilium/charts/cilium/README.md index d7697c56..840d0126 100644 --- a/packages/system/cilium/charts/cilium/README.md +++ b/packages/system/cilium/charts/cilium/README.md @@ -1,6 +1,6 @@ # cilium -![Version: 1.19.3](https://img.shields.io/badge/Version-1.19.3-informational?style=flat-square) ![AppVersion: 1.19.3](https://img.shields.io/badge/AppVersion-1.19.3-informational?style=flat-square) +![Version: 1.18.6](https://img.shields.io/badge/Version-1.18.6-informational?style=flat-square) ![AppVersion: 1.18.6](https://img.shields.io/badge/AppVersion-1.18.6-informational?style=flat-square) Cilium is open source software for providing and transparently securing network connectivity and loadbalancing between application workloads such as @@ -59,14 +59,10 @@ contributors across the globe, there is almost always someone available to help. | agentNotReadyTaintKey | string | `"node.cilium.io/agent-not-ready"` | Configure the key of the taint indicating that Cilium is not ready on the node. When set to a value starting with `ignore-taint.cluster-autoscaler.kubernetes.io/`, the Cluster Autoscaler will ignore the taint on its decisions, allowing the cluster to scale up. | | aksbyocni.enabled | bool | `false` | Enable AKS BYOCNI integration. Note that this is incompatible with AKS clusters not created in BYOCNI mode: use Azure integration (`azure.enabled`) instead. | | alibabacloud.enabled | bool | `false` | Enable AlibabaCloud ENI integration | -| alibabacloud.nodeSpec.securityGroupTags | list | `[]` | | -| alibabacloud.nodeSpec.securityGroups | list | `[]` | | -| alibabacloud.nodeSpec.vSwitchTags | list | `[]` | | -| alibabacloud.nodeSpec.vSwitches | list | `[]` | | | annotateK8sNode | bool | `false` | Annotate k8s node upon initialization with Cilium's metadata. | | annotations | object | `{}` | Annotations to be added to all top-level cilium-agent objects (resources under templates/cilium-agent) | | apiRateLimit | string | `nil` | The api-rate-limit option can be used to overwrite individual settings of the default configuration for rate limiting calls to the Cilium Agent API | -| authentication.enabled | bool | `false` | Enable authentication processing and garbage collection. Note that if disabled, policy enforcement will still block requests that require authentication. But the resulting authentication requests for these requests will not be processed, therefore the requests not be allowed. | +| authentication.enabled | bool | `true` | Enable authentication processing and garbage collection. Note that if disabled, policy enforcement will still block requests that require authentication. But the resulting authentication requests for these requests will not be processed, therefore the requests not be allowed. | | authentication.gcInterval | string | `"5m0s"` | Interval for garbage collection of auth map entries. | | authentication.mutual.connectTimeout | string | `"5s"` | Timeout for connecting to the remote node TCP socket | | authentication.mutual.port | int | `4250` | Port on the agent where mutual authentication handshakes between agents will be performed | @@ -77,7 +73,7 @@ contributors across the globe, there is almost always someone available to help. | authentication.mutual.spire.enabled | bool | `false` | Enable SPIRE integration (beta) | | authentication.mutual.spire.install.agent.affinity | object | `{}` | SPIRE agent affinity configuration | | authentication.mutual.spire.install.agent.annotations | object | `{}` | SPIRE agent annotations | -| authentication.mutual.spire.install.agent.image | object | `{"digest":"sha256:5106ac601272a88684db14daf7f54b9a45f31f77bb16a906bd5e87756ee7b97c","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-agent","tag":"1.9.6","useDigest":true}` | SPIRE agent image | +| authentication.mutual.spire.install.agent.image | object | `{"digest":"sha256:163970884fba18860cac93655dc32b6af85a5dcf2ebb7e3e119a10888eff8fcd","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-agent","tag":"1.12.4","useDigest":true}` | SPIRE agent image | | authentication.mutual.spire.install.agent.labels | object | `{}` | SPIRE agent labels | | authentication.mutual.spire.install.agent.nodeSelector | object | `{}` | SPIRE agent nodeSelector configuration ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | authentication.mutual.spire.install.agent.podSecurityContext | object | `{}` | Security context to be added to spire agent pods. SecurityContext holds pod-level security attributes and common container settings. ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod | @@ -89,7 +85,7 @@ contributors across the globe, there is almost always someone available to help. | authentication.mutual.spire.install.agent.tolerations | list | `[{"effect":"NoSchedule","key":"node.kubernetes.io/not-ready"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane"},{"effect":"NoSchedule","key":"node.cloudprovider.kubernetes.io/uninitialized","value":"true"},{"key":"CriticalAddonsOnly","operator":"Exists"}]` | SPIRE agent tolerations configuration By default it follows the same tolerations as the agent itself to allow the Cilium agent on this node to connect to SPIRE. ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | authentication.mutual.spire.install.enabled | bool | `true` | Enable SPIRE installation. This will only take effect only if authentication.mutual.spire.enabled is true | | authentication.mutual.spire.install.existingNamespace | bool | `false` | SPIRE namespace already exists. Set to true if Helm should not create, manage, and import the SPIRE namespace. | -| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.37.0","useDigest":true}` | init container image of SPIRE agent and server | +| authentication.mutual.spire.install.initImage | object | `{"digest":"sha256:2383baad1860bbe9d8a7a843775048fd07d8afe292b94bd876df64a69aae7cb1","override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/library/busybox","tag":"1.37.0","useDigest":true}` | init container image of SPIRE agent and server | | authentication.mutual.spire.install.namespace | string | `"cilium-spire"` | SPIRE namespace to install into | | authentication.mutual.spire.install.server.affinity | object | `{}` | SPIRE server affinity configuration | | authentication.mutual.spire.install.server.annotations | object | `{}` | SPIRE server annotations | @@ -99,7 +95,7 @@ contributors across the globe, there is almost always someone available to help. | authentication.mutual.spire.install.server.dataStorage.enabled | bool | `true` | Enable SPIRE server data storage | | authentication.mutual.spire.install.server.dataStorage.size | string | `"1Gi"` | Size of the SPIRE server data storage | | authentication.mutual.spire.install.server.dataStorage.storageClass | string | `nil` | StorageClass of the SPIRE server data storage | -| authentication.mutual.spire.install.server.image | object | `{"digest":"sha256:59a0b92b39773515e25e68a46c40d3b931b9c1860bc445a79ceb45a805cab8b4","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-server","tag":"1.9.6","useDigest":true}` | SPIRE server image | +| authentication.mutual.spire.install.server.image | object | `{"digest":"sha256:34147f27066ab2be5cc10ca1d4bfd361144196467155d46c45f3519f41596e49","override":null,"pullPolicy":"IfNotPresent","repository":"ghcr.io/spiffe/spire-server","tag":"1.12.4","useDigest":true}` | SPIRE server image | | authentication.mutual.spire.install.server.initContainers | list | `[]` | SPIRE server init containers | | authentication.mutual.spire.install.server.labels | object | `{}` | SPIRE server labels | | authentication.mutual.spire.install.server.nodeSelector | object | `{}` | SPIRE server nodeSelector configuration ref: ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | @@ -118,14 +114,13 @@ contributors across the globe, there is almost always someone available to help. | authentication.rotatedIdentitiesQueueSize | int | `1024` | Buffer size of the channel Cilium uses to receive certificate expiration events from auth handlers. | | autoDirectNodeRoutes | bool | `false` | Enable installation of PodCIDR routes between worker nodes if worker nodes share a common L2 network segment. | | azure.enabled | bool | `false` | Enable Azure integration. Note that this is incompatible with AKS clusters created in BYOCNI mode: use AKS BYOCNI integration (`aksbyocni.enabled`) instead. | -| azure.nodeSpec.azureInterfaceName | string | `""` | | | bandwidthManager | object | `{"bbr":false,"bbrHostNamespaceOnly":false,"enabled":false}` | Enable bandwidth manager to optimize TCP and UDP workloads and allow for rate-limiting traffic from individual Pods with EDT (Earliest Departure Time) through the "kubernetes.io/egress-bandwidth" Pod annotation. | | bandwidthManager.bbr | bool | `false` | Activate BBR TCP congestion control for Pods | | bandwidthManager.bbrHostNamespaceOnly | bool | `false` | Activate BBR TCP congestion control for Pods in the host namespace only. | | bandwidthManager.enabled | bool | `false` | Enable bandwidth manager infrastructure (also prerequirement for BBR) | -| bgpControlPlane | object | `{"enabled":false,"legacyOriginAttribute":{"enabled":false},"routerIDAllocation":{"ipPool":"","mode":"default"},"secretsNamespace":{"create":false,"name":"kube-system"},"statusReport":{"enabled":true}}` | This feature set enables virtual BGP routers to be created via BGP CRDs. | +| bgpControlPlane | object | `{"enabled":false,"legacyOriginAttribute":{"enabled":false},"routerIDAllocation":{"ipPool":"","mode":"default"},"secretsNamespace":{"create":false,"name":"kube-system"},"statusReport":{"enabled":true}}` | This feature set enables virtual BGP routers to be created via CiliumBGPPeeringPolicy CRDs. | | bgpControlPlane.enabled | bool | `false` | Enables the BGP control plane. | -| bgpControlPlane.legacyOriginAttribute | object | `{"enabled":false}` | Legacy BGP ORIGIN attribute settings | +| bgpControlPlane.legacyOriginAttribute | object | `{"enabled":false}` | Legacy BGP ORIGIN attribute settings (BGPv2 only) | | bgpControlPlane.legacyOriginAttribute.enabled | bool | `false` | Enable/Disable advertising LoadBalancerIP routes with the legacy BGP ORIGIN attribute value INCOMPLETE (2) instead of the default IGP (0). Enable for compatibility with the legacy behavior of MetalLB integration. | | bgpControlPlane.routerIDAllocation | object | `{"ipPool":"","mode":"default"}` | BGP router-id allocation mode | | bgpControlPlane.routerIDAllocation.ipPool | string | `""` | IP pool to allocate the BGP router-id from when the mode is ip-pool. | @@ -133,20 +128,20 @@ contributors across the globe, there is almost always someone available to help. | bgpControlPlane.secretsNamespace | object | `{"create":false,"name":"kube-system"}` | SecretsNamespace is the namespace which BGP support will retrieve secrets from. | | bgpControlPlane.secretsNamespace.create | bool | `false` | Create secrets namespace for BGP secrets. | | bgpControlPlane.secretsNamespace.name | string | `"kube-system"` | The name of the secret namespace to which Cilium agents are given read access | -| bgpControlPlane.statusReport | object | `{"enabled":true}` | Status reporting settings | -| bgpControlPlane.statusReport.enabled | bool | `true` | Enable/Disable BGP status reporting It is recommended to enable status reporting in general, but if you have any issue such as high API server load, you can disable it by setting this to false. | +| bgpControlPlane.statusReport | object | `{"enabled":true}` | Status reporting settings (BGPv2 only) | +| bgpControlPlane.statusReport.enabled | bool | `true` | Enable/Disable BGPv2 status reporting It is recommended to enable status reporting in general, but if you have any issue such as high API server load, you can disable it by setting this to false. | | bpf.authMapMax | int | `524288` | Configure the maximum number of entries in auth map. | | bpf.autoMount.enabled | bool | `true` | Enable automatic mount of BPF filesystem When `autoMount` is enabled, the BPF filesystem is mounted at `bpf.root` path on the underlying host and inside the cilium agent pod. If users disable `autoMount`, it's expected that users have mounted bpffs filesystem at the specified `bpf.root` volume, and then the volume will be mounted inside the cilium agent pod at the same path. | | bpf.ctAccounting | bool | `false` | Enable CT accounting for packets and bytes | | bpf.ctAnyMax | int | `262144` | Configure the maximum number of entries for the non-TCP connection tracking table. | | bpf.ctTcpMax | int | `524288` | Configure the maximum number of entries in the TCP connection tracking table. | -| bpf.datapathMode | string | `veth` | Mode for Pod devices for the core datapath (veth, netkit, netkit-l2). Note netkit is incompatible with TPROXY (`bpf.tproxy`). | +| bpf.datapathMode | string | `veth` | Mode for Pod devices for the core datapath (veth, netkit, netkit-l2) | | bpf.disableExternalIPMitigation | bool | `false` | Disable ExternalIP mitigation (CVE-2020-8554) | | bpf.distributedLRU | object | `{"enabled":false}` | Control to use a distributed per-CPU backend memory for the core BPF LRU maps which Cilium uses. This improves performance significantly, but it is also recommended to increase BPF map sizing along with that. | | bpf.distributedLRU.enabled | bool | `false` | Enable distributed LRU backend memory. For compatibility with existing installations it is off by default. | | bpf.enableTCX | bool | `true` | Attach endpoint programs using tcx instead of legacy tc hooks on supported kernels. | | bpf.events | object | `{"default":{"burstLimit":null,"rateLimit":null},"drop":{"enabled":true},"policyVerdict":{"enabled":true},"trace":{"enabled":true}}` | Control events generated by the Cilium datapath exposed to Cilium monitor and Hubble. Helm configuration for BPF events map rate limiting is experimental and might change in upcoming releases. | -| bpf.events.default | object | `{"burstLimit":null,"rateLimit":null}` | Default settings for all types of events except dbg. | +| bpf.events.default | object | `{"burstLimit":null,"rateLimit":null}` | Default settings for all types of events except dbg and pcap. | | bpf.events.default.burstLimit | int | `0` | Configure the maximum number of messages that can be written to BPF events map in 1 second. If burstLimit is greater than 0, non-zero value for rateLimit must also be provided lest the configuration is considered invalid. Setting both burstLimit and rateLimit to 0 disables BPF events rate limiting. | | bpf.events.default.rateLimit | int | `0` | Configure the limit of messages per second that can be written to BPF events map. The number of messages is averaged, meaning that if no messages were written to the map over 5 seconds, it's possible to write more events in the 6th second. If rateLimit is greater than 0, non-zero value for burstLimit must also be provided lest the configuration is considered invalid. Setting both burstLimit and rateLimit to 0 disables BPF events rate limiting. | | bpf.events.drop.enabled | bool | `true` | Enable drop events. | @@ -163,23 +158,19 @@ contributors across the globe, there is almost always someone available to help. | bpf.monitorAggregation | string | `"medium"` | Configure the level of aggregation for monitor notifications. Valid options are none, low, medium, maximum. | | bpf.monitorFlags | string | `"all"` | Configure which TCP flags trigger notifications when seen for the first time in a connection. | | bpf.monitorInterval | string | `"5s"` | Configure the typical time between monitor notifications for active connections. | -| bpf.monitorTraceIPOption | int | `0` | Configure the IP tracing option type. This option is used to specify the IP option type to use for tracing. The value must be an integer between 0 and 255. @schema type: [null, integer] minimum: 0 maximum: 255 @schema | | bpf.natMax | int | `524288` | Configure the maximum number of entries for the NAT table. | | bpf.neighMax | int | `524288` | Configure the maximum number of entries for the neighbor table. | | bpf.nodeMapMax | int | `nil` | Configures the maximum number of entries for the node table. | | bpf.policyMapMax | int | `16384` | Configure the maximum number of entries in endpoint policy map (per endpoint). @schema type: [null, integer] @schema | -| bpf.policyMapPressureMetricsThreshold | float64 | `0.1` | Configure threshold for emitting pressure metrics of policy maps. @schema type: [null, number] @schema | | bpf.policyStatsMapMax | int | `65536` | Configure the maximum number of entries in global policy stats map. @schema type: [null, integer] @schema | | bpf.preallocateMaps | bool | `false` | Enables pre-allocation of eBPF map values. This increases memory usage but can reduce latency. | | bpf.root | string | `"/sys/fs/bpf"` | Configure the mount point for the BPF filesystem | -| bpf.tproxy | bool | `false` | Configure the eBPF-based TPROXY (beta) to reduce reliance on iptables rules for implementing Layer 7 policy. Note this is incompatible with netkit (`bpf.datapathMode=netkit`, `bpf.datapathMode=netkit-l2`). | +| bpf.tproxy | bool | `false` | Configure the eBPF-based TPROXY (beta) to reduce reliance on iptables rules for implementing Layer 7 policy. | | bpf.vlanBypass | list | `[]` | Configure explicitly allowed VLAN id's for bpf logic bypass. [0] will allow all VLAN id's without any filtering. | | bpfClockProbe | bool | `false` | Enable BPF clock source probing for more efficient tick retrieval. | -| certgen | object | `{"affinity":{},"annotations":{"cronJob":{},"job":{}},"cronJob":{"failedJobsHistoryLimit":1,"successfulJobsHistoryLimit":3},"extraVolumeMounts":[],"extraVolumes":[],"generateCA":true,"image":{"digest":"sha256:f0c656830e856d26b24b0e144df1f8b327d3b46748d76a630514111fc365b697","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/certgen","tag":"v0.4.1","useDigest":true},"nodeSelector":{},"podLabels":{},"priorityClassName":"","resources":{},"tolerations":[],"ttlSecondsAfterFinished":null}` | Configure certificate generation for Hubble integration. If hubble.tls.auto.method=cronJob, these values are used for the Kubernetes CronJob which will be scheduled regularly to (re)generate any certificates not provided manually. | +| certgen | object | `{"affinity":{},"annotations":{"cronJob":{},"job":{}},"extraVolumeMounts":[],"extraVolumes":[],"generateCA":true,"image":{"digest":"sha256:2825dbfa6f89cbed882fd1d81e46a56c087e35885825139923aa29eb8aec47a9","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/certgen","tag":"v0.3.1","useDigest":true},"nodeSelector":{},"podLabels":{},"priorityClassName":"","resources":{},"tolerations":[],"ttlSecondsAfterFinished":1800}` | Configure certificate generation for Hubble integration. If hubble.tls.auto.method=cronJob, these values are used for the Kubernetes CronJob which will be scheduled regularly to (re)generate any certificates not provided manually. | | certgen.affinity | object | `{}` | Affinity for certgen | | certgen.annotations | object | `{"cronJob":{},"job":{}}` | Annotations to be added to the hubble-certgen initial Job and CronJob | -| certgen.cronJob.failedJobsHistoryLimit | int | `1` | The number of failed finished jobs to keep | -| certgen.cronJob.successfulJobsHistoryLimit | int | `3` | The number of successful finished jobs to keep | | certgen.extraVolumeMounts | list | `[]` | Additional certgen volumeMounts. | | certgen.extraVolumes | list | `[]` | Additional certgen volumes. | | certgen.generateCA | bool | `true` | When set to true the certificate authority secret is created. | @@ -188,7 +179,7 @@ contributors across the globe, there is almost always someone available to help. | certgen.priorityClassName | string | `""` | Priority class for certgen ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass | | certgen.resources | object | `{}` | Resource limits for certgen ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers | | certgen.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | -| certgen.ttlSecondsAfterFinished | string | `nil` | Seconds after which the completed job pod will be deleted | +| certgen.ttlSecondsAfterFinished | int | `1800` | Seconds after which the completed job pod will be deleted | | cgroup | object | `{"autoMount":{"enabled":true,"resources":{}},"hostRoot":"/run/cilium/cgroupv2"}` | Configure cgroup related configuration | | cgroup.autoMount.enabled | bool | `true` | Enable auto mount of cgroup2 filesystem. When `autoMount` is enabled, cgroup2 filesystem is mounted at `cgroup.hostRoot` path on the underlying host and inside the cilium agent pod. If users disable `autoMount`, it's expected that users have mounted cgroup2 filesystem at the specified `cgroup.hostRoot` volume, and then the volume will be mounted inside the cilium agent pod at the same path. | | cgroup.autoMount.resources | object | `{}` | Init Container Cgroup Automount resource limits & requests | @@ -214,7 +205,7 @@ contributors across the globe, there is almost always someone available to help. | clustermesh.apiserver.extraVolumeMounts | list | `[]` | Additional clustermesh-apiserver volumeMounts. | | clustermesh.apiserver.extraVolumes | list | `[]` | Additional clustermesh-apiserver volumes. | | clustermesh.apiserver.healthPort | int | `9880` | TCP port for the clustermesh-apiserver health API. | -| clustermesh.apiserver.image | object | `{"digest":"sha256:a8136a7615d6c6041d3aa6f2674d17beaec238170d669507ccc05328a778e2b7","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.19.3","useDigest":true}` | Clustermesh API server image. | +| clustermesh.apiserver.image | object | `{"digest":"sha256:8ee142912a0e261850c0802d9256ddbe3729e1cd35c6bea2d93077f334c3cf3b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/clustermesh-apiserver","tag":"v1.18.6","useDigest":true}` | Clustermesh API server image. | | clustermesh.apiserver.kvstoremesh.enabled | bool | `true` | Enable KVStoreMesh. KVStoreMesh caches the information retrieved from the remote clusters in the local etcd instance (deprecated - KVStoreMesh will always be enabled once the option is removed). | | clustermesh.apiserver.kvstoremesh.extraArgs | list | `[]` | Additional KVStoreMesh arguments. | | clustermesh.apiserver.kvstoremesh.extraEnv | list | `[]` | Additional KVStoreMesh environment variables. | @@ -264,65 +255,38 @@ contributors across the globe, there is almost always someone available to help. | clustermesh.apiserver.service.annotations | object | `{}` | Annotations for the clustermesh-apiserver service. Example annotations to configure an internal load balancer on different cloud providers: * AKS: service.beta.kubernetes.io/azure-load-balancer-internal: "true" * EKS: service.beta.kubernetes.io/aws-load-balancer-scheme: "internal" * GKE: networking.gke.io/load-balancer-type: "Internal" | | clustermesh.apiserver.service.enableSessionAffinity | string | `"HAOnly"` | Defines when to enable session affinity. Each replica in a clustermesh-apiserver deployment runs its own discrete etcd cluster. Remote clients connect to one of the replicas through a shared Kubernetes Service. A client reconnecting to a different backend will require a full resync to ensure data integrity. Session affinity can reduce the likelihood of this happening, but may not be supported by all cloud providers. Possible values: - "HAOnly" (default) Only enable session affinity for deployments with more than 1 replica. - "Always" Always enable session affinity. - "Never" Never enable session affinity. Useful in environments where session affinity is not supported, but may lead to slightly degraded performance due to more frequent reconnections. | | clustermesh.apiserver.service.externalTrafficPolicy | string | `"Cluster"` | The externalTrafficPolicy of service used for apiserver access. | -| clustermesh.apiserver.service.externallyCreated | bool | `false` | Set externallyCreated to true to create the clustermesh-apiserver service outside this helm chart. For example after external load balancer controllers are created. | | clustermesh.apiserver.service.internalTrafficPolicy | string | `"Cluster"` | The internalTrafficPolicy of service used for apiserver access. | | clustermesh.apiserver.service.labels | object | `{}` | Labels for the clustermesh-apiserver service. | | clustermesh.apiserver.service.loadBalancerClass | string | `nil` | Configure a loadBalancerClass. Allows to configure the loadBalancerClass on the clustermesh-apiserver LB service in case the Service type is set to LoadBalancer (requires Kubernetes 1.24+). | | clustermesh.apiserver.service.loadBalancerIP | string | `nil` | Configure a specific loadBalancerIP. Allows to configure a specific loadBalancerIP on the clustermesh-apiserver LB service in case the Service type is set to LoadBalancer. | | clustermesh.apiserver.service.loadBalancerSourceRanges | list | `[]` | Configure loadBalancerSourceRanges. Allows to configure the source IP ranges allowed to access the clustermesh-apiserver LB service in case the Service type is set to LoadBalancer. | -| clustermesh.apiserver.service.nodePort | int | `32379` | Optional port to use as the node port for apiserver access. | +| clustermesh.apiserver.service.nodePort | int | `32379` | Optional port to use as the node port for apiserver access. WARNING: make sure to configure a different NodePort in each cluster if kube-proxy replacement is enabled, as Cilium is currently affected by a known bug (#24692) when NodePorts are handled by the KPR implementation. If a service with the same NodePort exists both in the local and the remote cluster, all traffic originating from inside the cluster and targeting the corresponding NodePort will be redirected to a local backend, regardless of whether the destination node belongs to the local or the remote cluster. | | clustermesh.apiserver.service.type | string | `"NodePort"` | The type of service used for apiserver access. | | clustermesh.apiserver.terminationGracePeriodSeconds | int | `30` | terminationGracePeriodSeconds for the clustermesh-apiserver deployment | | clustermesh.apiserver.tls.admin | object | `{"cert":"","key":""}` | base64 encoded PEM values for the clustermesh-apiserver admin certificate and private key. Used if 'auto' is not enabled. | -| clustermesh.apiserver.tls.admin.cert | string | `""` | Deprecated, as secrets will always need to be created externally if `auto` is disabled. | -| clustermesh.apiserver.tls.admin.key | string | `""` | Deprecated, as secrets will always need to be created externally if `auto` is disabled. | -| clustermesh.apiserver.tls.authMode | string | `"migration"` | Configure the clustermesh authentication mode. Supported values: - legacy: All clusters access remote clustermesh instances with the same username (i.e., remote). The "remote" certificate must be generated with CN=remote if provided manually. - migration: Intermediate mode required to upgrade from legacy to cluster (and vice versa) with no disruption. Specifically, it enables the creation of the per-cluster usernames, while still using the common one for authentication. The "remote" certificate must be generated with CN=remote if provided manually (same as legacy). - cluster: Each cluster accesses remote etcd instances with a username depending on the local cluster name (i.e., remote-). The "remote" certificate must be generated with CN=remote- if provided manually. Cluster mode is meaningful only when the same CA is shared across all clusters part of the mesh. | +| clustermesh.apiserver.tls.authMode | string | `"legacy"` | Configure the clustermesh authentication mode. Supported values: - legacy: All clusters access remote clustermesh instances with the same username (i.e., remote). The "remote" certificate must be generated with CN=remote if provided manually. - migration: Intermediate mode required to upgrade from legacy to cluster (and vice versa) with no disruption. Specifically, it enables the creation of the per-cluster usernames, while still using the common one for authentication. The "remote" certificate must be generated with CN=remote if provided manually (same as legacy). - cluster: Each cluster accesses remote etcd instances with a username depending on the local cluster name (i.e., remote-). The "remote" certificate must be generated with CN=remote- if provided manually. Cluster mode is meaningful only when the same CA is shared across all clusters part of the mesh. | | clustermesh.apiserver.tls.auto | object | `{"certManagerIssuerRef":{},"certValidityDuration":1095,"enabled":true,"method":"helm"}` | Configure automatic TLS certificates generation. A Kubernetes CronJob is used the generate any certificates not provided by the user at installation time. | | clustermesh.apiserver.tls.auto.certManagerIssuerRef | object | `{}` | certmanager issuer used when clustermesh.apiserver.tls.auto.method=certmanager. | | clustermesh.apiserver.tls.auto.certValidityDuration | int | `1095` | Generated certificates validity duration in days. | -| clustermesh.apiserver.tls.auto.enabled | bool | `true` | When set to true, automatically generate a CA and certificates to enable mTLS between clustermesh-apiserver and external workload instances. When set to false you need to pre-create the following secrets: - clustermesh-apiserver-server-cert - clustermesh-apiserver-admin-cert - clustermesh-apiserver-remote-cert - clustermesh-apiserver-local-cert The above secret should at least contains the keys `tls.crt` and `tls.key` and optionally `ca.crt` if a CA bundle is not configured. | -| clustermesh.apiserver.tls.enableSecrets | deprecated | `true` | Allow users to provide their own certificates Users may need to provide their certificates using a mechanism that requires they provide their own secrets. This setting does not apply to any of the auto-generated mechanisms below, it only restricts the creation of secrets via the `tls-provided` templates. This option is deprecated as secrets are expected to be created externally when 'auto' is not enabled. | +| clustermesh.apiserver.tls.auto.enabled | bool | `true` | When set to true, automatically generate a CA and certificates to enable mTLS between clustermesh-apiserver and external workload instances. If set to false, the certs to be provided by setting appropriate values below. | +| clustermesh.apiserver.tls.client | object | `{"cert":"","key":""}` | base64 encoded PEM values for the clustermesh-apiserver client certificate and private key. Used if 'auto' is not enabled. | +| clustermesh.apiserver.tls.enableSecrets | bool | `true` | Allow users to provide their own certificates Users may need to provide their certificates using a mechanism that requires they provide their own secrets. This setting does not apply to any of the auto-generated mechanisms below, it only restricts the creation of secrets via the `tls-provided` templates. | | clustermesh.apiserver.tls.remote | object | `{"cert":"","key":""}` | base64 encoded PEM values for the clustermesh-apiserver remote cluster certificate and private key. Used if 'auto' is not enabled. | -| clustermesh.apiserver.tls.remote.cert | string | `""` | Deprecated, as secrets will always need to be created externally if `auto` is disabled. | -| clustermesh.apiserver.tls.remote.key | string | `""` | Deprecated, as secrets will always need to be created externally if `auto` is disabled. | | clustermesh.apiserver.tls.server | object | `{"cert":"","extraDnsNames":[],"extraIpAddresses":[],"key":""}` | base64 encoded PEM values for the clustermesh-apiserver server certificate and private key. Used if 'auto' is not enabled. | -| clustermesh.apiserver.tls.server.cert | string | `""` | Deprecated, as secrets will always need to be created externally if `auto` is disabled. | | clustermesh.apiserver.tls.server.extraDnsNames | list | `[]` | Extra DNS names added to certificate when it's auto generated | | clustermesh.apiserver.tls.server.extraIpAddresses | list | `[]` | Extra IP addresses added to certificate when it's auto generated | -| clustermesh.apiserver.tls.server.key | string | `""` | Deprecated, as secrets will always need to be created externally if `auto` is disabled. | | clustermesh.apiserver.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | clustermesh.apiserver.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for clustermesh-apiserver | | clustermesh.apiserver.updateStrategy | object | `{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0},"type":"RollingUpdate"}` | clustermesh-apiserver update strategy | -| clustermesh.cacheTTL | string | `"0s"` | The time to live for the cache of a remote cluster after connectivity is lost. If the connection is not re-established within this duration, the cached data is revoked to prevent stale state. If not specified or set to 0s, the cache is never revoked (default). | | clustermesh.config | object | `{"clusters":[],"domain":"mesh.cilium.io","enabled":false}` | Clustermesh explicit configuration. | -| clustermesh.config.clusters | list | `[]` | Clusters to be peered in the mesh. @schema type: [object, array] @schema | +| clustermesh.config.clusters | list | `[]` | List of clusters to be peered in the mesh. | | clustermesh.config.domain | string | `"mesh.cilium.io"` | Default dns domain for the Clustermesh API servers This is used in the case cluster addresses are not provided and IPs are used. | -| clustermesh.config.enabled | bool | `false` | Enable the Clustermesh explicit configuration. If set to false, you need to provide the following resources yourself: - (Secret) cilium-clustermesh (used by cilium-agent/cilium-operator to connect to the local etcd instance if KVStoreMesh is enabled or the remote clusters if KVStoreMesh is disabled) - (Secret) cilium-kvstoremesh (used by KVStoreMesh to connect to the remote clusters) - (ConfigMap) clustermesh-remote-users (used to create one etcd user per remote cluster if clustermesh-apiserver is used and `clustermesh.apiserver.tls.authMode` is not set to `legacy`) | +| clustermesh.config.enabled | bool | `false` | Enable the Clustermesh explicit configuration. | | clustermesh.enableEndpointSliceSynchronization | bool | `false` | Enable the synchronization of Kubernetes EndpointSlices corresponding to the remote endpoints of appropriately-annotated global services through ClusterMesh | -| clustermesh.enableMCSAPISupport | bool | `false` | Enable Multi-Cluster Services API support (deprecated; use clustermesh.mcsapi.enabled) | +| clustermesh.enableMCSAPISupport | bool | `false` | Enable Multi-Cluster Services API support | | clustermesh.maxConnectedClusters | int | `255` | The maximum number of clusters to support in a ClusterMesh. This value cannot be changed on running clusters, and all clusters in a ClusterMesh must be configured with the same value. Values > 255 will decrease the maximum allocatable cluster-local identities. Supported values are 255 and 511. | -| clustermesh.mcsapi.corednsAutoConfigure.affinity | object | `{}` | Affinity for coredns-mcsapi-autoconfig | -| clustermesh.mcsapi.corednsAutoConfigure.annotations | object | `{}` | Annotations to be added to the coredns-mcsapi-autoconfig Job | -| clustermesh.mcsapi.corednsAutoConfigure.coredns.clusterDomain | string | `"cluster.local"` | The cluster domain for the cluster CoreDNS service | -| clustermesh.mcsapi.corednsAutoConfigure.coredns.clustersetDomain | string | `"clusterset.local"` | The clusterset domain for the cluster CoreDNS service | -| clustermesh.mcsapi.corednsAutoConfigure.coredns.configMapName | string | `"coredns"` | The ConfigMap name for the cluster CoreDNS service | -| clustermesh.mcsapi.corednsAutoConfigure.coredns.deploymentName | string | `"coredns"` | The Deployment for the cluster CoreDNS service | -| clustermesh.mcsapi.corednsAutoConfigure.coredns.namespace | string | `"kube-system"` | The namespace for the cluster CoreDNS service | -| clustermesh.mcsapi.corednsAutoConfigure.coredns.serviceAccountName | string | `"coredns"` | The Service Account name for the cluster CoreDNS service | -| clustermesh.mcsapi.corednsAutoConfigure.enabled | bool | `false` | Enable auto-configuration of CoreDNS for Multi-Cluster Services API. CoreDNS MUST be at least in version v1.12.2 to run this. | -| clustermesh.mcsapi.corednsAutoConfigure.extraArgs | list | `[]` | Additional arguments to `clustermesh-apiserver coredns-mcsapi-auto-configure`. | -| clustermesh.mcsapi.corednsAutoConfigure.extraVolumeMounts | list | `[]` | Additional coredns-mcsapi-autoconfig volumeMounts. | -| clustermesh.mcsapi.corednsAutoConfigure.extraVolumes | list | `[]` | Additional coredns-mcsapi-autoconfig volumes. | -| clustermesh.mcsapi.corednsAutoConfigure.nodeSelector | object | `{}` | Node selector for coredns-mcsapi-autoconfig ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | -| clustermesh.mcsapi.corednsAutoConfigure.podLabels | object | `{}` | Labels to be added to coredns-mcsapi-autoconfig pods | -| clustermesh.mcsapi.corednsAutoConfigure.priorityClassName | string | `""` | Priority class for coredns-mcsapi-autoconfig ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass | -| clustermesh.mcsapi.corednsAutoConfigure.resources | object | `{}` | Resource limits for coredns-mcsapi-autoconfig ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers | -| clustermesh.mcsapi.corednsAutoConfigure.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | -| clustermesh.mcsapi.corednsAutoConfigure.ttlSecondsAfterFinished | int | `1800` | Seconds after which the completed job pod will be deleted | -| clustermesh.mcsapi.enabled | bool | `false` | Enable Multi-Cluster Services API support | -| clustermesh.mcsapi.installCRDs | bool | `true` | Enabled MCS-API CRDs auto-installation | -| clustermesh.policyDefaultLocalCluster | bool | `true` | Control whether policy rules assume by default the local cluster if not explicitly selected | -| clustermesh.useAPIServer | bool | `false` | Deploy clustermesh-apiserver for clustermesh. This option is typically used with ``clustermesh.config.enabled=true``. Refer to the ``clustermesh.config.enabled=true``documentation for more information. | +| clustermesh.policyDefaultLocalCluster | bool | `false` | Control whether policy rules assume by default the local cluster if not explicitly selected | +| clustermesh.useAPIServer | bool | `false` | Deploy clustermesh-apiserver for clustermesh | | cni.binPath | string | `"/opt/cni/bin"` | Configure the path to the CNI binary directory on the host. | | cni.chainingMode | string | `nil` | Configure chaining on top of other CNI plugins. Possible values: - none - aws-cni - flannel - generic-veth - portmap | | cni.chainingTarget | string | `nil` | A CNI network name in to which the Cilium plugin should be added as a chained plugin. This will cause the agent to watch for a CNI network with this network name. When it is found, this will be used as the basis for Cilium's CNI configuration file. If this is set, it assumes a chaining mode of generic-veth. As a special case, a chaining mode of aws-cni implies a chainingTarget of aws-cni. | @@ -337,17 +301,15 @@ contributors across the globe, there is almost always someone available to help. | cni.install | bool | `true` | Install the CNI configuration and binary files into the filesystem. | | cni.iptablesRemoveAWSRules | bool | `true` | Enable the removal of iptables rules created by the AWS CNI VPC plugin. | | cni.logFile | string | `"/var/run/cilium/cilium-cni.log"` | Configure the log file for CNI logging with retention policy of 7 days. Disable CNI file logging by setting this field to empty explicitly. | -| cni.resources | object | `{"limits":{"cpu":1,"memory":"1Gi"},"requests":{"cpu":"100m","memory":"10Mi"}}` | Specifies the resources for the cni initContainer | +| cni.resources | object | `{"requests":{"cpu":"100m","memory":"10Mi"}}` | Specifies the resources for the cni initContainer | | cni.uninstall | bool | `false` | Remove the CNI configuration and binary files on agent shutdown. Enable this if you're removing Cilium from the cluster. Disable this to prevent the CNI configuration file from being removed during agent upgrade, which can cause nodes to go unmanageable. | | commonLabels | object | `{}` | commonLabels allows users to add common labels for all Cilium resources. | -| configDriftDetection | object | `{"driftChecker":true,"enabled":true,"ignoredKeys":[]}` | Configuration for the ConfigMap drift detection feature. When enabled, the agent continuously watches the cilium-config ConfigMap and exposes a cilium_drift_checker_config_delta Prometheus metric reporting the number of keys that differ between the ConfigMap and the agent's active settings. A non-zero value indicates that the agent has not yet applied all current ConfigMap changes and needs to be restarted. | -| configDriftDetection.driftChecker | bool | `true` | Enable the drift checker which compares the DynamicConfig table against the agent's active settings and publishes the cilium_drift_checker_config_delta metric. | -| configDriftDetection.enabled | bool | `true` | Enable watching of the cilium-config ConfigMap and reflecting its contents into the agent's internal DynamicConfig table. | -| configDriftDetection.ignoredKeys | list | `[]` | List of config-map keys to ignore when computing the drift delta. | | connectivityProbeFrequencyRatio | float64 | `0.5` | Ratio of the connectivity probe frequency vs resource usage, a float in [0, 1]. 0 will give more frequent probing, 1 will give less frequent probing. Probing frequency is dynamically adjusted based on the cluster size. | | conntrackGCInterval | string | `"0s"` | Configure how frequently garbage collection should occur for the datapath connection tracking table. | | conntrackGCMaxInterval | string | `""` | Configure the maximum frequency for the garbage collection of the connection tracking table. Only affects the automatic computation for the frequency and has no effect when 'conntrackGCInterval' is set. This can be set to more frequently clean up unused identities created from ToFQDN policies. | | crdWaitTimeout | string | `"5m"` | Configure timeout in which Cilium will exit if CRDs are not available | +| customCalls | object | `{"enabled":false}` | Tail call hooks for custom eBPF programs. | +| customCalls.enabled | bool | `false` | Enable tail call hooks for custom eBPF programs. | | daemon.allowedConfigOverrides | string | `nil` | allowedConfigOverrides is a list of config-map keys that can be overridden. That is to say, if this value is set, config sources (excepting the first one) can only override keys in this list. This takes precedence over blockedConfigOverrides. By default, all keys may be overridden. To disable overrides, set this to "none" or change the configSources variable. | | daemon.blockedConfigOverrides | string | `nil` | blockedConfigOverrides is a list of config-map keys that may not be overridden. In other words, if any of these keys appear in a configuration source excepting the first one, they will be ignored This is ignored if allowedConfigOverrides is set. By default, all keys may be overridden. | | daemon.configSources | string | `nil` | Configure a custom list of possible configuration override sources The default is "config-map:cilium-config,cilium-node-config". For supported values, see the help text for the build-config subcommand. Note that this value should be a comma-separated string. | @@ -356,8 +318,8 @@ contributors across the globe, there is almost always someone available to help. | dashboards | object | `{"annotations":{},"enabled":false,"label":"grafana_dashboard","labelValue":"1","namespace":null}` | Grafana dashboards for cilium-agent grafana can import dashboards based on the label and value ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards | | debug.enabled | bool | `false` | Enable debug logging | | debug.metricsSamplingInterval | string | `"5m"` | Set the agent-internal metrics sampling frequency. This sets the frequency of the internal sampling of the agent metrics. These are available via the "cilium-dbg shell -- metrics -s" command and are part of the metrics HTML page included in the sysdump. @schema type: [null, string] @schema | -| debug.verbose | string | `nil` | Configure verbosity levels for debug logging This option is used to enable debug messages for operations related to such sub-system such as (e.g. kvstore, envoy, datapath, policy, or tagged), and flow is for enabling debug messages emitted per request, message and connection. Multiple values can be set via a space-separated string (e.g. "datapath envoy"). Applicable values: - flow - kvstore - envoy - datapath - policy - tagged | -| defaultLBServiceIPAM | string | `"lbipam"` | defaultLBServiceIPAM indicates the default LoadBalancer Service IPAM when no LoadBalancer class is set. Applicable values: lbipam, nodeipam, none | +| debug.verbose | string | `nil` | Configure verbosity levels for debug logging This option is used to enable debug messages for operations related to such sub-system such as (e.g. kvstore, envoy, datapath or policy), and flow is for enabling debug messages emitted per request, message and connection. Multiple values can be set via a space-separated string (e.g. "datapath envoy"). Applicable values: - flow - kvstore - envoy - datapath - policy | +| defaultLBServiceIPAM | string | `"lbipam"` | defaultLBServiceIPAM indicates the default LoadBalancer Service IPAM when no LoadBalancer class is set. Applicable values: lbipam, nodeipam, none @schema type: [string] @schema | | directRoutingSkipUnreachable | bool | `false` | Enable skipping of PodCIDR routes between worker nodes if the worker nodes are in a different L2 network segment. | | disableEndpointCRD | bool | `false` | Disable the usage of CiliumEndpoint CRD. | | dnsPolicy | string | `""` | DNS policy for Cilium agent pods. Ref: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy | @@ -376,13 +338,12 @@ contributors across the globe, there is almost always someone available to help. | egressGateway.reconciliationTriggerInterval | string | `"1s"` | Time between triggers of egress gateway state reconciliations | | enableCriticalPriorityClass | bool | `true` | Explicitly enable or disable priority class. .Capabilities.KubeVersion is unsettable in `helm template` calls, it depends on k8s libraries version that Helm was compiled against. This option allows to explicitly disable setting the priority class, which is useful for rendering charts for gke clusters in advance. | | enableIPv4BIGTCP | bool | `false` | Enables IPv4 BIG TCP support which increases maximum IPv4 GSO/GRO limits for nodes and pods | -| enableIPv4Masquerade | bool | `true` unless ipam eni mode is active | Enables masquerading of IPv4 traffic leaving the node from endpoints. | +| enableIPv4Masquerade | bool | `true` unless ipam eni mode is active | Enables masquerading of IPv4 traffic leaving the node from endpoints. | | enableIPv6BIGTCP | bool | `false` | Enables IPv6 BIG TCP support which increases maximum IPv6 GSO/GRO limits for nodes and pods | | enableIPv6Masquerade | bool | `true` | Enables masquerading of IPv6 traffic leaving the node from endpoints. | | enableInternalTrafficPolicy | bool | `true` | Enable Internal Traffic Policy | | enableLBIPAM | bool | `true` | Enable LoadBalancer IP Address Management | | enableMasqueradeRouteSource | bool | `false` | Enables masquerading to the source of the route for traffic leaving the node from endpoints. | -| enableNoServiceEndpointsRoutable | bool | `true` | Enable routing to a service that has zero endpoints | | enableNonDefaultDenyPolicies | bool | `true` | Enable Non-Default-Deny policies | | enableXTSocketFallback | bool | `true` | Enables the fallback compatibility solution for when the xt_socket kernel module is missing and it is needed for the datapath L7 redirection to work properly. See documentation for details on when this can be disabled: https://docs.cilium.io/en/stable/operations/system_requirements/#linux-kernel. | | encryption.enabled | bool | `false` | Enable transparent network encryption. | @@ -394,39 +355,14 @@ contributors across the globe, there is almost always someone available to help. | encryption.ipsec.mountPath | string | `"/etc/ipsec"` | Path to mount the secret inside the Cilium pod. | | encryption.ipsec.secretName | string | `"cilium-ipsec-keys"` | Name of the Kubernetes secret containing the encryption keys. | | encryption.nodeEncryption | bool | `false` | Enable encryption for pure node to node traffic. This option is only effective when encryption.type is set to "wireguard". | -| encryption.strictMode | object | `{"allowRemoteNodeIdentities":false,"cidr":"","egress":{"allowRemoteNodeIdentities":false,"cidr":"","enabled":false},"enabled":false,"ingress":{"enabled":false}}` | Configure the Encryption Pod2Pod strict mode. | -| encryption.strictMode.allowRemoteNodeIdentities | bool | `false` | Allow dynamic lookup of remote node identities. (deprecated: please use encryption.strictMode.egress.allowRemoteNodeIdentities) This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. | -| encryption.strictMode.cidr | string | `""` | CIDR for the Encryption Pod2Pod strict mode. (deprecated: please use encryption.strictMode.egress.cidr) | -| encryption.strictMode.egress.allowRemoteNodeIdentities | bool | `false` | Allow dynamic lookup of remote node identities. This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. | -| encryption.strictMode.egress.cidr | string | `""` | CIDR for the Encryption Pod2Pod strict egress mode. | -| encryption.strictMode.egress.enabled | bool | `false` | Enable strict egress encryption. | -| encryption.strictMode.enabled | bool | `false` | Enable Encryption Pod2Pod strict mode. (deprecated: please use encryption.strictMode.egress.enabled) | -| encryption.strictMode.ingress.enabled | bool | `false` | Enable strict ingress encryption. When enabled, all unencrypted overlay ingress traffic will be dropped. This option is only applicable when WireGuard and tunneling are enabled. | -| encryption.type | string | `"ipsec"` | Encryption method. Can be one of ipsec, wireguard or ztunnel. | +| encryption.strictMode | object | `{"allowRemoteNodeIdentities":false,"cidr":"","enabled":false}` | Configure the WireGuard Pod2Pod strict mode. | +| encryption.strictMode.allowRemoteNodeIdentities | bool | `false` | Allow dynamic lookup of remote node identities. This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. | +| encryption.strictMode.cidr | string | `""` | CIDR for the WireGuard Pod2Pod strict mode. | +| encryption.strictMode.enabled | bool | `false` | Enable WireGuard Pod2Pod strict mode. | +| encryption.type | string | `"ipsec"` | Encryption method. Can be either ipsec or wireguard. | | encryption.wireguard.persistentKeepalive | string | `"0s"` | Controls WireGuard PersistentKeepalive option. Set 0s to disable. | -| encryption.ztunnel | object | `{"affinity":{},"annotations":{},"caAddress":"https://localhost:15012","extraEnv":[],"extraVolumeMounts":[],"extraVolumes":[],"healthPort":15021,"image":{"digest":null,"override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/istio/ztunnel","tag":"1.28.0-distroless","useDigest":false},"nodeSelector":{"kubernetes.io/os":"linux"},"podAnnotations":{},"podLabels":{},"priorityClassName":null,"readinessProbe":{"failureThreshold":3,"initialDelaySeconds":0,"periodSeconds":10},"resources":{"requests":{"cpu":"200m","memory":"512Mi"}},"secrets":{"bootstrapRootCert":null},"terminationGracePeriodSeconds":30,"tolerations":[{"effect":"NoSchedule","operator":"Exists"},{"key":"CriticalAddonsOnly","operator":"Exists"},{"effect":"NoExecute","operator":"Exists"}],"updateStrategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0},"type":"RollingUpdate"}}` | ztunnel encryption configuration. ztunnel is Istio's purpose-built, per-node proxy for handling L4 traffic in ambient mesh mode. These settings only apply when encryption.type is set to "ztunnel". | -| encryption.ztunnel.affinity | object | `{}` | Affinity for ztunnel pods. | -| encryption.ztunnel.annotations | object | `{}` | Annotations to be added to all ztunnel resources. | -| encryption.ztunnel.caAddress | string | `"https://localhost:15012"` | CA server address for certificate requests. | -| encryption.ztunnel.extraEnv | list | `[]` | Additional ztunnel container environment variables. | -| encryption.ztunnel.extraVolumeMounts | list | `[]` | Additional ztunnel volumeMounts. | -| encryption.ztunnel.extraVolumes | list | `[]` | Additional ztunnel volumes. | -| encryption.ztunnel.healthPort | int | `15021` | TCP port for the health API. | -| encryption.ztunnel.image | object | `{"digest":null,"override":null,"pullPolicy":"IfNotPresent","repository":"docker.io/istio/ztunnel","tag":"1.28.0-distroless","useDigest":false}` | ztunnel container image. | -| encryption.ztunnel.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node selector for ztunnel pods. | -| encryption.ztunnel.podAnnotations | object | `{}` | Annotations to be added to ztunnel pods. | -| encryption.ztunnel.podLabels | object | `{}` | Labels to be added to ztunnel pods. | -| encryption.ztunnel.priorityClassName | string | `nil` | The priority class to use for ztunnel pods. | -| encryption.ztunnel.readinessProbe | object | `{"failureThreshold":3,"initialDelaySeconds":0,"periodSeconds":10}` | Readiness probe configuration. | -| encryption.ztunnel.resources | object | `{"requests":{"cpu":"200m","memory":"512Mi"}}` | ztunnel resource limits & requests. | -| encryption.ztunnel.secrets | object | `{"bootstrapRootCert":null}` | ztunnel secrets configuration. | -| encryption.ztunnel.secrets.bootstrapRootCert | string | `nil` | Base64-encoded bootstrap root certificate content. If not provided, the secret must be created manually before deploying. @schema type: [null, string] @schema | -| encryption.ztunnel.terminationGracePeriodSeconds | int | `30` | Configure termination grace period for ztunnel DaemonSet. | -| encryption.ztunnel.tolerations | list | `[{"effect":"NoSchedule","operator":"Exists"},{"key":"CriticalAddonsOnly","operator":"Exists"},{"effect":"NoExecute","operator":"Exists"}]` | Node tolerations for ztunnel scheduling. | -| encryption.ztunnel.updateStrategy | object | `{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0},"type":"RollingUpdate"}` | ztunnel update strategy. | | endpointHealthChecking.enabled | bool | `true` | Enable connectivity health checking between virtual endpoints. | | endpointLockdownOnMapOverflow | bool | `false` | Enable endpoint lockdown on policy map overflow. | -| endpointPolicyUpdateTimeoutDuration | string | `nil` | Max duration to wait for envoy to respond to configuration changes. Default "10s". | | endpointRoutes.enabled | bool | `false` | Enable use of per endpoint routes instead of routing via the cilium_host interface. | | eni.awsEnablePrefixDelegation | bool | `false` | Enable ENI prefix delegation | | eni.awsReleaseExcessIPs | bool | `false` | Release IPs not used from the ENI | @@ -437,24 +373,12 @@ contributors across the globe, there is almost always someone available to help. | eni.gcTags | object | `{"io.cilium/cilium-managed":"true,"io.cilium/cluster-name":""}` | Additional tags attached to ENIs created by Cilium. Dangling ENIs with this tag will be garbage collected | | eni.iamRole | string | `""` | If using IAM role for Service Accounts will not try to inject identity values from cilium-aws kubernetes secret. Adds annotation to service account if managed by Helm. See https://github.com/aws/amazon-eks-pod-identity-webhook | | eni.instanceTagsFilter | list | `[]` | Filter via AWS EC2 Instance tags (k=v) which will dictate which AWS EC2 Instances are going to be used to create new ENIs | -| eni.nodeSpec | object | `{"deleteOnTermination":null,"disablePrefixDelegation":false,"excludeInterfaceTags":[],"firstInterfaceIndex":null,"securityGroupTags":[],"securityGroups":[],"subnetIDs":[],"subnetTags":[],"usePrimaryAddress":false}` | NodeSpec configuration for the ENI | -| eni.nodeSpec.deleteOnTermination | string | `nil` | Delete ENI on termination @schema type: [null, boolean] @schema | -| eni.nodeSpec.disablePrefixDelegation | bool | `false` | Disable prefix delegation for IP allocation | -| eni.nodeSpec.excludeInterfaceTags | list | `[]` | Exclude interface tags to use for IP allocation | -| eni.nodeSpec.firstInterfaceIndex | string | `nil` | First interface index to use for IP allocation @schema type: [null, integer] @schema | -| eni.nodeSpec.securityGroupTags | list | `[]` | Security group tags to use for IP allocation | -| eni.nodeSpec.securityGroups | list | `[]` | Security groups to use for IP allocation | -| eni.nodeSpec.subnetIDs | list | `[]` | Subnet IDs to use for IP allocation | -| eni.nodeSpec.subnetTags | list | `[]` | Subnet tags to use for IP allocation | -| eni.nodeSpec.usePrimaryAddress | bool | `false` | Use primary address for IP allocation | | eni.subnetIDsFilter | list | `[]` | Filter via subnet IDs which will dictate which subnets are going to be used to create new ENIs Important note: This requires that each instance has an ENI with a matching subnet attached when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, use the CNI configuration file settings (cni.customConf) instead. | | eni.subnetTagsFilter | list | `[]` | Filter via tags (k=v) which will dictate which subnets are going to be used to create new ENIs Important note: This requires that each instance has an ENI with a matching subnet attached when Cilium is deployed. If you only want to control subnets for ENIs attached by Cilium, use the CNI configuration file settings (cni.customConf) instead. | | envoy.affinity | object | `{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"cilium.io/no-schedule","operator":"NotIn","values":["true"]}]}]}},"podAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]},"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium-envoy"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-envoy. | | envoy.annotations | object | `{}` | Annotations to be added to all top-level cilium-envoy objects (resources under templates/cilium-envoy) | | envoy.baseID | int | `0` | Set Envoy'--base-id' to use when allocating shared memory regions. Only needs to be changed if multiple Envoy instances will run on the same node and may have conflicts. Supported values: 0 - 4294967295. Defaults to '0' | | envoy.bootstrapConfigMap | string | `nil` | ADVANCED OPTION: Bring your own custom Envoy bootstrap ConfigMap. Provide the name of a ConfigMap with a `bootstrap-config.json` key. When specified, Envoy will use this ConfigMap instead of the default provided by the chart. WARNING: Use of this setting has the potential to prevent cilium-envoy from starting up, and can cause unexpected behavior (e.g. due to syntax error or semantically incorrect configuration). Before submitting an issue, please ensure you have disabled this feature, as support cannot be provided for custom Envoy bootstrap configs. @schema type: [null, string] @schema | -| envoy.clusterMaxConnections | int | `1024` | Maximum number of connections on Envoy clusters | -| envoy.clusterMaxRequests | int | `1024` | Maximum number of requests on Envoy clusters | | envoy.connectTimeoutSeconds | int | `2` | Time in seconds after which a TCP connection attempt times out | | envoy.debug.admin.enabled | bool | `false` | Enable admin interface for cilium-envoy. This is useful for debugging and should not be enabled in production. | | envoy.debug.admin.port | int | `9901` | Port number (bound to loopback interface). kubectl port-forward can be used to access the admin interface. | @@ -470,8 +394,7 @@ contributors across the globe, there is almost always someone available to help. | envoy.httpRetryCount | int | `3` | Maximum number of retries for each HTTP request | | envoy.httpUpstreamLingerTimeout | string | `nil` | Time in seconds to block Envoy worker thread while an upstream HTTP connection is closing. If set to 0, the connection is closed immediately (with TCP RST). If set to -1, the connection is closed asynchronously in the background. | | envoy.idleTimeoutDurationSeconds | int | `60` | Set Envoy upstream HTTP idle connection timeout seconds. Does not apply to connections with pending requests. Default 60s | -| envoy.image | object | `{"digest":"sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa","useDigest":true}` | Envoy container image. | -| envoy.initContainers | list | `[]` | Init containers added to the cilium Envoy DaemonSet. | +| envoy.image | object | `{"digest":"sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9","useDigest":true}` | Envoy container image. | | envoy.initialFetchTimeoutSeconds | int | `30` | Time in seconds after which the initial fetch on an xDS stream is considered timed out | | envoy.livenessProbe.enabled | bool | `true` | Enable liveness probe for cilium-envoy | | envoy.livenessProbe.failureThreshold | int | `10` | failure threshold of liveness probe | @@ -483,7 +406,6 @@ contributors across the globe, there is almost always someone available to help. | envoy.log.path | string | `""` | Path to a separate Envoy log file, if any. Defaults to /dev/stdout. | | envoy.maxConcurrentRetries | int | `128` | Maximum number of concurrent retries on Envoy clusters | | envoy.maxConnectionDurationSeconds | int | `0` | Set Envoy HTTP option max_connection_duration seconds. Default 0 (disable) | -| envoy.maxGlobalDownstreamConnections | int | `50000` | Maximum number of global downstream connections | | envoy.maxRequestsPerConnection | int | `0` | ProxyMaxRequestsPerConnection specifies the max_requests_per_connection setting for Envoy | | envoy.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node selector for cilium-envoy. | | envoy.podAnnotations | object | `{}` | Annotations to be added to envoy pods | @@ -517,7 +439,6 @@ contributors across the globe, there is almost always someone available to help. | envoy.terminationGracePeriodSeconds | int | `1` | Configure termination grace period for cilium-envoy DaemonSet. | | envoy.tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for envoy scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | envoy.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":2},"type":"RollingUpdate"}` | cilium-envoy update strategy ref: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#updating-a-daemonset | -| envoy.useOriginalSourceAddress | bool | `true` | For cases when CiliumEnvoyConfig is not used directly (Ingress, Gateway), configures Cilium BPF Metadata listener filter to use the original source address when extracting the metadata for a request. | | envoy.xffNumTrustedHopsL7PolicyEgress | int | `0` | Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the egress L7 policy enforcement Envoy listeners. | | envoy.xffNumTrustedHopsL7PolicyIngress | int | `0` | Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the ingress L7 policy enforcement Envoy listeners. | | envoyConfig.enabled | bool | `false` | Enable CiliumEnvoyConfig CRD CiliumEnvoyConfig CRD can also be implicitly enabled by other options. | @@ -561,13 +482,12 @@ contributors across the globe, there is almost always someone available to help. | hubble.dropEventEmitter.interval | string | `"2m"` | - Minimum time between emitting same events. | | hubble.dropEventEmitter.reasons | list | `["auth_required","policy_denied"]` | - Drop reasons to emit events for. ref: https://docs.cilium.io/en/stable/_api/v1/flow/README/#dropreason | | hubble.enabled | bool | `true` | Enable Hubble (true by default). | -| hubble.export | object | `{"dynamic":{"config":{"configMapName":"cilium-flowlog-config","content":[{"aggregationInterval":"0s","excludeFilters":[],"fieldAggregate":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log","includeFilters":[],"name":"all"}],"createConfigMap":true},"enabled":false},"static":{"aggregationInterval":"0s","allowList":[],"denyList":[],"enabled":false,"fieldAggregate":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log"}}` | Hubble flows export. | -| hubble.export.dynamic | object | `{"config":{"configMapName":"cilium-flowlog-config","content":[{"aggregationInterval":"0s","excludeFilters":[],"fieldAggregate":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log","includeFilters":[],"name":"all"}],"createConfigMap":true},"enabled":false}` | - Dynamic exporters configuration. Dynamic exporters may be reconfigured without a need of agent restarts. | +| hubble.export | object | `{"dynamic":{"config":{"configMapName":"cilium-flowlog-config","content":[{"excludeFilters":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log","includeFilters":[],"name":"all"}],"createConfigMap":true},"enabled":false},"static":{"allowList":[],"denyList":[],"enabled":false,"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log"}}` | Hubble flows export. | +| hubble.export.dynamic | object | `{"config":{"configMapName":"cilium-flowlog-config","content":[{"excludeFilters":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log","includeFilters":[],"name":"all"}],"createConfigMap":true},"enabled":false}` | - Dynamic exporters configuration. Dynamic exporters may be reconfigured without a need of agent restarts. | | hubble.export.dynamic.config.configMapName | string | `"cilium-flowlog-config"` | -- Name of configmap with configuration that may be altered to reconfigure exporters within a running agents. | -| hubble.export.dynamic.config.content | list | `[{"aggregationInterval":"0s","excludeFilters":[],"fieldAggregate":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log","includeFilters":[],"name":"all"}]` | -- Exporters configuration in YAML format. | +| hubble.export.dynamic.config.content | list | `[{"excludeFilters":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log","includeFilters":[],"name":"all"}]` | -- Exporters configuration in YAML format. | | hubble.export.dynamic.config.createConfigMap | bool | `true` | -- True if helm installer should create config map. Switch to false if you want to self maintain the file content. | -| hubble.export.static | object | `{"aggregationInterval":"0s","allowList":[],"denyList":[],"enabled":false,"fieldAggregate":[],"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log"}` | - Static exporter configuration. Static exporter is bound to agent lifecycle. | -| hubble.export.static.aggregationInterval | string | `"0s"` | - Defines the interval at which to aggregate before exporting Hubble flows. Aggregation feature is only enabled when fieldAggregate is specified and aggregationInterval > 0s. | +| hubble.export.static | object | `{"allowList":[],"denyList":[],"enabled":false,"fieldMask":[],"fileCompress":false,"fileMaxBackups":5,"fileMaxSizeMb":10,"filePath":"/var/run/cilium/hubble/events.log"}` | - Static exporter configuration. Static exporter is bound to agent lifecycle. | | hubble.export.static.fileCompress | bool | `false` | - Enable compression of rotated files. | | hubble.export.static.fileMaxBackups | int | `5` | - Defines max number of backup/rotated files. | | hubble.export.static.fileMaxSizeMb | int | `10` | - Defines max file size of output file before it gets rotated. | @@ -615,12 +535,9 @@ contributors across the globe, there is almost always someone available to help. | hubble.relay.extraVolumes | list | `[]` | Additional hubble-relay volumes. | | hubble.relay.gops.enabled | bool | `true` | Enable gops for hubble-relay | | hubble.relay.gops.port | int | `9893` | Configure gops listen port for hubble-relay | -| hubble.relay.image | object | `{"digest":"sha256:5ee21d57b6ef2aa6db67e603a735fdceb162454b352b7335b651456e308f681b","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.19.3","useDigest":true}` | Hubble-relay container image. | +| hubble.relay.image | object | `{"digest":"sha256:fb6135e34c31e5f175cb5e75f86cea52ef2ff12b49bcefb7088ed93f5009eb8e","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/hubble-relay","tag":"v1.18.6","useDigest":true}` | Hubble-relay container image. | | hubble.relay.listenHost | string | `""` | Host to listen to. Specify an empty string to bind to all the interfaces. | | hubble.relay.listenPort | string | `"4245"` | Port to listen to. | -| hubble.relay.logOptions | object | `{"format":null,"level":null}` | Logging configuration for hubble-relay. | -| hubble.relay.logOptions.format | string | text-ts | Log format for hubble-relay. Valid values are: text, text-ts, json, json-ts. | -| hubble.relay.logOptions.level | string | info | Log level for hubble-relay. Valid values are: debug, info, warn, error. | | hubble.relay.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | hubble.relay.podAnnotations | object | `{}` | Annotations to be added to hubble-relay pods | | hubble.relay.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | @@ -630,9 +547,7 @@ contributors across the globe, there is almost always someone available to help. | hubble.relay.podLabels | object | `{}` | Labels to be added to hubble-relay pods | | hubble.relay.podSecurityContext | object | `{"fsGroup":65532,"seccompProfile":{"type":"RuntimeDefault"}}` | hubble-relay pod security context | | hubble.relay.pprof.address | string | `"localhost"` | Configure pprof listen address for hubble-relay | -| hubble.relay.pprof.blockProfileRate | int | `0` | Enable goroutine blocking profiling for hubble-relay and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) | | hubble.relay.pprof.enabled | bool | `false` | Enable pprof for hubble-relay | -| hubble.relay.pprof.mutexProfileFraction | int | `0` | Enable mutex contention profiling for hubble-relay and set the fraction of sampled events (set to 1 to sample all events) | | hubble.relay.pprof.port | int | `6062` | Configure pprof listen port for hubble-relay | | hubble.relay.priorityClassName | string | `""` | The priority class to use for hubble-relay | | hubble.relay.prometheus | object | `{"enabled":false,"port":9966,"serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","labels":{},"metricRelabelings":null,"relabelings":null,"scrapeTimeout":null}}` | Enable prometheus metrics for hubble-relay on the configured port at /metrics | @@ -726,14 +641,13 @@ contributors across the globe, there is almost always someone available to help. | hubble.ui.tls.client.cert | string | `""` | base64 encoded PEM values for the Hubble UI client certificate (deprecated). Use existingSecret instead. | | hubble.ui.tls.client.existingSecret | string | `""` | Name of the Secret containing the client certificate and key for Hubble UI If specified, cert and key are ignored. | | hubble.ui.tls.client.key | string | `""` | base64 encoded PEM values for the Hubble UI client key (deprecated). Use existingSecret instead. | -| hubble.ui.tmpVolume | object | `{}` | Configure temporary volume for hubble-ui | | hubble.ui.tolerations | list | `[]` | Node tolerations for pod assignment on nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | hubble.ui.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for hubble-ui | | hubble.ui.updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":1},"type":"RollingUpdate"}` | hubble-ui update strategy. | | identityAllocationMode | string | `"crd"` | Method to use for identity allocation (`crd`, `kvstore` or `doublewrite-readkvstore` / `doublewrite-readcrd` for migrating between identity backends). | | identityChangeGracePeriod | string | `"5s"` | Time to wait before using new identity on endpoint identity change. | | identityManagementMode | string | `"agent"` | Control whether CiliumIdentities are created by the agent ("agent"), the operator ("operator") or both ("both"). "Both" should be used only to migrate between "agent" and "operator". Operator-managed identities is a beta feature. | -| image | object | `{"digest":"sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.19.3","useDigest":true}` | Agent container image. | +| image | object | `{"digest":"sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.18.6","useDigest":true}` | Agent container image. | | imagePullSecrets | list | `[]` | Configure image pull secrets for pulling container images | | ingressController.default | bool | `false` | Set cilium ingress controller to be the default ingress controller This will let cilium ingress controller route entries without ingress class set | | ingressController.defaultSecretName | string | `nil` | Default secret name for ingresses without .spec.tls[].secretName set. | @@ -768,11 +682,6 @@ contributors across the globe, there is almost always someone available to help. | ipam.installUplinkRoutesForDelegatedIPAM | bool | `false` | Install ingress/egress routes through uplink on host for Pods when working with delegated IPAM plugin. | | ipam.mode | string | `"cluster-pool"` | Configure IP Address Management mode. ref: https://docs.cilium.io/en/stable/network/concepts/ipam/ | | ipam.multiPoolPreAllocation | string | `""` | Pre-allocation settings for IPAM in Multi-Pool mode | -| ipam.nodeSpec | object | `{"ipamMaxAllocate":null,"ipamMinAllocate":null,"ipamPreAllocate":null,"ipamStaticIPTags":[]}` | NodeSpec configuration for the IPAM | -| ipam.nodeSpec.ipamMaxAllocate | string | `nil` | IPAM max allocate @schema type: [null, integer] @schema | -| ipam.nodeSpec.ipamMinAllocate | string | `nil` | IPAM min allocate @schema type: [null, integer] @schema | -| ipam.nodeSpec.ipamPreAllocate | string | `nil` | IPAM pre allocate @schema type: [null, integer] @schema | -| ipam.nodeSpec.ipamStaticIPTags | list | `[]` | IPAM static IP tags (currently only works with AWS and Azure) | | ipam.operator.autoCreateCiliumPodIPPools | object | `{}` | IP pools to auto-create in multi-pool IPAM mode. | | ipam.operator.clusterPoolIPv4MaskSize | int | `24` | IPv4 CIDR mask size to delegate to individual nodes for IPAM. | | ipam.operator.clusterPoolIPv4PodCIDRList | list | `["10.0.0.0/8"]` | IPv4 CIDR list range to delegate to individual nodes for IPAM. | @@ -821,13 +730,12 @@ contributors across the globe, there is almost always someone available to help. | livenessProbe.failureThreshold | int | `10` | failure threshold of liveness probe | | livenessProbe.periodSeconds | int | `30` | interval between checks of the liveness probe | | livenessProbe.requireK8sConnectivity | bool | `false` | whether to require k8s connectivity as part of the check. | -| loadBalancer | object | `{"acceleration":"disabled","l7":{"algorithm":"round_robin","backend":"disabled","ports":[]},"serviceTopology":false}` | Configure service load balancing | +| loadBalancer | object | `{"acceleration":"disabled","l7":{"algorithm":"round_robin","backend":"disabled","ports":[]}}` | Configure service load balancing | | loadBalancer.acceleration | string | `"disabled"` | acceleration is the option to accelerate service handling via XDP Applicable values can be: disabled (do not use XDP), native (XDP BPF program is run directly out of the networking driver's early receive path), or best-effort (use native mode XDP acceleration on devices that support it). | | loadBalancer.l7 | object | `{"algorithm":"round_robin","backend":"disabled","ports":[]}` | L7 LoadBalancer | | loadBalancer.l7.algorithm | string | `"round_robin"` | Default LB algorithm The default LB algorithm to be used for services, which can be overridden by the service annotation (e.g. service.cilium.io/lb-l7-algorithm) Applicable values: round_robin, least_request, random | | loadBalancer.l7.backend | string | `"disabled"` | Enable L7 service load balancing via envoy proxy. The request to a k8s service, which has specific annotation e.g. service.cilium.io/lb-l7, will be forwarded to the local backend proxy to be load balanced to the service endpoints. Please refer to docs for supported annotations for more configuration. Applicable values: - envoy: Enable L7 load balancing via envoy proxy. This will automatically set enable-envoy-config as well. - disabled: Disable L7 load balancing by way of service annotation. | | loadBalancer.l7.ports | list | `[]` | List of ports from service to be automatically redirected to above backend. Any service exposing one of these ports will be automatically redirected. Fine-grained control can be achieved by using the service annotation. | -| loadBalancer.serviceTopology | bool | `false` | serviceTopology enables K8s Topology Aware Hints -based service endpoints filtering | | localRedirectPolicies.addressMatcherCIDRs | string | `nil` | Limit the allowed addresses in Address Matcher rule of Local Redirect Policies to the given CIDRs. @schema@ type: [null, array] @schema@ | | localRedirectPolicies.enabled | bool | `false` | Enable local redirect policies. | | localRedirectPolicy | bool | `false` | Enable Local Redirect Policy (deprecated, please use 'localRedirectPolicies.enabled' instead) | @@ -836,18 +744,19 @@ contributors across the globe, there is almost always someone available to help. | monitor | object | `{"enabled":false}` | cilium-monitor sidecar. | | monitor.enabled | bool | `false` | Enable the cilium-monitor sidecar. | | name | string | `"cilium"` | Agent daemonset name. | -| namespaceOverride | string | `""` | namespaceOverride allows to override the destination namespace for Cilium resources. | +| namespaceOverride | string | `""` | namespaceOverride allows to override the destination namespace for Cilium resources. This property allows to use Cilium as part of an Umbrella Chart with different targets. | | nat.mapStatsEntries | int | `32` | Number of the top-k SNAT map connections to track in Cilium statedb. | | nat.mapStatsInterval | string | `"30s"` | Interval between how often SNAT map is counted for stats. | | nat46x64Gateway | object | `{"enabled":false}` | Configure standalone NAT46/NAT64 gateway | | nat46x64Gateway.enabled | bool | `false` | Enable RFC6052-prefixed translation | | nodeIPAM.enabled | bool | `false` | Configure Node IPAM ref: https://docs.cilium.io/en/stable/network/node-ipam/ | -| nodePort | object | `{"addresses":null,"autoProtectPortRange":true,"bindProtection":true,"enableHealthCheck":true,"enableHealthCheckLoadBalancerIP":false}` | Configure N-S k8s service loadbalancing | +| nodePort | object | `{"addresses":null,"autoProtectPortRange":true,"bindProtection":true,"enableHealthCheck":true,"enableHealthCheckLoadBalancerIP":false,"enabled":false}` | Configure N-S k8s service loadbalancing | | nodePort.addresses | string | `nil` | List of CIDRs for choosing which IP addresses assigned to native devices are used for NodePort load-balancing. By default this is empty and the first suitable, preferably private, IPv4 and IPv6 address assigned to each device is used. Example: addresses: ["192.168.1.0/24", "2001::/64"] | | nodePort.autoProtectPortRange | bool | `true` | Append NodePort range to ip_local_reserved_ports if clash with ephemeral ports is detected. | | nodePort.bindProtection | bool | `true` | Set to true to prevent applications binding to service ports. | | nodePort.enableHealthCheck | bool | `true` | Enable healthcheck nodePort server for NodePort services | | nodePort.enableHealthCheckLoadBalancerIP | bool | `false` | Enable access of the healthcheck nodePort on the LoadBalancerIP. Needs EnableHealthCheck to be enabled | +| nodePort.enabled | bool | `false` | Enable the Cilium NodePort service implementation. | | nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node selector for cilium-agent. | | nodeSelectorLabels | bool | `false` | Enable/Disable use of node label based identity | | nodeinit.affinity | object | `{}` | Affinity for cilium-nodeinit | @@ -857,7 +766,7 @@ contributors across the globe, there is almost always someone available to help. | nodeinit.extraEnv | list | `[]` | Additional nodeinit environment variables. | | nodeinit.extraVolumeMounts | list | `[]` | Additional nodeinit volumeMounts. | | nodeinit.extraVolumes | list | `[]` | Additional nodeinit volumes. | -| nodeinit.image | object | `{"digest":"sha256:50b9cf9c280096b59b80d2fc8ee6638facef79ac18998a22f0cbc40d5d28c16f","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/startup-script","tag":"1763560095-8f36c34","useDigest":true}` | node-init image. | +| nodeinit.image | object | `{"digest":"sha256:5bdca3c2dec2c79f58d45a7a560bf1098c2126350c901379fe850b7f78d3d757","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/startup-script","tag":"1755531540-60ee83e","useDigest":true}` | node-init image. | | nodeinit.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for nodeinit pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | nodeinit.podAnnotations | object | `{}` | Annotations to be added to node-init pods. | | nodeinit.podLabels | object | `{}` | Labels to be added to node-init pods. | @@ -870,7 +779,6 @@ contributors across the globe, there is almost always someone available to help. | nodeinit.startup | object | `{"postScript":"","preScript":""}` | startup offers way to customize startup nodeinit script (pre and post position) | | nodeinit.tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for nodeinit scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | nodeinit.updateStrategy | object | `{"type":"RollingUpdate"}` | node-init update strategy | -| nodeinit.waitForCloudInit | bool | `false` | wait for Cloud init to finish on the host and assume the node has cloud init installed | | operator.affinity | object | `{"podAntiAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"io.cilium/app":"operator"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-operator | | operator.annotations | object | `{}` | Annotations to be added to all top-level cilium-operator objects (resources under templates/cilium-operator) | | operator.dashboards | object | `{"annotations":{},"enabled":false,"label":"grafana_dashboard","labelValue":"1","namespace":null}` | Grafana dashboards for cilium-operator grafana can import dashboards based on the label and value ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards | @@ -885,7 +793,7 @@ contributors across the globe, there is almost always someone available to help. | operator.hostNetwork | bool | `true` | HostNetwork setting | | operator.identityGCInterval | string | `"15m0s"` | Interval for identity garbage collection. | | operator.identityHeartbeatTimeout | string | `"30m0s"` | Timeout for identity heartbeats. | -| operator.image | object | `{"alibabacloudDigest":"sha256:176321a65123373ff8c7823b25183102cbad98375e8d6c80b96d68b6e8491103","awsDigest":"sha256:a53dcbfb77282bf2ddd3abbe60f6d49762e7c1389a36cb35b71d504644a56640","azureDigest":"sha256:699c1571a3df1a98882ee13610d47cffb7b34ee7e8d276096db798a5f6c7e4cb","genericDigest":"sha256:205b09b0ed6accbf9fe688d312a9f0fcfc6a316fc081c23fbffb472af5dd62cd","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.19.3","useDigest":true}` | cilium-operator image. | +| operator.image | object | `{"alibabacloudDigest":"sha256:212c4cbe27da3772bcb952b8f8cbaa0b0eef72488b52edf90ad2b32072a3ca4c","awsDigest":"sha256:47dbc1a5bd483fec170dab7fb0bf2cca3585a4893675b0324d41d97bac8be5eb","azureDigest":"sha256:a57aff47aeb32eccfedaa2a49d1af984d996d6d6de79609c232e0c4cf9ce97a1","genericDigest":"sha256:34a827ce9ed021c8adf8f0feca131f53b3c54a3ef529053d871d0347ec4d69af","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/operator","suffix":"","tag":"v1.18.6","useDigest":true}` | cilium-operator image. | | operator.nodeGCInterval | string | `"5m0s"` | Interval for cilium node garbage collection. | | operator.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for cilium-operator pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | operator.podAnnotations | object | `{}` | Annotations to be added to cilium-operator pods | @@ -896,12 +804,10 @@ contributors across the globe, there is almost always someone available to help. | operator.podLabels | object | `{}` | Labels to be added to cilium-operator pods | | operator.podSecurityContext | object | `{"seccompProfile":{"type":"RuntimeDefault"}}` | Security context to be added to cilium-operator pods | | operator.pprof.address | string | `"localhost"` | Configure pprof listen address for cilium-operator | -| operator.pprof.blockProfileRate | int | `0` | Enable goroutine blocking profiling for cilium-operator and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) | | operator.pprof.enabled | bool | `false` | Enable pprof for cilium-operator | -| operator.pprof.mutexProfileFraction | int | `0` | Enable mutex contention profiling for cilium-operator and set the fraction of sampled events (set to 1 to sample all events) | | operator.pprof.port | int | `6061` | Configure pprof listen port for cilium-operator | | operator.priorityClassName | string | `""` | The priority class to use for cilium-operator | -| operator.prometheus | object | `{"enabled":true,"metricsService":false,"port":9963,"serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","jobLabel":"","labels":{},"metricRelabelings":null,"relabelings":null,"scrapeTimeout":null},"tls":{"enabled":false,"server":{"existingSecret":"","mtls":{"enabled":false}}}}` | Enable prometheus metrics for cilium-operator on the configured port at /metrics | +| operator.prometheus | object | `{"enabled":true,"metricsService":false,"port":9963,"serviceMonitor":{"annotations":{},"enabled":false,"interval":"10s","jobLabel":"","labels":{},"metricRelabelings":null,"relabelings":null,"scrapeTimeout":null}}` | Enable prometheus metrics for cilium-operator on the configured port at /metrics | | operator.prometheus.serviceMonitor.annotations | object | `{}` | Annotations to add to ServiceMonitor cilium-operator | | operator.prometheus.serviceMonitor.enabled | bool | `false` | Enable service monitors. This requires the prometheus CRDs to be available (see https://github.com/prometheus-operator/prometheus-operator/blob/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml) | | operator.prometheus.serviceMonitor.interval | string | `"10s"` | Interval for scrape metrics. | @@ -910,8 +816,6 @@ contributors across the globe, there is almost always someone available to help. | operator.prometheus.serviceMonitor.metricRelabelings | string | `nil` | Metrics relabeling configs for the ServiceMonitor cilium-operator | | operator.prometheus.serviceMonitor.relabelings | string | `nil` | Relabeling configs for the ServiceMonitor cilium-operator | | operator.prometheus.serviceMonitor.scrapeTimeout | string | `nil` | Timeout after which scrape is considered to be failed. | -| operator.prometheus.tls | object | `{"enabled":false,"server":{"existingSecret":"","mtls":{"enabled":false}}}` | TLS configuration for Prometheus | -| operator.prometheus.tls.server.existingSecret | string | `""` | Name of the Secret containing the certificate, key and CA files for the Prometheus server. | | operator.removeNodeTaints | bool | `true` | Remove Cilium node taint from Kubernetes nodes that have a healthy Cilium pod running. | | operator.replicas | int | `2` | Number of replicas to run for the cilium-operator deployment | | operator.resources | object | `{}` | cilium-operator resource limits & requests ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | @@ -924,30 +828,25 @@ contributors across the globe, there is almost always someone available to help. | operator.topologySpreadConstraints | list | `[]` | Pod topology spread constraints for cilium-operator | | operator.unmanagedPodWatcher.intervalSeconds | int | `15` | Interval, in seconds, to check if there are any pods that are not managed by Cilium. | | operator.unmanagedPodWatcher.restart | bool | `true` | Restart any pod that are not managed by Cilium. | -| operator.unmanagedPodWatcher.selector | string | `nil` | Selector for pods that should be restarted when not managed by Cilium. If not set, defaults to built-in selector "k8s-app=kube-dns". Set to empty string to select all pods. @schema type: [null, string] @schema | | operator.updateStrategy | object | `{"rollingUpdate":{"maxSurge":"25%","maxUnavailable":"50%"},"type":"RollingUpdate"}` | cilium-operator update strategy | | pmtuDiscovery.enabled | bool | `false` | Enable path MTU discovery to send ICMP fragmentation-needed replies to the client. | -| pmtuDiscovery.packetizationLayerPMTUDMode | string | `"blackhole"` | Enable kernel probing path MTU discovery for Pods which uses different message sizes to search for correct MTU value. Valid values are: always, blackhole, disabled and unset (or empty). If value is 'unset' or left empty then will not try to override setting. | | podAnnotations | object | `{}` | Annotations to be added to agent pods | | podLabels | object | `{}` | Labels to be added to agent pods | | podSecurityContext | object | `{"appArmorProfile":{"type":"Unconfined"},"seccompProfile":{"type":"Unconfined"}}` | Security Context for cilium-agent pods. | | podSecurityContext.appArmorProfile | object | `{"type":"Unconfined"}` | AppArmorProfile options for the `cilium-agent` and init containers | | policyCIDRMatchMode | string | `nil` | policyCIDRMatchMode is a list of entities that may be selected by CIDR selector. The possible value is "nodes". | -| policyDenyResponse | string | `"none"` | Configure what the response should be to pod egress traffic denied by network policy. Possible values: - none (default) - icmp | | policyEnforcementMode | string | `"default"` | The agent can be put into one of the three policy enforcement modes: default, always and never. ref: https://docs.cilium.io/en/stable/security/policy/intro/#policy-enforcement-modes | | pprof.address | string | `"localhost"` | Configure pprof listen address for cilium-agent | -| pprof.blockProfileRate | int | `0` | Enable goroutine blocking profiling for cilium-agent and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) | | pprof.enabled | bool | `false` | Enable pprof for cilium-agent | -| pprof.mutexProfileFraction | int | `0` | Enable mutex contention profiling for cilium-agent and set the fraction of sampled events (set to 1 to sample all events) | | pprof.port | int | `6060` | Configure pprof listen port for cilium-agent | | preflight.affinity | object | `{"podAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":[{"labelSelector":{"matchLabels":{"k8s-app":"cilium"}},"topologyKey":"kubernetes.io/hostname"}]}}` | Affinity for cilium-preflight | | preflight.annotations | object | `{}` | Annotations to be added to all top-level preflight objects (resources under templates/cilium-preflight) | | preflight.enabled | bool | `false` | Enable Cilium pre-flight resources (required for upgrade) | -| preflight.envoy.image | object | `{"digest":"sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa","useDigest":true}` | Envoy pre-flight image. | +| preflight.envoy.image | object | `{"digest":"sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium-envoy","tag":"v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9","useDigest":true}` | Envoy pre-flight image. | | preflight.extraEnv | list | `[]` | Additional preflight environment variables. | | preflight.extraVolumeMounts | list | `[]` | Additional preflight volumeMounts. | | preflight.extraVolumes | list | `[]` | Additional preflight volumes. | -| preflight.image | object | `{"digest":"sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.19.3","useDigest":true}` | Cilium pre-flight image. | +| preflight.image | object | `{"digest":"sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4","override":null,"pullPolicy":"IfNotPresent","repository":"quay.io/cilium/cilium","tag":"v1.18.6","useDigest":true}` | Cilium pre-flight image. | | preflight.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for preflight pod assignment ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | | preflight.podAnnotations | object | `{}` | Annotations to be added to preflight pods | | preflight.podDisruptionBudget.enabled | bool | `false` | enable PodDisruptionBudget ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | @@ -991,37 +890,24 @@ contributors across the globe, there is almost always someone available to help. | sctp | object | `{"enabled":false}` | SCTP Configuration Values | | sctp.enabled | bool | `false` | Enable SCTP support. NOTE: Currently, SCTP support does not support rewriting ports or multihoming. | | secretsNamespaceAnnotations | object | `{}` | Annotations to be added to all cilium-secret namespaces (resources under templates/cilium-secrets-namespace) | -| secretsNamespaceLabels | object | `{}` | Labels to be added to all cilium-secret namespaces (resources under templates/cilium-secrets-namespace) | | securityContext.allowPrivilegeEscalation | bool | `false` | disable privilege escalation | | securityContext.capabilities.applySysctlOverwrites | list | `["SYS_ADMIN","SYS_CHROOT","SYS_PTRACE"]` | capabilities for the `apply-sysctl-overwrites` init container | -| securityContext.capabilities.ciliumAgent | list | `["CHOWN","KILL","NET_ADMIN","NET_RAW","IPC_LOCK","SYS_MODULE","SYS_ADMIN","SYS_RESOURCE","DAC_OVERRIDE","FOWNER","SETGID","SETUID","SYSLOG"]` | Capabilities for the `cilium-agent` container | +| securityContext.capabilities.ciliumAgent | list | `["CHOWN","KILL","NET_ADMIN","NET_RAW","IPC_LOCK","SYS_MODULE","SYS_ADMIN","SYS_RESOURCE","DAC_OVERRIDE","FOWNER","SETGID","SETUID"]` | Capabilities for the `cilium-agent` container | | securityContext.capabilities.cleanCiliumState | list | `["NET_ADMIN","SYS_MODULE","SYS_ADMIN","SYS_RESOURCE"]` | Capabilities for the `clean-cilium-state` init container | | securityContext.capabilities.mountCgroup | list | `["SYS_ADMIN","SYS_CHROOT","SYS_PTRACE"]` | Capabilities for the `mount-cgroup` init container | | securityContext.privileged | bool | `false` | Run the pod with elevated privileges | | securityContext.seLinuxOptions | object | `{"level":"s0","type":"spc_t"}` | SELinux options for the `cilium-agent` and init containers | | serviceAccounts | object | Component's fully qualified name. | Define serviceAccount names for components. | | serviceAccounts.clustermeshcertgen | object | `{"annotations":{},"automount":true,"create":true,"name":"clustermesh-apiserver-generate-certs"}` | Clustermeshcertgen is used if clustermesh.apiserver.tls.auto.method=cronJob | -| serviceAccounts.corednsMCSAPI | object | `{"annotations":{},"automount":true,"create":true,"name":"cilium-coredns-mcsapi-autoconfig"}` | CorednsMCSAPI is used if clustermesh.mcsapi.corednsAutoConfigure.enabled=true | | serviceAccounts.hubblecertgen | object | `{"annotations":{},"automount":true,"create":true,"name":"hubble-generate-certs"}` | Hubblecertgen is used if hubble.tls.auto.method=cronJob | | serviceAccounts.nodeinit.enabled | bool | `false` | Enabled is temporary until https://github.com/cilium/cilium-cli/issues/1396 is implemented. Cilium CLI doesn't create the SAs for node-init, thus the workaround. Helm is not affected by this issue. Name and automount can be configured, if enabled is set to true. Otherwise, they are ignored. Enabled can be removed once the issue is fixed. Cilium-nodeinit DS must also be fixed. | -| serviceAccounts.ztunnel | object | `{"annotations":{},"automount":false,"create":true,"name":"ztunnel-cilium"}` | Ztunnel is used if encryption.type=ztunnel | | serviceNoBackendResponse | string | `"reject"` | Configure what the response should be to traffic for a service without backends. Possible values: - reject (default) - drop | | sleepAfterInit | bool | `false` | Do not run Cilium agent when running with clean mode. Useful to completely uninstall Cilium as it will stop Cilium from starting and create artifacts in the node. | | socketLB | object | `{"enabled":false}` | Configure socket LB | | socketLB.enabled | bool | `false` | Enable socket LB | -| standaloneDnsProxy | object | `{"annotations":{},"automountServiceAccountToken":false,"debug":false,"enabled":false,"image":{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"","tag":"","useDigest":true},"nodeSelector":{"kubernetes.io/os":"linux"},"rollOutPods":false,"serverPort":10095,"tolerations":[],"updateStrategy":{"rollingUpdate":{"maxSurge":2,"maxUnavailable":0},"type":"RollingUpdate"}}` | Standalone DNS Proxy Configuration Note: The standalone DNS proxy uses the agent's dnsProxy.* configuration for DNS settings (proxyPort, enableDnsCompression) to ensure consistency. | -| standaloneDnsProxy.annotations | object | `{}` | Standalone DNS proxy annotations | -| standaloneDnsProxy.automountServiceAccountToken | bool | `false` | Standalone DNS proxy auto mount service account token | -| standaloneDnsProxy.debug | bool | `false` | Standalone DNS proxy debug mode | -| standaloneDnsProxy.enabled | bool | `false` | Enable standalone DNS proxy (alpha feature) | -| standaloneDnsProxy.image | object | `{"digest":"","override":null,"pullPolicy":"IfNotPresent","repository":"","tag":"","useDigest":true}` | Standalone DNS proxy image | -| standaloneDnsProxy.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Standalone DNS proxy Node Selector | -| standaloneDnsProxy.rollOutPods | bool | `false` | Roll out Standalone DNS proxy automatically when configmap is updated. | -| standaloneDnsProxy.serverPort | int | `10095` | Standalone DNS proxy server port | -| standaloneDnsProxy.tolerations | list | `[]` | Standalone DNS proxy tolerations | -| standaloneDnsProxy.updateStrategy | object | `{"rollingUpdate":{"maxSurge":2,"maxUnavailable":0},"type":"RollingUpdate"}` | Standalone DNS proxy update strategy | | startupProbe.failureThreshold | int | `300` | failure threshold of startup probe. Allow Cilium to take up to 600s to start up (300 attempts with 2s between attempts). | | startupProbe.periodSeconds | int | `2` | interval between checks of the startup probe | +| svcSourceRangeCheck | bool | `true` | Enable check of service source ranges (currently, only for LoadBalancer). | | synchronizeK8sNodes | bool | `true` | Synchronize Kubernetes nodes to kvstore and perform CNP GC. | | sysctlfix | object | `{"enabled":true}` | Configure sysctl override described in #20072. | | sysctlfix.enabled | bool | `true` | Enable the sysctl override. When enabled, the init container will mount the /proc of the host so that the `sysctlfix` utility can execute. | @@ -1043,12 +929,11 @@ contributors across the globe, there is almost always someone available to help. | tls.secretsNamespace | object | `{"create":true,"name":"cilium-secrets"}` | Configures where secrets used in CiliumNetworkPolicies will be looked for | | tls.secretsNamespace.create | bool | `true` | Create secrets namespace for TLS Interception secrets. | | tls.secretsNamespace.name | string | `"cilium-secrets"` | Name of TLS Interception secret namespace. | -| tmpVolume | object | `{}` | Configure temporary volume for cilium-agent | | tolerations | list | `[{"operator":"Exists"}]` | Node tolerations for agent scheduling to nodes with taints ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | | tunnelPort | int | Port 8472 for VXLAN, Port 6081 for Geneve | Configure VXLAN and Geneve tunnel port. | | tunnelProtocol | string | `"vxlan"` | Tunneling protocol to use in tunneling mode and for ad-hoc tunnels. Possible values: - "" - vxlan - geneve | | tunnelSourcePortRange | string | 0-0 to let the kernel driver decide the range | Configure VXLAN and Geneve tunnel source port range hint. | -| underlayProtocol | string | `"ipv4"` | IP family for the underlay. Possible values: - "ipv4" - "ipv6" | +| underlayProtocol | string | `"ipv4"` | IP family for the underlay. | | updateStrategy | object | `{"rollingUpdate":{"maxUnavailable":2},"type":"RollingUpdate"}` | Cilium agent update strategy | | upgradeCompatibility | string | `nil` | upgradeCompatibility helps users upgrading to ensure that the configMap for Cilium will not change critical values to ensure continued operation This flag is not required for new installations. For example: '1.7', '1.8', '1.9' | | vtep.cidr | string | `""` | A space separated list of VTEP device CIDRs, for example "1.1.1.0/24 1.1.2.0/24" | diff --git a/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml b/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml index 90ebf4ac..52439049 100644 --- a/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml +++ b/packages/system/cilium/charts/cilium/files/cilium-envoy/configmap/bootstrap-config.yaml @@ -167,8 +167,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -185,8 +183,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -208,8 +204,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -226,8 +220,6 @@ staticResources: circuitBreakers: thresholds: - maxRetries: {{ .Values.envoy.maxConcurrentRetries }} - maxConnections: {{ .Values.envoy.clusterMaxConnections }} - maxRequests: {{ .Values.envoy.clusterMaxRequests }} lbPolicy: "CLUSTER_PROVIDED" typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -300,7 +292,7 @@ overloadManager: - name: "envoy.resource_monitors.global_downstream_max_connections" typedConfig: "@type": "type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig" - max_active_downstream_connections: "{{ .Values.envoy.maxGlobalDownstreamConnections }}" + max_active_downstream_connections: "50000" applicationLogConfig: logFormat: {{- if .Values.envoy.log.format_json }} @@ -312,4 +304,3 @@ admin: address: pipe: path: "/var/run/cilium/envoy/sockets/admin.sock" - mode: 0660 diff --git a/packages/system/cilium/charts/cilium/files/nodeinit/startup.bash b/packages/system/cilium/charts/cilium/files/nodeinit/startup.bash index 68e6b50b..aa63cac8 100644 --- a/packages/system/cilium/charts/cilium/files/nodeinit/startup.bash +++ b/packages/system/cilium/charts/cilium/files/nodeinit/startup.bash @@ -156,14 +156,6 @@ fi iptables -w -t nat -D POSTROUTING -m comment --comment "ip-masq: ensure nat POSTROUTING directs all non-LOCAL destination traffic to our custom IP-MASQ chain" -m addrtype ! --dst-type LOCAL -j IP-MASQ || true {{- end }} -{{- if .Values.nodeinit.waitForCloudInit }} -echo "Waiting for cloud-init..." -if command -v cloud-init >/dev/null 2>&1; then - cloud-init status --wait - echo "cloud-init completed!" -fi -{{- end }} - {{- if not (eq .Values.nodeinit.bootstrapFile "") }} mkdir -p {{ .Values.nodeinit.bootstrapFile | dir | quote }} date > {{ .Values.nodeinit.bootstrapFile | quote }} diff --git a/packages/system/cilium/charts/cilium/templates/_extensions.tpl b/packages/system/cilium/charts/cilium/templates/_extensions.tpl index 8c0e5c20..bd8ba80b 100644 --- a/packages/system/cilium/charts/cilium/templates/_extensions.tpl +++ b/packages/system/cilium/charts/cilium/templates/_extensions.tpl @@ -21,24 +21,6 @@ dnsPolicy: {{ .Values.dnsPolicy }} {{- end }} {{- end }} -{{/* -Allow packagers to add extra volumes to cilium-operator. -*/}} -{{- define "cilium-operator.volumes.extra" }} -{{- end }} - -{{- define "cilium-operator.volumeMounts.extra" }} -{{- end }} - -{{/* -Allow packagers to set securityContext for cilium-operator. -*/}} -{{- define "cilium.operator.securityContext" }} -{{- with .Values.operator.securityContext }} -{{ toYaml . }} -{{- end }} -{{- end }} - {{/* Intentionally empty to allow downstream chart packagers to add extra containers to hubble-relay without having to modify the deployment manifest @@ -90,87 +72,3 @@ Allow packagers to add extra configuration to certgen. */}} {{- define "certgen.config.extra" -}} {{- end }} - -{{/* -Allow packagers to add extra arguments to the clustermesh-apiserver apiserver container. -*/}} -{{- define "clustermesh.apiserver.args.extra" -}} -{{- end }} - -{{/* -Allow packagers to add extra arguments to the clustermesh-apiserver kvstoremesh container. -*/}} -{{- define "clustermesh.kvstoremesh.args.extra" -}} -{{- end }} - -{{/* -Allow packagers to add init containers to the cilium-envoy pods. -*/}} -{{- define "envoy.initContainers" -}} -{{- end }} - -{{/* -Allow packagers to add extra args to the cilium-envoy container. -*/}} -{{- define "envoy.args.extra" -}} -{{- end }} - -{{/* -Allow packagers to add extra env vars to the cilium-envoy container. -*/}} -{{- define "envoy.env.extra" -}} -{{- end }} - -{{/* -Allow packagers to add extra volume mounts to the cilium-envoy container. -*/}} -{{- define "envoy.volumeMounts.extra" -}} -{{- end }} - -{{/* -Allow packagers to add extra host path mounts to the cilium-envoy container. -*/}} -{{- define "envoy.hostPathMounts.extra" -}} -{{- end }} - - -{{/* -Allow packagers to define set of ports for cilium-envoy container. -The template needs to allow overriding ports spec not just adding. -*/}} -{{- define "envoy.ports" -}} - {{- if .Values.envoy.prometheus.enabled }} - ports: - - name: envoy-metrics - containerPort: {{ .Values.envoy.prometheus.port }} - hostPort: {{ .Values.envoy.prometheus.port }} - protocol: TCP - {{- if and .Values.envoy.debug.admin.enabled .Values.envoy.debug.admin.port }} - - name: envoy-admin - containerPort: {{ .Values.envoy.debug.admin.port }} - hostPort: {{ .Values.envoy.debug.admin.port }} - protocol: TCP - {{- end }} - {{- end }} -{{- end }} - -{{/* -Allow packagers to define update strategy for cilium-envoy pods. -*/}} -{{- define "envoy.updateStrategy" -}} -{{- with .Values.envoy.updateStrategy }} -updateStrategy: - {{- toYaml . | trim | nindent 2 }} - {{- end }} -{{- end }} - -{{/* -Allow packagers to define affinity for cilium-envoy pods. -*/}} -{{- define "envoy.affinity" -}} -{{- with .Values.envoy.affinity }} -affinity: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- end }} - diff --git a/packages/system/cilium/charts/cilium/templates/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/_helpers.tpl index e90aa482..ba91c353 100644 --- a/packages/system/cilium/charts/cilium/templates/_helpers.tpl +++ b/packages/system/cilium/charts/cilium/templates/_helpers.tpl @@ -131,16 +131,12 @@ To override the namespace and configMap when using `auto`: {{- define "k8sServiceHost" }} {{- $configmapName := default "cluster-info" .Values.k8sServiceLookupConfigMapName }} {{- $configmapNamespace := default "kube-public" .Values.k8sServiceLookupNamespace }} - {{- if eq .Values.k8sServiceHost "auto" }} + {{- if and (eq .Values.k8sServiceHost "auto") (lookup "v1" "ConfigMap" $configmapNamespace $configmapName) }} {{- $configmap := (lookup "v1" "ConfigMap" $configmapNamespace $configmapName) }} - {{- if $configmap }} - {{- $kubeconfig := get $configmap.data "kubeconfig" }} - {{- $k8sServer := get ($kubeconfig | fromYaml) "clusters" | mustFirst | dig "cluster" "server" "" }} - {{- $uri := (split "https://" $k8sServer)._1 | trim }} - {{- (split ":" $uri)._0 | quote }} - {{- else }} - {{- fail (printf "ConfigMap %s/%s not found, please create it or set k8sServiceHost to a valid value" $configmapNamespace $configmapName) }} - {{- end }} + {{- $kubeconfig := get $configmap.data "kubeconfig" }} + {{- $k8sServer := get ($kubeconfig | fromYaml) "clusters" | mustFirst | dig "cluster" "server" "" }} + {{- $uri := (split "https://" $k8sServer)._1 | trim }} + {{- (split ":" $uri)._0 | quote }} {{- else }} {{- .Values.k8sServiceHost | quote }} {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml index 57b13447..eaca204e 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/clusterrole.yaml @@ -94,6 +94,7 @@ rules: - cilium.io resources: - ciliumloadbalancerippools + - ciliumbgppeeringpolicies - ciliumbgpnodeconfigs - ciliumbgpadvertisements - ciliumbgppeerconfigs diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml index fff1b384..c706da51 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/daemonset.yaml @@ -10,7 +10,6 @@ {{- $kubeProxyReplacement := (coalesce .Values.kubeProxyReplacement "false") -}} {{- $envoyDS := eq (include "envoyDaemonSetEnabled" .) "true" -}} -{{- $buildDaemonConfig := or (kindIs "invalid" .Values.daemon.configSources) (not (regexMatch "^config-map:[^,]+$" .Values.daemon.configSources)) -}} --- apiVersion: apps/v1 @@ -57,6 +56,19 @@ spec: # ensure pods roll when configmap updates cilium.io/cilium-configmap-checksum: {{ include (print $.Template.BasePath "/cilium-configmap.yaml") . | sha256sum | quote }} {{- end }} + {{- if not .Values.securityContext.privileged }} + {{- if semverCompare "<1.30.0" (printf "%d.%d.0" (semver .Capabilities.KubeVersion.Version).Major (semver .Capabilities.KubeVersion.Version).Minor) }} + # Set app AppArmor's profile to "unconfined". The value of this annotation + # can be modified as long users know which profiles they have available + # in AppArmor. + container.apparmor.security.beta.kubernetes.io/cilium-agent: "unconfined" + container.apparmor.security.beta.kubernetes.io/clean-cilium-state: "unconfined" + {{- if .Values.cgroup.autoMount.enabled }} + container.apparmor.security.beta.kubernetes.io/mount-cgroup: "unconfined" + container.apparmor.security.beta.kubernetes.io/apply-sysctl-overwrites: "unconfined" + {{- end }} + {{- end }} + {{- end }} {{- with .Values.podAnnotations }} {{- toYaml . | nindent 8 }} {{- end }} @@ -122,7 +134,7 @@ spec: httpGet: host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} path: /healthz - port: health + port: {{ .Values.healthPort }} scheme: HTTP httpHeaders: - name: "brief" @@ -142,7 +154,7 @@ spec: httpGet: host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} path: /healthz - port: health + port: {{ .Values.healthPort }} scheme: HTTP httpHeaders: - name: "brief" @@ -165,7 +177,7 @@ spec: httpGet: host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} path: /healthz - port: health + port: {{ .Values.healthPort }} scheme: HTTP httpHeaders: - name: "brief" @@ -238,17 +250,12 @@ spec: resources: {{- toYaml . | trim | nindent 10 }} {{- end }} + {{- if or .Values.prometheus.enabled (or .Values.hubble.metrics.enabled .Values.hubble.metrics.dynamic.enabled) }} ports: - - name: health - containerPort: {{ .Values.healthPort }} - hostPort: {{ .Values.healthPort }} - protocol: TCP - {{- if .Values.hubble.enabled }} - name: peer-service containerPort: {{ .Values.hubble.peerService.targetPort }} hostPort: {{ .Values.hubble.peerService.targetPort }} protocol: TCP - {{- end }} {{- if .Values.prometheus.enabled }} - name: prometheus containerPort: {{ .Values.prometheus.port }} @@ -273,6 +280,7 @@ spec: hostPort: {{ .Values.hubble.metrics.port }} protocol: TCP {{- end }} + {{- end }} securityContext: {{- if .Values.securityContext.privileged }} privileged: true @@ -367,10 +375,6 @@ spec: - name: cilium-ipsec-secrets mountPath: {{ .Values.encryption.ipsec.mountPath }} {{- end }} - {{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") }} - - name: cilium-ztunnel-secrets - mountPath: /etc/ztunnel - {{- end }} {{- if .Values.kubeConfigPath }} - name: kube-config mountPath: {{ .Values.kubeConfigPath }} @@ -386,14 +390,8 @@ spec: mountPath: /var/lib/cilium/tls/hubble readOnly: true {{- end }} - {{- if $buildDaemonConfig }} - name: tmp mountPath: /tmp - {{- else }} - - name: cilium-config-path - mountPath: /tmp/cilium/config-map - readOnly: true - {{- end }} {{- range .Values.extraHostPathMounts }} - name: {{ .name }} mountPath: {{ .mountPath }} @@ -449,7 +447,6 @@ spec: {{- toYaml .Values.extraContainers | nindent 6 }} {{- end }} initContainers: - {{- if $buildDaemonConfig }} - name: config image: {{ include "cilium.image" .Values.image | quote }} imagePullPolicy: {{ .Values.image.pullPolicy }} @@ -516,17 +513,6 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} terminationMessagePolicy: FallbackToLogsOnError - securityContext: - {{- if .Values.securityContext.privileged }} - privileged: true - {{- else }} - capabilities: - add: - - NET_ADMIN - drop: - - ALL - {{- end}} - {{- end }} {{- if .Values.cgroup.autoMount.enabled }} # Required to mount cgroup2 filesystem on the underlying Kubernetes node. # We use nsenter command with host's cgroup and mount namespaces enabled. @@ -538,15 +524,12 @@ spec: value: {{ .Values.cgroup.hostRoot }} - name: BIN_PATH value: {{ .Values.cni.binPath }} - {{- if .Values.cgroup.autoMount.resources }} + {{- with .Values.cgroup.autoMount.resources }} resources: - {{- toYaml .Values.cgroup.autoMount.resources | trim | nindent 10 }} - {{- else if .Values.initResources }} - resources: - {{- toYaml .Values.initResources | trim | nindent 10 }} + {{- toYaml . | trim | nindent 10 }} {{- end }} command: - - bash + - sh - -ec # The statically linked Go program binary is invoked to avoid any # dependency on utilities like sh and mount that can be missing on certain @@ -592,7 +575,7 @@ spec: - name: BIN_PATH value: {{ .Values.cni.binPath }} command: - - bash + - sh - -ec # The statically linked Go program binary is invoked to avoid any # dependency on utilities like sh that can be missing on certain @@ -660,7 +643,7 @@ spec: {{- toYaml . | trim | nindent 10 }} {{- end }} command: - - bash + - sh - -c - | until test -s {{ (print "/tmp/cilium-bootstrap.d/" (.Values.nodeinit.bootstrapFile | base)) | quote }}; do @@ -838,7 +821,7 @@ spec: {{- end }} {{- if and .Values.clustermesh.config.enabled (not (and .Values.clustermesh.useAPIServer .Values.clustermesh.apiserver.kvstoremesh.enabled )) }} hostAliases: - {{- range $_, $cluster := (include "clustermesh-clusters" . | fromJson) }} + {{- range $cluster := .Values.clustermesh.config.clusters }} {{- range $ip := $cluster.ips }} - ip: {{ $ip }} hostnames: [ "{{ $cluster.name }}.{{ $.Values.clustermesh.config.domain }}" ] @@ -846,20 +829,9 @@ spec: {{- end }} {{- end }} volumes: - {{- if $buildDaemonConfig }} - # For sharing configuration between the "config" initContainer and the agent + # For sharing configuration between the "config" initContainer and the agent - name: tmp - {{- if .Values.tmpVolume }} - {{- toYaml .Values.tmpVolume | nindent 8 }} - {{- else }} emptyDir: {} - {{- end }} - {{- else }} - # To read the configuration from the config map - - name: cilium-config-path - configMap: - name: {{ trimPrefix "config-map:" .Values.daemon.configSources }} - {{- end }} # To keep state between restarts / upgrades - name: cilium-run hostPath: @@ -1020,11 +992,6 @@ spec: secret: secretName: {{ .Values.encryption.ipsec.secretName }} {{- end }} - {{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") }} - - name: cilium-ztunnel-secrets - secret: - secretName: cilium-ztunnel-secrets - {{- end }} {{- if .Values.cni.configMap }} - name: cni-configuration configMap: diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml index df60d89b..89266e0d 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/role.yaml @@ -120,7 +120,7 @@ rules: - watch {{- end}} -{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create $readSecretsOnlyFromSecretsNamespace .Values.tls.secretsNamespace.name }} +{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create $readSecretsOnlyFromSecretsNamespace .Values.tls.secretsNamespace.name }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role diff --git a/packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml b/packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml index 5caf2f15..c76350b3 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-agent/rolebinding.yaml @@ -126,7 +126,7 @@ subjects: namespace: {{ include "cilium.namespace" . }} {{- end}} -{{- if and .Values.agent (not .Values.preflight.enabled) .Values.serviceAccounts.cilium.create $readSecretsOnlyFromSecretsNamespace .Values.tls.secretsNamespace.name }} +{{- if and (not .Values.preflight.enabled) $readSecretsOnlyFromSecretsNamespace .Values.tls.secretsNamespace.name }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding diff --git a/packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml b/packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml index 91569863..7dd15d02 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-ca-secret.yaml @@ -11,13 +11,8 @@ kind: Secret metadata: name: {{ .commonCASecretName }} namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} - cilium.io/helm-template-non-idempotent: "true" - {{- with .Values.nonIdempotentAnnotations }} - annotations: + labels: {{- toYaml . | nindent 4 }} {{- end }} data: diff --git a/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml b/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml index 5d76944d..a9bb1cd9 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-configmap.yaml @@ -33,6 +33,12 @@ {{- end }} {{- $defaultBpfCtTcpMax = 0 -}} {{- $defaultBpfCtAnyMax = 0 -}} + {{- $defaultKubeProxyReplacement = "probe" -}} +{{- end -}} + +{{- /* Default values when 1.9 was initially deployed */ -}} +{{- if semverCompare ">=1.9" (default "1.9" .Values.upgradeCompatibility) -}} + {{- $defaultKubeProxyReplacement = "probe" -}} {{- end -}} {{- /* Default values when 1.10 was initially deployed */ -}} @@ -46,6 +52,7 @@ {{- if .Values.azure.enabled }} {{- $azureUsePrimaryAddress = "false" -}} {{- end }} + {{- $defaultKubeProxyReplacement = "disabled" -}} {{- $defaultDNSProxyEnableTransparentMode = "true" -}} {{- end -}} @@ -64,10 +71,6 @@ {{- end }} {{- end -}} {{- $ipam := (coalesce .Values.ipam.mode $defaultIPAM) -}} -{{- if .Values.eni.enabled }} - {{- $ipam = "eni" -}} -{{- end }} - {{- $bpfCtTcpMax := (coalesce .Values.bpf.ctTcpMax $defaultBpfCtTcpMax) -}} {{- $bpfCtAnyMax := (coalesce .Values.bpf.ctAnyMax $defaultBpfCtAnyMax) -}} {{- $stringValueKPR := (toString .Values.kubeProxyReplacement) -}} @@ -255,14 +258,6 @@ data: operator-prometheus-serve-addr: ":{{ .Values.operator.prometheus.port }}" enable-metrics: "true" {{- end }} -{{- if and .Values.operator.prometheus.enabled .Values.operator.prometheus.tls.enabled }} - operator-prometheus-enable-tls: "true" - operator-prometheus-tls-cert-file: /var/lib/cilium/tls/prometheus/server.crt - operator-prometheus-tls-key-file: /var/lib/cilium/tls/prometheus/server.key - {{- if .Values.operator.prometheus.tls.server.mtls.enabled }} - operator-prometheus-tls-client-ca-files: /var/lib/cilium/tls/prometheus/client-ca.crt - {{- end }} -{{- end }} {{- if .Values.operator.skipCRDCreation }} skip-crd-creation: "true" @@ -461,12 +456,6 @@ data: # policy map (per endpoint) bpf-policy-map-max: "{{ .Values.bpf.policyMapMax | int }}" {{- end }} -{{- if has (kindOf .Values.bpf.policyMapPressureMetricsThreshold) (list "int64" "float64") }} - bpf-policy-map-pressure-metrics-threshold: {{ .Values.bpf.policyMapPressureMetricsThreshold | quote }} -{{- end }} -{{- if .Values.endpointPolicyUpdateTimeoutDuration }} - endpoint-policy-update-timeout: {{ .Values.endpointPolicyUpdateTimeoutDuration | quote }} -{{- end }} {{- if hasKey .Values.bpf "policyStatsMapMax" }} # bpf-policy-stats-map-max specifies the maximum number of entries in global # policy stats map @@ -516,7 +505,7 @@ data: cluster-name: {{ .Values.cluster.name | quote }} {{- if hasKey .Values.cluster "id" }} - # Unique ID of the cluster. Must be unique across all connected clusters and + # Unique ID of the cluster. Must be unique across all conneted clusters and # in the range of 1 and 255. Only relevant when building a mesh of clusters. cluster-id: "{{ .Values.cluster.id }}" {{- end }} @@ -537,7 +526,7 @@ data: {{- end }} {{- end }} - routing-mode: {{ .Values.routingMode | default (ternary "native" "tunnel" (or .Values.eni.enabled .Values.gke.enabled)) | quote }} + routing-mode: {{ .Values.routingMode | default (ternary "native" "tunnel" .Values.gke.enabled) | quote }} tunnel-protocol: {{ .Values.tunnelProtocol | default "vxlan" | quote }} {{- if eq .Values.routingMode "native" }} @@ -569,10 +558,6 @@ data: service-no-backend-response: "{{ .Values.serviceNoBackendResponse }}" {{- end}} -{{- if .Values.policyDenyResponse }} - policy-deny-response: "{{ .Values.policyDenyResponse }}" -{{- end}} - {{- if .Values.MTU }} mtu: {{ .Values.MTU | quote }} {{- end }} @@ -590,35 +575,6 @@ data: {{- end }} ec2-api-endpoint: {{ .Values.eni.ec2APIEndpoint | quote }} eni-tags: {{ .Values.eni.eniTags | toRawJson | quote }} -{{- if .Values.eni.nodeSpec }} - {{- if ne .Values.eni.nodeSpec.firstInterfaceIndex nil }} - eni-first-interface-index: {{ .Values.eni.nodeSpec.firstInterfaceIndex | quote }} - {{- end }} - {{- if .Values.eni.nodeSpec.subnetIDs }} - eni-subnet-ids: {{ .Values.eni.nodeSpec.subnetIDs | join "," | quote }} - {{- end }} - {{- if .Values.eni.nodeSpec.subnetTags }} - eni-subnet-tags: {{ .Values.eni.nodeSpec.subnetTags | join "," | quote }} - {{- end }} - {{- if .Values.eni.nodeSpec.securityGroups }} - eni-security-groups: {{ .Values.eni.nodeSpec.securityGroups | join "," | quote }} - {{- end }} - {{- if .Values.eni.nodeSpec.securityGroupTags }} - eni-security-group-tags: {{ .Values.eni.nodeSpec.securityGroupTags | join "," | quote }} - {{- end }} - {{- if .Values.eni.nodeSpec.excludeInterfaceTags }} - eni-exclude-interface-tags: {{ .Values.eni.nodeSpec.excludeInterfaceTags | join "," | quote }} - {{- end }} - {{- if .Values.eni.nodeSpec.usePrimaryAddress }} - eni-use-primary-address: "true" - {{- end }} - {{- if .Values.eni.nodeSpec.disablePrefixDelegation }} - eni-disable-prefix-delegation: "true" - {{- end }} - {{- if ne .Values.eni.nodeSpec.deleteOnTermination nil }} - eni-delete-on-termination: {{ .Values.eni.nodeSpec.deleteOnTermination | quote }} - {{- end }} -{{- end }} {{- if .Values.eni.subnetIDsFilter }} subnet-ids-filter: {{ .Values.eni.subnetIDsFilter | join " " | quote }} {{- end }} @@ -644,39 +600,17 @@ data: {{- end }} azure-use-primary-address: {{ $azureUsePrimaryAddress | quote }} {{- end }} -{{- if .Values.azure.nodeSpec.azureInterfaceName }} - azure-interface-name: {{ .Values.azure.nodeSpec.azureInterfaceName | quote }} -{{- end }} {{- if .Values.alibabacloud.enabled }} enable-endpoint-routes: "true" auto-create-cilium-node-resource: "true" {{- end }} -{{- if .Values.alibabacloud.nodeSpec.vSwitches }} - alibabacloud-vswitches: {{ .Values.alibabacloud.nodeSpec.vSwitches | join "," | quote }} -{{- end }} -{{- if .Values.alibabacloud.nodeSpec.vSwitchTags }} - alibabacloud-vswitch-tags: {{ .Values.alibabacloud.nodeSpec.vSwitchTags | join "," | quote }} -{{- end }} -{{- if .Values.alibabacloud.nodeSpec.securityGroups }} - alibabacloud-security-groups: {{ .Values.alibabacloud.nodeSpec.securityGroups | join "," | quote }} -{{- end }} -{{- if .Values.alibabacloud.nodeSpec.securityGroupTags }} - alibabacloud-security-group-tags: {{ .Values.alibabacloud.nodeSpec.securityGroupTags | join "," | quote }} -{{- end }} {{- if hasKey .Values "l7Proxy" }} # Enables L7 proxy for L7 policy enforcement and visibility enable-l7-proxy: {{ .Values.l7Proxy | quote }} {{- end }} -{{- if hasKey .Values "standaloneDnsProxy" }} - {{- if .Values.standaloneDnsProxy.enabled }} - enable-standalone-dns-proxy: {{ .Values.standaloneDnsProxy.enabled | quote }} - standalone-dns-proxy-server-port: {{ .Values.standaloneDnsProxy.serverPort | quote }} - {{- end }} -{{- end }} - {{- if ne $cniChainingMode "none" }} # Enable chaining with another CNI plugin # @@ -753,8 +687,6 @@ data: {{- if .Values.encryption.wireguard.persistentKeepalive }} wireguard-persistent-keepalive: {{ .Values.encryption.wireguard.persistentKeepalive | quote }} {{- end }} - {{- else if eq .Values.encryption.type "ztunnel" }} - enable-ztunnel: {{ .Values.encryption.enabled | quote }} {{- end }} {{- if .Values.encryption.nodeEncryption }} encrypt-node: {{ .Values.encryption.nodeEncryption | quote }} @@ -762,20 +694,11 @@ data: {{- end }} {{- if .Values.encryption.strictMode.enabled }} - # --- DEPRECATED: Please use encryption.strictMode.egress.enabled instead - enable-encryption-strict-mode-egress: {{ .Values.encryption.strictMode.enabled | quote }} - encryption-strict-egress-cidr: {{ .Values.encryption.strictMode.cidr | quote }} - encryption-strict-egress-allow-remote-node-identities: {{ .Values.encryption.strictMode.allowRemoteNodeIdentities | quote }} -{{- end }} + enable-encryption-strict-mode: {{ .Values.encryption.strictMode.enabled | quote }} -{{- if .Values.encryption.strictMode.ingress.enabled }} - enable-encryption-strict-mode-ingress: {{ .Values.encryption.strictMode.ingress.enabled | quote }} -{{- end }} + encryption-strict-mode-cidr: {{ .Values.encryption.strictMode.cidr | quote }} -{{- if .Values.encryption.strictMode.egress.enabled }} - enable-encryption-strict-mode-egress: {{ .Values.encryption.strictMode.egress.enabled | quote }} - encryption-strict-egress-cidr: {{ .Values.encryption.strictMode.egress.cidr | quote }} - encryption-strict-egress-allow-remote-node-identities: {{ .Values.encryption.strictMode.egress.allowRemoteNodeIdentities | quote }} + encryption-strict-mode-allow-remote-node-identities: {{ .Values.encryption.strictMode.allowRemoteNodeIdentities | quote }} {{- end }} enable-xt-socket-fallback: {{ .Values.enableXTSocketFallback | quote }} @@ -850,10 +773,6 @@ data: kube-proxy-replacement-healthz-bind-address: {{ default "" .Values.kubeProxyReplacementHealthzBindAddr | quote}} {{- end }} -{{- if hasKey .Values "enableNoServiceEndpointsRoutable" }} - enable-no-service-endpoints-routable: {{ .Values.enableNoServiceEndpointsRoutable | quote }} -{{- end }} - {{- if $socketLB }} {{- if hasKey $socketLB "enabled" }} bpf-lb-sock: {{ $socketLB.enabled | quote }} @@ -870,6 +789,9 @@ data: {{- end }} {{- if hasKey .Values "nodePort" }} +{{- if eq $kubeProxyReplacement "false" }} + enable-node-port: {{ .Values.nodePort.enabled | quote }} +{{- end }} {{- if hasKey .Values.nodePort "range" }} node-port-range: {{ get .Values.nodePort "range" | quote }} {{- end }} @@ -908,18 +830,24 @@ data: {{- end }} {{- if hasKey .Values.loadBalancer "serviceTopology" }} enable-service-topology: {{ .Values.loadBalancer.serviceTopology | quote }} -{{- end }} +# {{- end }} + +{{- if hasKey .Values.loadBalancer "protocolDifferentiation" }} + bpf-lb-proto-diff: {{ .Values.loadBalancer.protocolDifferentiation.enabled | quote }} {{- end }} +{{- end }} {{- if hasKey .Values.maglev "tableSize" }} bpf-lb-maglev-table-size: {{ .Values.maglev.tableSize | quote}} {{- end }} {{- if hasKey .Values.maglev "hashSeed" }} bpf-lb-maglev-hash-seed: {{ .Values.maglev.hashSeed | quote}} {{- end }} - -{{- if .Values.bpf.monitorTraceIPOption }} - ip-tracing-option-type: {{ .Values.bpf.monitorTraceIPOption | quote }} +{{- if .Values.sessionAffinity }} + enable-session-affinity: {{ .Values.sessionAffinity | quote }} +{{- end }} +{{- if .Values.svcSourceRangeCheck }} + enable-svc-source-range-check: {{ .Values.svcSourceRangeCheck | quote }} {{- end }} {{- if hasKey .Values "l2NeighDiscovery" }} @@ -932,16 +860,12 @@ data: pprof: {{ .Values.pprof.enabled | quote }} pprof-address: {{ .Values.pprof.address | quote }} pprof-port: {{ .Values.pprof.port | quote }} - pprof-mutex-profile-fraction: {{ .Values.pprof.mutexProfileFraction | quote }} - pprof-block-profile-rate: {{ .Values.pprof.blockProfileRate | quote }} {{- end }} {{- if .Values.operator.pprof.enabled }} operator-pprof: {{ .Values.operator.pprof.enabled | quote }} operator-pprof-address: {{ .Values.operator.pprof.address | quote }} operator-pprof-port: {{ .Values.operator.pprof.port | quote }} - operator-pprof-mutex-profile-fraction: {{ .Values.operator.pprof.mutexProfileFraction | quote }} - operator-pprof-block-profile-rate: {{ .Values.operator.pprof.blockProfileRate | quote }} {{- end }} {{- if .Values.logSystemLoad }} @@ -1049,10 +973,6 @@ data: # Capacity of the buffer to store recent events. hubble-event-buffer-capacity: {{ .Values.hubble.eventBufferCapacity | quote }} {{- end }} -{{- if hasKey .Values.hubble "lostEventSendInterval" }} - # Interval to send lost events from Observer server. - hubble-lost-event-send-interval: {{ include "validateDuration" .Values.hubble.lostEventSendInterval | quote }} -{{- end }} {{- if or .Values.hubble.metrics.enabled .Values.hubble.metrics.dynamic.enabled}} # Address to expose Hubble metrics (e.g. ":7070"). Metrics server will be disabled if this # field is not set. @@ -1120,10 +1040,8 @@ data: hubble-export-file-max-size-mb: {{ .Values.hubble.export.fileMaxSizeMb | default .Values.hubble.export.static.fileMaxSizeMb | quote }} hubble-export-file-max-backups: {{ .Values.hubble.export.fileMaxBackups | default .Values.hubble.export.static.fileMaxBackups | quote }} hubble-export-file-compress: {{ .Values.hubble.export.fileCompress | default .Values.hubble.export.static.fileCompress | quote }} - hubble-export-aggregation-interval: {{ include "validateDuration" .Values.hubble.export.aggregationInterval | default .Values.hubble.export.static.aggregationInterval | quote }} hubble-export-file-path: {{ .Values.hubble.export.static.filePath | quote }} hubble-export-fieldmask: {{ .Values.hubble.export.static.fieldMask | join " " | quote }} - hubble-export-fieldaggregate: {{ .Values.hubble.export.static.fieldAggregate | join " " | quote }} hubble-export-allowlist: {{ .Values.hubble.export.static.allowList | join " " | quote }} hubble-export-denylist: {{ .Values.hubble.export.static.denyList | join " " | quote }} {{- end }} @@ -1160,28 +1078,10 @@ data: disable-iptables-feeder-rules: {{ .Values.disableIptablesFeederRules | join " " | quote }} {{- end }} {{- if .Values.aksbyocni.enabled }} - {{- if or (not .Values.ipam.mode) (eq .Values.ipam.mode "cluster-pool") }} ipam: "cluster-pool" - {{- else if eq .Values.ipam.mode "multi-pool" }} - ipam: "multi-pool" - {{- end }} {{- else }} ipam: {{ $ipam | quote }} {{- end }} -{{- if .Values.ipam.nodeSpec }} - {{- if ne .Values.ipam.nodeSpec.ipamMinAllocate nil }} - ipam-min-allocate: {{ .Values.ipam.nodeSpec.ipamMinAllocate | quote }} - {{- end }} - {{- if ne .Values.ipam.nodeSpec.ipamPreAllocate nil }} - ipam-pre-allocate: {{ .Values.ipam.nodeSpec.ipamPreAllocate | quote }} - {{- end }} - {{- if ne .Values.ipam.nodeSpec.ipamMaxAllocate nil }} - ipam-max-allocate: {{ .Values.ipam.nodeSpec.ipamMaxAllocate | quote }} - {{- end }} - {{- if .Values.ipam.nodeSpec.ipamStaticIPTags }} - ipam-static-ip-tags: {{ .Values.ipam.nodeSpec.ipamStaticIPTags | join "," | quote }} - {{- end }} -{{- end }} {{- if .Values.ipam.multiPoolPreAllocation }} ipam-multi-pool-pre-allocation: {{ .Values.ipam.multiPoolPreAllocation | quote }} {{- end }} @@ -1192,10 +1092,18 @@ data: {{- if (eq $ipam "cluster-pool") }} {{- if .Values.ipv4.enabled }} + {{- if hasKey .Values.ipam.operator "clusterPoolIPv4PodCIDR" }} + {{- /* ipam.operator.clusterPoolIPv4PodCIDR removed in v1.14, remove this failsafe around v1.17 */ -}} + {{- fail "Value ipam.operator.clusterPoolIPv4PodCIDR removed, use ipam.operator.clusterPoolIPv4PodCIDRList instead" }} + {{- end }} cluster-pool-ipv4-cidr: {{ .Values.ipam.operator.clusterPoolIPv4PodCIDRList | join " " | quote }} cluster-pool-ipv4-mask-size: {{ .Values.ipam.operator.clusterPoolIPv4MaskSize | quote }} {{- end }} {{- if .Values.ipv6.enabled }} + {{- if hasKey .Values.ipam.operator "clusterPoolIPv6PodCIDR" }} + {{- /* ipam.operator.clusterPoolIPv6PodCIDR removed in v1.14, remove this failsafe around v1.17 */ -}} + {{- fail "Value ipam.operator.clusterPoolIPv6PodCIDR removed, use ipam.operator.clusterPoolIPv6PodCIDRList instead" }} + {{- end }} cluster-pool-ipv6-cidr: {{ .Values.ipam.operator.clusterPoolIPv6PodCIDRList | join " " | quote }} cluster-pool-ipv6-mask-size: {{ .Values.ipam.operator.clusterPoolIPv6MaskSize | quote }} {{- end }} @@ -1264,11 +1172,20 @@ data: crd-wait-timeout: {{ include "validateDuration" .Values.crdWaitTimeout | quote }} {{- end }} +{{- if .Values.enableK8sEndpointSlice }} + enable-k8s-endpoint-slice: {{ .Values.enableK8sEndpointSlice | quote }} +{{- end }} + {{- if hasKey .Values.k8s "serviceProxyName" }} # Configure service proxy name for Cilium. k8s-service-proxy-name: {{ .Values.k8s.serviceProxyName | quote }} {{- end }} +{{- if and .Values.customCalls .Values.customCalls.enabled }} + # Enable tail call hooks for custom eBPF programs. + enable-custom-calls: {{ .Values.customCalls.enabled | quote }} +{{- end }} + {{- if .Values.l2announcements.enabled }} # Enable L2 announcements enable-l2-announcements: {{ .Values.l2announcements.enabled | quote }} @@ -1305,8 +1222,6 @@ data: enable-pmtu-discovery: "true" {{- end }} - packetization-layer-pmtud-mode: {{ .Values.pmtuDiscovery.packetizationLayerPMTUDMode | quote }} - {{- if not .Values.securityContext.privileged }} procfs: "/host/proc" {{- end }} @@ -1381,16 +1296,11 @@ data: {{- end }} {{- if .Values.operator.unmanagedPodWatcher.restart }} - {{- $interval := .Values.operator.unmanagedPodWatcher.intervalSeconds }} - unmanaged-pod-watcher-interval: {{ printf "%ds" (int $interval) | quote }} + unmanaged-pod-watcher-interval: {{ .Values.operator.unmanagedPodWatcher.intervalSeconds | quote }} {{- else }} unmanaged-pod-watcher-interval: "0" {{- end }} -{{- if ne .Values.operator.unmanagedPodWatcher.selector nil }} - pod-restart-selector: {{ .Values.operator.unmanagedPodWatcher.selector }} -{{- end }} - {{- if .Values.dnsProxy }} {{- if hasKey .Values.dnsProxy "enableTransparentMode" }} # explicit setting gets precedence @@ -1460,14 +1370,10 @@ data: proxy-xff-num-trusted-hops-egress: {{ .Values.envoy.xffNumTrustedHopsL7PolicyEgress | quote }} proxy-connect-timeout: {{ .Values.envoy.connectTimeoutSeconds | quote }} proxy-initial-fetch-timeout: {{ .Values.envoy.initialFetchTimeoutSeconds | quote }} - proxy-max-active-downstream-connections: {{ .Values.envoy.maxGlobalDownstreamConnections | quote }} proxy-max-requests-per-connection: {{ .Values.envoy.maxRequestsPerConnection | quote }} proxy-max-connection-duration-seconds: {{ .Values.envoy.maxConnectionDurationSeconds | quote }} proxy-idle-timeout-seconds: {{ .Values.envoy.idleTimeoutDurationSeconds | quote }} proxy-max-concurrent-retries: {{ .Values.envoy.maxConcurrentRetries | quote }} - proxy-use-original-source-address: {{ .Values.envoy.useOriginalSourceAddress | quote }} - proxy-cluster-max-connections: {{ .Values.envoy.clusterMaxConnections | quote }} - proxy-cluster-max-requests: {{ .Values.envoy.clusterMaxRequests | quote }} http-retry-count: {{ .Values.envoy.httpRetryCount | quote }} http-stream-idle-timeout: {{ .Values.envoy.streamIdleTimeoutDurationSeconds | quote }} @@ -1496,14 +1402,13 @@ data: {{- if hasKey .Values.clustermesh "maxConnectedClusters" }} max-connected-clusters: {{ .Values.clustermesh.maxConnectedClusters | quote }} {{- end }} - clustermesh-cache-ttl: {{ .Values.clustermesh.cacheTTL | quote }} clustermesh-enable-endpoint-sync: {{ .Values.clustermesh.enableEndpointSliceSynchronization | quote }} - clustermesh-enable-mcs-api: {{ (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) | quote }} - clustermesh-mcs-api-install-crds: {{ .Values.clustermesh.mcsapi.installCRDs | quote }} + clustermesh-enable-mcs-api: {{ .Values.clustermesh.enableMCSAPISupport | quote }} policy-default-local-cluster: {{ .Values.clustermesh.policyDefaultLocalCluster | quote }} nat-map-stats-entries: {{ .Values.nat.mapStatsEntries | quote }} nat-map-stats-interval: {{ .Values.nat.mapStatsInterval | quote }} + enable-internal-traffic-policy: {{ .Values.enableInternalTrafficPolicy | quote }} enable-lb-ipam: {{ .Values.enableLBIPAM | quote }} enable-non-default-deny-policies: {{ .Values.enableNonDefaultDenyPolicies | quote }} @@ -1515,14 +1420,6 @@ data: connectivity-probe-frequency-ratio: {{ .Values.connectivityProbeFrequencyRatio | quote }} {{- end }} -{{- if hasKey .Values "configDriftDetection" }} - enable-dynamic-config: {{ .Values.configDriftDetection.enabled | quote }} - enable-drift-checker: {{ .Values.configDriftDetection.driftChecker | quote }} - {{- if .Values.configDriftDetection.ignoredKeys }} - ignore-flags-drift-checker: {{ join "," .Values.configDriftDetection.ignoredKeys | quote }} - {{- end }} -{{- end }} - # Extra config allows adding arbitrary properties to the cilium config. # By putting it at the end of the ConfigMap, it's also possible to override existing properties. {{- if .Values.extraConfig }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml index 2afc2e97..a5decd02 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/daemonset.yaml @@ -22,7 +22,10 @@ spec: selector: matchLabels: k8s-app: cilium-envoy - {{- include "envoy.updateStrategy" . | nindent 2 }} + {{- with .Values.envoy.updateStrategy }} + updateStrategy: + {{- toYaml . | trim | nindent 4 }} + {{- end }} template: metadata: annotations: @@ -66,7 +69,6 @@ spec: securityContext: {{- toYaml . | nindent 8 }} {{- end }} - {{- include "envoy.initContainers" . | nindent 6 }} containers: - name: cilium-envoy image: {{ include "cilium.image" .Values.envoy.image | quote }} @@ -92,7 +94,6 @@ spec: {{- if .Values.envoy.log.path }} - '--log-path {{ .Values.envoy.log.path }}' {{- end }} - {{- include "envoy.args.extra" . | nindent 8 }} {{- with .Values.envoy.extraArgs }} {{- toYaml . | trim | nindent 8 }} {{- end }} @@ -156,7 +157,6 @@ spec: - name: KUBERNETES_SERVICE_PORT value: {{ include "k8sServicePort" . }} {{- end }} - {{- include "envoy.env.extra" . | nindent 8 }} {{- with .Values.envoy.extraEnv }} {{- toYaml . | trim | nindent 8 }} {{- end }} @@ -164,7 +164,19 @@ spec: resources: {{- toYaml . | trim | nindent 10 }} {{- end }} - {{- include "envoy.ports" . }} + {{- if .Values.envoy.prometheus.enabled }} + ports: + - name: envoy-metrics + containerPort: {{ .Values.envoy.prometheus.port }} + hostPort: {{ .Values.envoy.prometheus.port }} + protocol: TCP + {{- if and .Values.envoy.debug.admin.enabled .Values.envoy.debug.admin.port }} + - name: envoy-admin + containerPort: {{ .Values.envoy.debug.admin.port }} + hostPort: {{ .Values.envoy.debug.admin.port }} + protocol: TCP + {{- end }} + {{- end }} securityContext: {{- if .Values.envoy.securityContext.privileged }} privileged: true @@ -197,7 +209,6 @@ spec: mountPath: /sys/fs/bpf mountPropagation: HostToContainer {{- end }} - {{- include "envoy.volumeMounts.extra" . | nindent 8 }} {{- range .Values.envoy.extraHostPathMounts }} - name: {{ .name }} mountPath: {{ .mountPath }} @@ -221,7 +232,10 @@ spec: {{- if .Values.envoy.dnsPolicy }} dnsPolicy: {{ .Values.envoy.dnsPolicy }} {{- end }} - {{- include "envoy.affinity" . | nindent 6 }} + {{- with .Values.envoy.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} {{- with .Values.envoy.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} @@ -255,7 +269,6 @@ spec: path: /sys/fs/bpf type: DirectoryOrCreate {{- end }} - {{- include "envoy.hostPathMounts.extra" . | nindent 4 }} {{- range .Values.envoy.extraHostPathMounts }} - name: {{ .name }} hostPath: diff --git a/packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml b/packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml index 8da47943..6b982c28 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-envoy/service.yaml @@ -32,5 +32,5 @@ spec: - name: envoy-metrics port: {{ .Values.envoy.prometheus.port }} protocol: TCP - targetPort: {{ .Values.envoy.prometheus.port }} + targetPort: envoy-metrics {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml b/packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml index f25afeee..5d16d7ca 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-ingress-service.yaml @@ -49,8 +49,8 @@ spec: externalTrafficPolicy: {{ .Values.ingressController.service.externalTrafficPolicy }} {{- end }} --- -apiVersion: discovery.k8s.io/v1 -kind: EndpointSlice +apiVersion: v1 +kind: Endpoints metadata: name: {{ .Values.ingressController.service.name }} namespace: {{ include "cilium.namespace" . }} @@ -65,10 +65,9 @@ metadata: annotations: {{- toYaml .Values.ingressController.service.annotations | nindent 4 }} {{- end }} -addressType: IPv4 -endpoints: +subsets: - addresses: - - "192.192.192.192" -ports: -- port: 9999 + - ip: "192.192.192.192" + ports: + - port: 9999 {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml index 4edbeada..add6ae5a 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-nodeinit/daemonset.yaml @@ -122,8 +122,6 @@ spec: {{- if .Values.serviceAccounts.nodeinit.enabled }} serviceAccountName: {{ .Values.serviceAccounts.nodeinit.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.nodeinit.automount }} - {{- else }} - automountServiceAccountToken: false {{- end }} {{- with .Values.nodeinit.extraVolumes }} volumes: diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml index c147e2b5..4fcb5985 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/clusterrole.yaml @@ -69,7 +69,7 @@ rules: resources: - endpointslices verbs: -{{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} +{{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.enableMCSAPISupport }} - create - update - delete @@ -78,17 +78,6 @@ rules: - get - list - watch -{{- if .Values.clustermesh.enableEndpointSliceSynchronization }} -- apiGroups: - - "" - resources: - # The controller needs to be able to set a service's finalizers to be able to create an EndpointSlice - # resource that is owned by the service and sets blockOwnerDeletion=true in its ownerRef. - # This is required when the admission plugin OwnerReferencesPermissionEnforcement is activated. - - services/finalizers - verbs: - - update -{{- end }} - apiGroups: - "" resources: @@ -125,20 +114,6 @@ rules: - delete - patch {{- end }} -{{- if or .Values.ingressController.enabled .Values.gatewayAPI.enabled }} -- apiGroups: - - "discovery.k8s.io" - resources: - - endpointslices - verbs: - - get - - list - - watch - - create - - update - - delete - - patch -{{- end }} {{- if .Values.clustermesh.enableEndpointSliceSynchronization }} - apiGroups: - "" @@ -252,6 +227,7 @@ rules: - update resourceNames: - ciliumloadbalancerippools.cilium.io + - ciliumbgppeeringpolicies.cilium.io - ciliumbgpclusterconfigs.cilium.io - ciliumbgppeerconfigs.cilium.io - ciliumbgpadvertisements.cilium.io @@ -272,15 +248,12 @@ rules: - ciliuml2announcementpolicies.cilium.io - ciliumpodippools.cilium.io - ciliumgatewayclassconfigs.cilium.io -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.installCRDs }} - - serviceimports.multicluster.x-k8s.io - - serviceexports.multicluster.x-k8s.io -{{- end }} - apiGroups: - cilium.io resources: - ciliumloadbalancerippools - ciliumpodippools + - ciliumbgppeeringpolicies - ciliumbgpclusterconfigs - ciliumbgpnodeconfigoverrides - ciliumbgppeerconfigs @@ -328,10 +301,6 @@ rules: - networking.k8s.io resources: - ingresses/status # To update ingress status with load balancer IP. - # The controller needs to be able to set ingress finalizers to be able to create a CiliumEnvoyConfig - # resource that is owned by the ingress, and set blockOwnerDeletion=true in its ownerRef. - # This is required when the admission plugin OwnerReferencesPermissionEnforcement is activated. - - ingresses/finalizers verbs: - update {{- end }} @@ -383,7 +352,7 @@ rules: - update - patch {{- end }} -{{- if or .Values.gatewayAPI.enabled .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} +{{- if or .Values.gatewayAPI.enabled .Values.clustermesh.enableMCSAPISupport }} - apiGroups: - multicluster.x-k8s.io resources: @@ -392,14 +361,14 @@ rules: - get - list - watch -{{- if or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} +{{- if .Values.clustermesh.enableMCSAPISupport }} - create - update - patch - delete {{- end }} {{- end }} -{{- if or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} +{{- if .Values.clustermesh.enableMCSAPISupport }} - apiGroups: - multicluster.x-k8s.io resources: @@ -407,15 +376,6 @@ rules: verbs: - update - patch -- apiGroups: - - multicluster.x-k8s.io - resources: - # The controller needs to be able to set serviceimport finalizers to be able to create a derived Service - # resource that is owned by the ServiceImport and sets blockOwnerDeletion=true in its ownerRef. - # This is required when the admission plugin OwnerReferencesPermissionEnforcement is activated. - - serviceimports/finalizers - verbs: - - update - apiGroups: - multicluster.x-k8s.io resources: @@ -441,10 +401,4 @@ rules: - patch - delete {{- end }} -- apiGroups: - - cilium.io - resources: - - ciliumendpointslices - verbs: - - deletecollection {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml index f4cddff8..606807f3 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/deployment.yaml @@ -98,7 +98,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - {{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} + {{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.enableMCSAPISupport }} - name: CILIUM_CLUSTERMESH_CONFIG value: /var/lib/cilium/clustermesh/ {{- end }} @@ -170,7 +170,6 @@ spec: - name: AZURE_RESOURCE_GROUP value: {{ .Values.azure.resourceGroup }} {{- end }} - {{- if .Values.azure.clientID }} - name: AZURE_CLIENT_ID valueFrom: secretKeyRef: @@ -182,15 +181,11 @@ spec: name: cilium-azure key: AZURE_CLIENT_SECRET {{- end }} - {{- end }} {{- with .Values.operator.extraEnv }} {{- toYaml . | nindent 8 }} {{- end }} - ports: - - name: health - containerPort: 9234 - hostPort: 9234 {{- if .Values.operator.prometheus.enabled }} + ports: - name: prometheus containerPort: {{ .Values.operator.prometheus.port }} {{- if .Values.operator.hostNetwork }} @@ -204,7 +199,7 @@ spec: host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} {{- end }} path: /healthz - port: health + port: 9234 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 @@ -215,7 +210,7 @@ spec: host: {{ .Values.ipv4.enabled | ternary "127.0.0.1" "::1" | quote }} {{- end }} path: /healthz - port: health + port: 9234 scheme: HTTP initialDelaySeconds: 0 periodSeconds: 5 @@ -235,7 +230,7 @@ spec: readOnly: true {{- end }} {{- end }} - {{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} + {{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.enableMCSAPISupport }} - name: clustermesh-secrets mountPath: /var/lib/cilium/clustermesh readOnly: true @@ -250,11 +245,6 @@ spec: mountPath: {{ dir .Values.authentication.mutual.spire.agentSocketPath }} readOnly: true {{- end }} - {{- if and .Values.operator.prometheus.enabled .Values.operator.prometheus.tls.enabled }} - - name: prometheus-tls - mountPath: /var/lib/cilium/tls/prometheus - readOnly: true - {{- end }} {{- range .Values.operator.extraHostPathMounts }} - name: {{ .name }} mountPath: {{ .mountPath }} @@ -266,15 +256,13 @@ spec: {{- with .Values.operator.extraVolumeMounts }} {{- toYaml . | nindent 8 }} {{- end }} - {{- include "cilium-operator.volumeMounts.extra" . | nindent 8 }} {{- with .Values.operator.resources }} resources: {{- toYaml . | trim | nindent 10 }} {{- end }} - {{- $sc := include "cilium.operator.securityContext" . | trim }} - {{- if $sc }} + {{- with .Values.operator.securityContext }} securityContext: - {{- $sc | nindent 10 }} + {{- toYaml . | trim | nindent 10 }} {{- end }} terminationMessagePolicy: FallbackToLogsOnError hostNetwork: {{ .Values.operator.hostNetwork }} @@ -307,25 +295,23 @@ spec: nodeSelector: {{- toYaml . | trim | nindent 8 }} {{- end }} - {{- if and (or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.config.enabled (not (and .Values.clustermesh.useAPIServer .Values.clustermesh.apiserver.kvstoremesh.enabled )) }} + {{- if and (or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.config.enabled (not (and .Values.clustermesh.useAPIServer .Values.clustermesh.apiserver.kvstoremesh.enabled )) }} hostAliases: - {{- range $_, $cluster := (include "clustermesh-clusters" . | fromJson) }} + {{- range $cluster := .Values.clustermesh.config.clusters }} {{- range $ip := $cluster.ips }} - ip: {{ $ip }} hostnames: [ "{{ $cluster.name }}.{{ $.Values.clustermesh.config.domain }}" ] {{- end }} {{- end }} {{- end }} - {{- if or (.Values.operator.tolerations) (hasKey .Values "agentNotReadyTaintKey") }} - tolerations: {{- with .Values.operator.tolerations }} + tolerations: {{- toYaml . | trim | nindent 8 }} {{- end }} {{- if hasKey .Values "agentNotReadyTaintKey" }} - key: {{ .Values.agentNotReadyTaintKey }} operator: Exists {{ end}} - {{- end}} volumes: # To read the configuration from the config map - name: cilium-config-path @@ -374,7 +360,7 @@ spec: {{- with .Values.operator.extraVolumes }} {{- toYaml . | nindent 6 }} {{- end }} - {{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} + {{- if or .Values.clustermesh.enableEndpointSliceSynchronization .Values.clustermesh.enableMCSAPISupport }} # To read the clustermesh configuration - name: clustermesh-secrets projected: @@ -431,25 +417,4 @@ spec: path: local-etcd-client-ca.crt {{- end }} {{- end }} - {{- if and .Values.operator.prometheus.enabled .Values.operator.prometheus.tls.enabled }} - # To read the prometheus configuration - - name: prometheus-tls - projected: - # note: the leading zero means this number is in octal representation: do not remove it - defaultMode: 0400 - sources: - - secret: - name: {{ .Values.operator.prometheus.tls.server.existingSecret }} - optional: true - items: - - key: tls.crt - path: server.crt - - key: tls.key - path: server.key - {{- if .Values.operator.prometheus.tls.server.mtls.enabled }} - - key: ca.crt - path: client-ca.crt - {{- end }} - {{- end }} - {{- include "cilium-operator.volumes.extra" . | nindent 6 }} {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml index 11515ced..8f7acd9f 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/role.yaml @@ -83,35 +83,3 @@ rules: - update - patch {{- end }} - -{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: cilium-operator-ztunnel - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.operator.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} - labels: - app.kubernetes.io/part-of: cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} -rules: -# ZTunnel DaemonSet management permissions -# Note: These permissions must always be granted (not conditional on encryption.type) -# because the controller needs to clean up stale DaemonSets when ztunnel is disabled. -- apiGroups: - - apps - resources: - - daemonsets - verbs: - - create - - delete - - get - - list - - watch -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml index 22ac17bc..56b89209 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/rolebinding.yaml @@ -77,29 +77,3 @@ subjects: name: {{ .Values.serviceAccounts.operator.name | quote }} namespace: {{ include "cilium.namespace" . }} {{- end }} - -{{- if and .Values.operator.enabled .Values.serviceAccounts.operator.create }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cilium-operator-ztunnel - namespace: {{ include "cilium.namespace" . }} - labels: - app.kubernetes.io/part-of: cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.operator.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: cilium-operator-ztunnel -subjects: -- kind: ServiceAccount - name: {{ .Values.serviceAccounts.operator.name | quote }} - namespace: {{ include "cilium.namespace" . }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml b/packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml index 6346e136..4ac55d7a 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-operator/secret.yaml @@ -1,6 +1,5 @@ {{- if .Values.operator.enabled }} {{- if .Values.azure.enabled }} -{{- if .Values.azure.clientID }} apiVersion: v1 kind: Secret metadata: @@ -20,4 +19,3 @@ data: AZURE_CLIENT_SECRET: {{ default "" .Values.azure.clientSecret | b64enc | quote }} {{- end }} {{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml index fbf511cd..bf0f07da 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-preflight/clusterrole.yaml @@ -94,6 +94,7 @@ rules: - cilium.io resources: - ciliumloadbalancerippools + - ciliumbgppeeringpolicies - ciliumbgpnodeconfigs - ciliumbgpadvertisements - ciliumbgppeerconfigs diff --git a/packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml b/packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml index 600ccfeb..944b0629 100644 --- a/packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml +++ b/packages/system/cilium/charts/cilium/templates/cilium-secrets-namespace.yaml @@ -20,9 +20,6 @@ metadata: {{- with $.Values.commonLabels }} {{- toYaml . | nindent 4 }} {{- end }} - {{- with $.Values.secretsNamespaceLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} annotations: {{- with $.Values.secretsNamespaceAnnotations }} {{- toYaml . | nindent 4 }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml index 88288eb8..8565f585 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/clusterrole.yaml @@ -50,7 +50,7 @@ rules: - get - list - watch -{{- if or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} +{{- if .Values.clustermesh.enableMCSAPISupport }} - apiGroups: - multicluster.x-k8s.io resources: diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml index 1146209a..b0366e3b 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/deployment.yaml @@ -137,7 +137,6 @@ spec: - --advertise-client-urls=https://localhost:2379 - --initial-cluster-token=$(INITIAL_CLUSTER_TOKEN) - --auto-compaction-retention=1 - - --enable-grpc-gateway=false {{- if .Values.clustermesh.apiserver.metrics.etcd.enabled }} - --listen-metrics-urls=http://0.0.0.0:{{ .Values.clustermesh.apiserver.metrics.etcd.port }} - --metrics={{ .Values.clustermesh.apiserver.metrics.etcd.mode }} @@ -209,13 +208,12 @@ spec: - --prometheus-serve-addr=:{{ .Values.clustermesh.apiserver.metrics.port }} - --controller-group-metrics=all {{- end }} - {{- if or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport }} + {{- if .Values.clustermesh.enableMCSAPISupport }} - --clustermesh-enable-mcs-api {{- end }} {{- if .Values.ciliumEndpointSlice.enabled }} - --enable-cilium-endpoint-slice {{- end }} - {{- include "clustermesh.apiserver.args.extra" . | nindent 8 }} {{- with .Values.clustermesh.apiserver.extraArgs }} {{- toYaml . | trim | nindent 8 }} {{- end }} @@ -305,14 +303,12 @@ spec: {{- if hasKey .Values.clustermesh "maxConnectedClusters" }} - --max-connected-clusters={{ .Values.clustermesh.maxConnectedClusters }} {{- end }} - - --clustermesh-cache-ttl={{ .Values.clustermesh.cacheTTL }} - --health-port={{ .Values.clustermesh.apiserver.kvstoremesh.healthPort }} {{- if .Values.clustermesh.apiserver.metrics.kvstoremesh.enabled }} - --prometheus-serve-addr=:{{ .Values.clustermesh.apiserver.metrics.kvstoremesh.port }} - --controller-group-metrics=all {{- end }} - --enable-heartbeat={{ eq "true" (include "identityAllocationCRD" .) | ternary "false" "true" }} - {{- include "clustermesh.kvstoremesh.args.extra" . | nindent 8 }} {{- with .Values.clustermesh.apiserver.kvstoremesh.extraArgs }} {{- toYaml . | trim | nindent 8 }} {{- end }} @@ -509,7 +505,7 @@ spec: {{- end }} {{- if and .Values.clustermesh.config.enabled .Values.clustermesh.apiserver.kvstoremesh.enabled }} hostAliases: - {{- range $_, $cluster := (include "clustermesh-clusters" . | fromJson) }} + {{- range $cluster := .Values.clustermesh.config.clusters }} {{- range $ip := $cluster.ips }} - ip: {{ $ip }} hostnames: [ "{{ $cluster.name }}.{{ $.Values.clustermesh.config.domain }}" ] diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml index 5e20234b..6ef3f63f 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/service.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.clustermesh.useAPIServer (eq .Values.clustermesh.apiserver.kvstoremesh.kvstoreMode "internal") (not .Values.clustermesh.apiserver.service.externallyCreated) }} +{{- if and .Values.clustermesh.useAPIServer (eq .Values.clustermesh.apiserver.kvstoremesh.kvstoreMode "internal") }} apiVersion: v1 kind: Service metadata: diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl index 2fdccf47..7ba8cb12 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/_job-spec.tpl @@ -9,18 +9,10 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} spec: - securityContext: - seccompProfile: - type: RuntimeDefault containers: - name: certgen image: {{ include "cilium.image" .Values.certgen.image | quote }} imagePullPolicy: {{ .Values.certgen.image.pullPolicy }} - securityContext: - capabilities: - drop: - - ALL - allowPrivilegeEscalation: false {{- with .Values.certgen.resources }} resources: {{- toYaml . | nindent 12 }} @@ -92,7 +84,7 @@ spec: volumeMounts: {{- toYaml . | nindent 10 }} {{- end }} - hostNetwork: false + hostNetwork: true {{- with .Values.certgen.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} @@ -104,6 +96,7 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} + serviceAccount: {{ .Values.serviceAccounts.clustermeshcertgen.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.clustermeshcertgen.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.clustermeshcertgen.automount }} {{- with .Values.imagePullSecrets }} @@ -115,11 +108,9 @@ spec: volumes: {{- toYaml . | nindent 6 }} {{- end }} - {{- with .Values.certgen.affinity }} affinity: + {{- with .Values.certgen.affinity }} {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.certgen.ttlSecondsAfterFinished }} - ttlSecondsAfterFinished: {{ . }} - {{- end }} + ttlSecondsAfterFinished: {{ .Values.certgen.ttlSecondsAfterFinished }} {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml index 4b88d92c..ebda21bd 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/cronjob.yaml @@ -16,8 +16,6 @@ metadata: {{- end }} spec: schedule: {{ .Values.clustermesh.apiserver.tls.auto.schedule | quote }} - successfulJobsHistoryLimit: {{ .Values.certgen.cronJob.successfulJobsHistoryLimit }} - failedJobsHistoryLimit: {{ .Values.certgen.cronJob.failedJobsHistoryLimit }} concurrencyPolicy: Forbid jobTemplate: {{- include "clustermesh-apiserver-generate-certs.job.spec" . | nindent 4 }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml index 574aee13..72f8dc60 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/job.yaml @@ -1,18 +1,9 @@ {{- if and (and .Values.clustermesh.useAPIServer (eq .Values.clustermesh.apiserver.kvstoremesh.kvstoreMode "internal")) .Values.clustermesh.apiserver.tls.auto.enabled (eq .Values.clustermesh.apiserver.tls.auto.method "cronJob") }} -{{/* -Because Kubernetes job specs are immutable, Helm will fail patch this job if -the spec changes between releases. To avoid breaking the upgrade path, we -generate a name for the job here which is based on the checksum of the spec. -This will cause the name of the job to change if its content changes, -and in turn cause Helm to do delete the old job and replace it with a new one. -*/}} -{{- $jobSpec := include "clustermesh-apiserver-generate-certs.job.spec" . -}} -{{- $checkSum := $jobSpec | sha256sum | trunc 10 -}} --- apiVersion: batch/v1 kind: Job metadata: - name: clustermesh-apiserver-generate-certs-{{$checkSum}} + name: clustermesh-apiserver-generate-certs namespace: {{ include "cilium.namespace" . }} labels: k8s-app: clustermesh-apiserver-generate-certs @@ -20,14 +11,13 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} app.kubernetes.io/part-of: cilium - {{- if or .Values.certgen.annotations.job .Values.clustermesh.annotations }} annotations: + "helm.sh/hook": post-install,post-upgrade {{- with .Values.certgen.annotations.job }} - {{- toYaml . | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} {{- with .Values.clustermesh.annotations }} {{- toYaml . | nindent 4 }} {{- end }} - {{- end }} -{{ $jobSpec }} +{{ include "clustermesh-apiserver-generate-certs.job.spec" . }} {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml index 1f6dc153..6e822701 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-cronjob/role.yaml @@ -38,6 +38,7 @@ rules: - clustermesh-apiserver-admin-cert - clustermesh-apiserver-remote-cert - clustermesh-apiserver-local-cert + - clustermesh-apiserver-client-cert verbs: - update {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml index 49325d14..fa49c9ce 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/admin-secret.yaml @@ -8,16 +8,12 @@ kind: Secret metadata: name: clustermesh-apiserver-admin-cert namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/local-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/local-secret.yaml index 3d34bd68..0589a9e7 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/local-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/local-secret.yaml @@ -8,16 +8,12 @@ kind: Secret metadata: name: clustermesh-apiserver-local-cert namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml index 11bfc51d..42afe0fe 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/remote-secret.yaml @@ -8,16 +8,12 @@ kind: Secret metadata: name: clustermesh-apiserver-remote-cert namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml index 0df9a20d..e49478cb 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/tls-helm/server-secret.yaml @@ -10,16 +10,12 @@ kind: Secret metadata: name: clustermesh-apiserver-server-cert namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml index d742e4e7..c736eb1e 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-apiserver/users-configmap.yaml @@ -1,5 +1,5 @@ {{- if and - (and .Values.clustermesh.useAPIServer .Values.clustermesh.config.enabled (eq .Values.clustermesh.apiserver.kvstoremesh.kvstoreMode "internal") (eq "true" (include "identityAllocationCRD" .))) + (and .Values.clustermesh.useAPIServer (eq .Values.clustermesh.apiserver.kvstoremesh.kvstoreMode "internal") (eq "true" (include "identityAllocationCRD" .))) (ne .Values.clustermesh.apiserver.tls.authMode "legacy") }} --- @@ -21,7 +21,7 @@ metadata: data: users.yaml: | users: - {{- range (include "clustermesh-clusters" . | fromJson) }} + {{- range .Values.clustermesh.config.clusters }} - name: remote-{{ .name }} role: remote {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl b/packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl index abe9bdb8..47c3393c 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-config/_helpers.tpl @@ -43,26 +43,3 @@ key-file: /var/lib/cilium/clustermesh/{{ $prefix }}etcd-client.key cert-file: /var/lib/cilium/clustermesh/{{ $prefix }}etcd-client.crt {{- end }} {{- end }} - -{{- define "clustermesh-clusters" }} -{{- $clusters := dict }} -{{- if kindIs "map" .Values.clustermesh.config.clusters }} - {{- range $name, $cluster := deepCopy .Values.clustermesh.config.clusters }} - {{- if ne $cluster.enabled false }} - {{- $_ := unset $cluster "enabled" }} - {{- $_ = set $cluster "name" $name }} - {{- $_ = set $clusters $name $cluster }} - {{- end }} - {{- end }} -{{- else if kindIs "slice" .Values.clustermesh.config.clusters }} - {{- range $cluster := deepCopy .Values.clustermesh.config.clusters }} - {{- if ne $cluster.enabled false }} - {{- $_ := unset $cluster "enabled" }} - {{- $_ := set $clusters $cluster.name $cluster }} - {{- end }} - {{- end }} -{{- else }} - {{- fail (printf "unknown type %s for clustermesh.config.clusters" (kindOf .Values.clustermesh.config.clusters)) }} -{{- end }} -{{- toJson $clusters }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml index d60d6f1c..5a3a7aa8 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-config/clustermesh-secret.yaml @@ -18,7 +18,7 @@ data: {{- $kvstoremesh := and .Values.clustermesh.useAPIServer .Values.clustermesh.apiserver.kvstoremesh.enabled }} {{- $override := ternary (printf "https://clustermesh-apiserver.%s.svc:2379" (include "cilium.namespace" .)) "" $kvstoremesh }} {{- $local_etcd := and $kvstoremesh (eq .Values.clustermesh.apiserver.kvstoremesh.kvstoreMode "external") }} - {{- range (include "clustermesh-clusters" . | fromJson) }} + {{- range .Values.clustermesh.config.clusters }} {{ .name }}: {{ include "clustermesh-config-generate-etcd-cfg" (list . $.Values.clustermesh.config.domain $override $local_etcd $.Values.etcd ) | b64enc }} {{- /* The parenthesis around .tls are required, since it can be null: https://stackoverflow.com/a/68807258 */}} {{- if and (eq $override "") (.tls).cert (.tls).key }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml index 2828cfd2..3cdc7828 100644 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/clustermesh-config/kvstoremesh-secret.yaml @@ -15,7 +15,7 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} data: - {{- range (include "clustermesh-clusters" . | fromJson) }} + {{- range .Values.clustermesh.config.clusters }} {{ .name }}: {{ include "clustermesh-config-generate-etcd-cfg" (list . $.Values.clustermesh.config.domain "" false $.Values.etcd ) | b64enc }} {{- /* The parenthesis around .tls are required, since it can be null: https://stackoverflow.com/a/68807258 */}} {{- if and (.tls).cert (.tls).key }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/clusterrole.yaml deleted file mode 100644 index 08fcea1b..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/clusterrole.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: coredns-mcsapi - labels: - app.kubernetes.io/part-of: cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} - annotations: - {{/* - We have to leave CoreDNS RBAC to be able to read MCS-API resources - as we would leave a broken CoreDNS installation otherwise - */}} - helm.sh/resource-policy: keep - {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -rules: -- apiGroups: - - multicluster.x-k8s.io - resources: - - serviceimports - verbs: - - list - - watch -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/clusterrolebinding.yaml deleted file mode 100644 index 7a1867f5..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/clusterrolebinding.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled }} -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: coredns-mcsapi - labels: - app.kubernetes.io/part-of: cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} - annotations: - {{/* - We have to leave CoreDNS RBAC to be able to read MCS-API resources - as we would leave a broken CoreDNS installation otherwise - */}} - helm.sh/resource-policy: keep - {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: coredns-mcsapi -subjects: -- kind: ServiceAccount - name: {{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.serviceAccountName | quote }} - namespace: {{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.namespace | quote }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-clusterrole.yaml deleted file mode 100644 index ac339f9f..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-clusterrole.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: cilium-coredns-mcsapi-autoconfig - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.clustermesh.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -rules: -# note: namespaces permission are needed to initialize and verify that the kubernetes client works. -- apiGroups: - - "" - resources: - - "namespaces" - verbs: - - "get" -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-clusterrolebinding.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-clusterrolebinding.yaml deleted file mode 100644 index 4b70ccf4..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-clusterrolebinding.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled }} -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: cilium-coredns-mcsapi-autoconfig - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.clustermesh.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cilium-coredns-mcsapi-autoconfig -subjects: -- kind: ServiceAccount - name: {{ .Values.serviceAccounts.corednsMCSAPI.name | quote }} - namespace: {{ include "cilium.namespace" . }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-role.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-role.yaml deleted file mode 100644 index 52f42fae..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-role.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled }} -kind: Role -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: cilium-coredns-mcsapi-autoconfig - namespace: {{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.namespace }} - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.clustermesh.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -rules: -- apiGroups: - - "" - resources: - - "configmaps" - verbs: - - "update" - - "patch" - - "get" - resourceNames: - - "{{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.configMapName }}" -- apiGroups: - - "apps" - resources: - - "deployments" - verbs: - - "patch" - - "update" - - "get" - resourceNames: - - "{{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.deploymentName }}" -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-rolebinding.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-rolebinding.yaml deleted file mode 100644 index f5caf1a1..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-rolebinding.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled }} -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: cilium-coredns-mcsapi-autoconfig - namespace: {{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.namespace }} - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.clustermesh.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: cilium-coredns-mcsapi-autoconfig -subjects: -- kind: ServiceAccount - name: {{ .Values.serviceAccounts.corednsMCSAPI.name | quote }} - namespace: {{ include "cilium.namespace" . }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-serviceaccount.yaml deleted file mode 100644 index 4e572a13..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job-serviceaccount.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled .Values.serviceAccounts.corednsMCSAPI.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.serviceAccounts.corednsMCSAPI.name | quote }} - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if or .Values.serviceAccounts.corednsMCSAPI.annotations .Values.clustermesh.annotations }} - annotations: - {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.serviceAccounts.corednsMCSAPI.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job.yaml b/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job.yaml deleted file mode 100644 index 9f9c3ccd..00000000 --- a/packages/system/cilium/charts/cilium/templates/clustermesh-coredns-mcsapi/job.yaml +++ /dev/null @@ -1,82 +0,0 @@ -{{- if and (or .Values.clustermesh.mcsapi.enabled .Values.clustermesh.enableMCSAPISupport) .Values.clustermesh.mcsapi.corednsAutoConfigure.enabled }} ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: cilium-coredns-mcsapi-autoconfig - namespace: {{ include "cilium.namespace" . }} - labels: - k8s-app: cilium-coredns-mcsapi-autoconfig - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} - app.kubernetes.io/part-of: cilium - annotations: - "helm.sh/hook": post-install,post-upgrade - {{- with .Values.clustermesh.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - template: - metadata: - labels: - k8s-app: cilium-coredns-mcsapi-autoconfig - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - containers: - - name: autoconfig - image: {{ include "cilium.image" .Values.clustermesh.apiserver.image | quote }} - imagePullPolicy: {{ .Values.clustermesh.apiserver.image.pullPolicy }} - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.resources }} - resources: - {{- toYaml . | nindent 10 }} - {{- end }} - command: - - /usr/bin/clustermesh-apiserver - args: - - mcsapi-coredns-cfg - - --coredns-deployment-name={{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.deploymentName }} - - --coredns-configmap-name={{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.configMapName }} - - --coredns-namespace={{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.namespace }} - - --coredns-cluster-domain={{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.clusterDomain }} - - --coredns-clusterset-domain={{ .Values.clustermesh.mcsapi.corednsAutoConfigure.coredns.clustersetDomain }} - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.extraArgs }} - {{- toYaml . | trim | nindent 12 }} - {{- end }} - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.extraVolumeMounts }} - volumeMounts: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- if .Values.clustermesh.mcsapi.corednsAutoConfigure.priorityClassName }} - priorityClassName: {{ .Values.clustermesh.mcsapi.corednsAutoConfigure.priorityClassName }} - {{- end }} - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ .Values.serviceAccounts.corednsMCSAPI.name | quote }} - automountServiceAccountToken: true - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - restartPolicy: OnFailure - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.extraVolumes }} - volumes: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.clustermesh.mcsapi.corednsAutoConfigure.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - ttlSecondsAfterFinished: {{ .Values.clustermesh.mcsapi.corednsAutoConfigure.ttlSecondsAfterFinished }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml b/packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml index 9df77bae..26b6219a 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble-relay/configmap.yaml @@ -29,8 +29,6 @@ data: pprof: {{ .Values.hubble.relay.pprof.enabled | quote }} pprof-address: {{ .Values.hubble.relay.pprof.address | quote }} pprof-port: {{ .Values.hubble.relay.pprof.port | quote }} - pprof-mutex-profile-fraction: {{ .Values.hubble.relay.pprof.mutexProfileFraction | quote }} - pprof-block-profile-rate: {{ .Values.hubble.relay.pprof.blockProfileRate | quote }} {{- end }} {{- if .Values.hubble.relay.prometheus.enabled }} metrics-listen-address: ":{{ .Values.hubble.relay.prometheus.port }}" @@ -46,10 +44,4 @@ data: disable-client-tls: true {{- end }} {{- include "hubble-relay.config.tls" . | nindent 4 }} - {{- if .Values.hubble.relay.logOptions.format }} - log-format: {{ .Values.hubble.relay.logOptions.format }} - {{- end }} - {{- if .Values.hubble.relay.logOptions.level }} - log-level: {{ .Values.hubble.relay.logOptions.level }} - {{- end }} {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml index ebb8cbd6..b8607bd9 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/clusterrole.yaml @@ -14,6 +14,14 @@ metadata: {{- end }} rules: +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - get + - list + - watch - apiGroups: - "" resources: @@ -35,4 +43,12 @@ rules: - get - list - watch +- apiGroups: + - cilium.io + resources: + - "*" + verbs: + - get + - list + - watch {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml b/packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml index 07a94dce..c3b3dc5a 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble-ui/deployment.yaml @@ -74,11 +74,11 @@ spec: livenessProbe: httpGet: path: /healthz - port: http + port: 8081 readinessProbe: httpGet: path: / - port: http + port: 8081 {{- with .Values.hubble.ui.frontend.resources }} resources: {{- toYaml . | trim | nindent 10 }} @@ -184,12 +184,8 @@ spec: defaultMode: 420 name: hubble-ui-nginx name: hubble-ui-nginx-conf - - name: tmp-dir - {{- if .Values.hubble.ui.tmpVolume }} - {{- toYaml .Values.hubble.ui.tmpVolume | nindent 8 }} - {{- else }} - emptyDir: {} - {{- end }} + - emptyDir: {} + name: tmp-dir {{- if .Values.hubble.relay.tls.server.enabled }} - name: hubble-ui-client-certs {{- if .Values.hubble.ui.standalone.enabled }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl index 06fb3347..72a1f3d8 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/_job-spec.tpl @@ -137,6 +137,7 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} + serviceAccount: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} serviceAccountName: {{ .Values.serviceAccounts.hubblecertgen.name | quote }} automountServiceAccountToken: {{ .Values.serviceAccounts.hubblecertgen.automount }} {{- with .Values.imagePullSecrets }} @@ -148,11 +149,9 @@ spec: volumes: {{- toYaml . | nindent 6 }} {{- end }} - {{- with .Values.certgen.affinity }} affinity: + {{- with .Values.certgen.affinity }} {{- toYaml . | nindent 8 }} {{- end }} - {{- with .Values.certgen.ttlSecondsAfterFinished }} - ttlSecondsAfterFinished: {{ . }} - {{- end }} + ttlSecondsAfterFinished: {{ .Values.certgen.ttlSecondsAfterFinished }} {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml index b49c00a6..697806c6 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/cronjob.yaml @@ -23,8 +23,6 @@ metadata: {{- end }} spec: schedule: {{ .Values.hubble.tls.auto.schedule | quote }} - successfulJobsHistoryLimit: {{ .Values.certgen.cronJob.successfulJobsHistoryLimit }} - failedJobsHistoryLimit: {{ .Values.certgen.cronJob.failedJobsHistoryLimit }} concurrencyPolicy: Forbid jobTemplate: {{- include "hubble-generate-certs.job.spec" . | nindent 4 }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml index 96371916..5e4e67ff 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-cronjob/job.yaml @@ -1,18 +1,9 @@ {{- if and .Values.hubble.enabled .Values.hubble.tls.enabled .Values.hubble.tls.auto.enabled (eq .Values.hubble.tls.auto.method "cronJob") }} -{{/* -Because Kubernetes job specs are immutable, Helm will fail patch this job if -the spec changes between releases. To avoid breaking the upgrade path, we -generate a name for the job here which is based on the checksum of the spec. -This will cause the name of the job to change if its content changes, -and in turn cause Helm to do delete the old job and replace it with a new one. -*/}} -{{- $jobSpec := include "hubble-generate-certs.job.spec" . -}} -{{- $checkSum := $jobSpec | sha256sum | trunc 10 -}} --- apiVersion: batch/v1 kind: Job metadata: - name: hubble-generate-certs-{{$checkSum}} + name: hubble-generate-certs namespace: {{ include "cilium.namespace" . }} labels: k8s-app: hubble-generate-certs @@ -21,14 +12,13 @@ metadata: {{- with .Values.commonLabels }} {{- toYaml . | nindent 4 }} {{- end }} - {{- if or .Values.certgen.annotations.job .Values.hubble.annotations }} annotations: + "helm.sh/hook": post-install,post-upgrade {{- with .Values.certgen.annotations.job }} - {{- toYaml . | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} {{- with .Values.hubble.annotations }} - {{- toYaml . | nindent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} - {{- end }} -{{ $jobSpec }} +{{ include "hubble-generate-certs.job.spec" . }} {{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/metrics-server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/metrics-server-secret.yaml index d334b986..0cc13efa 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/metrics-server-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/metrics-server-secret.yaml @@ -10,17 +10,13 @@ kind: Secret metadata: name: hubble-metrics-server-certs namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.hubble.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml index 6f001dc9..fa0c908e 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-client-secret.yaml @@ -17,17 +17,13 @@ kind: Secret metadata: name: hubble-relay-client-certs namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.hubble.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml index 229148a0..986b3cac 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/relay-server-secret.yaml @@ -10,17 +10,13 @@ kind: Secret metadata: name: hubble-relay-server-certs namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.hubble.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml index 4d214a56..b7bedb89 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/server-secret.yaml @@ -18,17 +18,13 @@ kind: Secret metadata: name: hubble-server-certs namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.hubble.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml index 8c1b40aa..e1f62ead 100644 --- a/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml +++ b/packages/system/cilium/charts/cilium/templates/hubble/tls-helm/ui-client-certs.yaml @@ -10,17 +10,13 @@ metadata: name: hubble-ui-client-certs namespace: {{ include "cilium.namespace" . }} - labels: {{- with .Values.commonLabels }} + labels: {{- toYaml . | nindent 4 }} {{- end }} - cilium.io/helm-template-non-idempotent: "true" - annotations: {{- with .Values.hubble.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.nonIdempotentAnnotations }} + annotations: {{- toYaml . | nindent 4 }} {{- end }} type: kubernetes.io/tls diff --git a/packages/system/cilium/charts/cilium/templates/standalone-dns-proxy/configmap.yaml b/packages/system/cilium/charts/cilium/templates/standalone-dns-proxy/configmap.yaml deleted file mode 100644 index 9d65c1a8..00000000 --- a/packages/system/cilium/charts/cilium/templates/standalone-dns-proxy/configmap.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if .Values.standaloneDnsProxy.enabled }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: standalone-dns-proxy-config - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - - {{- with .Values.standaloneDnsProxy.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -data: - # Use the same L7 proxy and DNS settings as the agent for consistency - enable-l7-proxy: {{ .Values.l7Proxy | quote }} - debug: {{ .Values.standaloneDnsProxy.debug | quote }} - enable-standalone-dns-proxy: {{ .Values.standaloneDnsProxy.enabled | quote }} - enable-ipv4: {{ .Values.ipv4.enabled | quote }} - enable-ipv6: {{ .Values.ipv6.enabled | quote }} - standalone-dns-proxy-server-port: {{ .Values.standaloneDnsProxy.serverPort | quote }} - # DNS proxy configuration inherited from agent settings - tofqdns-proxy-port: {{ .Values.dnsProxy.proxyPort | quote }} - tofqdns-enable-dns-compression: {{ .Values.dnsProxy.enableDnsCompression | quote }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/standalone-dns-proxy/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/standalone-dns-proxy/daemonset.yaml deleted file mode 100644 index 7ea150a4..00000000 --- a/packages/system/cilium/charts/cilium/templates/standalone-dns-proxy/daemonset.yaml +++ /dev/null @@ -1,80 +0,0 @@ -{{- if .Values.standaloneDnsProxy.enabled }} ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: standalone-dns-proxy - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.standaloneDnsProxy.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} - labels: - k8s-app: standalone-dns-proxy - app.kubernetes.io/part-of: cilium - app.kubernetes.io/name: standalone-dns-proxy - name: standalone-dns-proxy - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - minReadySeconds: 5 - {{- with .Values.standaloneDnsProxy.updateStrategy }} - updateStrategy: - {{- toYaml . | nindent 4 }} - {{- end }} - selector: - matchLabels: - k8s-app: standalone-dns-proxy - template: - metadata: - annotations: - {{- if .Values.standaloneDnsProxy.rollOutPods }} - # ensure pods roll when configmap updates - cilium.io/standalone-dns-proxy-configmap-checksum: {{ include (print $.Template.BasePath "/standalone-dns-proxy/configmap.yaml") . | sha256sum | quote }} - {{- end }} - container.apparmor.security.beta.kubernetes.io/standalone-dns-proxy: "unconfined" - labels: - k8s-app: standalone-dns-proxy - name: standalone-dns-proxy - app.kubernetes.io/name: standalone-dns-proxy - app.kubernetes.io/part-of: cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - hostNetwork: true - automountServiceAccountToken: {{ .Values.standaloneDnsProxy.automountServiceAccountToken }} - {{- with .Values.standaloneDnsProxy.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - tolerations: - - operator: Exists - {{- with .Values.standaloneDnsProxy.tolerations }} - {{- toYaml . | nindent 8 }} - {{- end }} - containers: - - name: standalone-dns-proxy - image: {{ include "cilium.image" .Values.standaloneDnsProxy.image | quote }} - args: - - --config-dir=/tmp/standalone-dns-proxy/config-map - imagePullPolicy: {{ .Values.standaloneDnsProxy.image.pullPolicy }} - volumeMounts: - - mountPath: /tmp/standalone-dns-proxy/config-map - name: standalone-dns-proxy-config-path - readOnly: true - - mountPath: /var/run/standalone-dns-proxy - name: runtime-dir - securityContext: - capabilities: - add: ["NET_ADMIN", "NET_RAW"] - drop: ["ALL"] - volumes: - - configMap: - defaultMode: 420 - name: standalone-dns-proxy-config - name: standalone-dns-proxy-config-path - - emptyDir: {} - name: runtime-dir -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/validate.yaml b/packages/system/cilium/charts/cilium/templates/validate.yaml index ac3164b6..4fff21a3 100644 --- a/packages/system/cilium/charts/cilium/templates/validate.yaml +++ b/packages/system/cilium/charts/cilium/templates/validate.yaml @@ -220,22 +220,3 @@ {{- end }} {{- end }} {{- end }} - -{{/* validate Standalone DNS Proxy */}} -{{- if .Values.standaloneDnsProxy.enabled }} - {{- if not .Values.dnsProxy.proxyPort }} - {{ fail "standaloneDnsProxy requires dnsProxy.proxyPort to be explicitly set (e.g., 10094)" }} - {{- end }} - {{- if eq (int .Values.dnsProxy.proxyPort) 0 }} - {{ fail "standaloneDnsProxy requires dnsProxy.proxyPort to be set to a non-zero value (e.g., 10094). The standalone DNS proxy uses the same DNS configuration as the agent." }} - {{- end }} -{{- end }} - -{{/* validate we don't run tproxy with netkit - see GH issue 39892 */}} -{{- if hasKey .Values "bpf" }} - {{- if and (hasKey .Values.bpf "tproxy") (hasKey .Values.bpf "datapathMode") }} - {{- if and (.Values.bpf.tproxy) (list "netkit" "netkit-l2" | has .Values.bpf.datapathMode) }} - {{ fail ".Values.bpf.tproxy cannot be enabled with .Values.bpf.datapathMode=netkit or .Values.bpf.datapathMode=netkit-l2" }} - {{- end }} - {{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/ztunnel/daemonset.yaml b/packages/system/cilium/charts/cilium/templates/ztunnel/daemonset.yaml deleted file mode 100644 index f9363068..00000000 --- a/packages/system/cilium/charts/cilium/templates/ztunnel/daemonset.yaml +++ /dev/null @@ -1,165 +0,0 @@ -{{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") }} ---- -kind: DaemonSet -apiVersion: apps/v1 -metadata: - name: ztunnel-cilium - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.encryption.ztunnel.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} - labels: - app: ztunnel-cilium - app.kubernetes.io/part-of: cilium - app.kubernetes.io/name: ztunnel-cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - revisionHistoryLimit: 10 - selector: - matchLabels: - app: ztunnel-cilium - {{- with .Values.encryption.ztunnel.updateStrategy }} - updateStrategy: - {{- toYaml . | trim | nindent 4 }} - {{- end }} - template: - metadata: - annotations: - sidecar.istio.io/inject: "false" - {{- with .Values.encryption.ztunnel.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - app: ztunnel-cilium - app.kubernetes.io/part-of: cilium - app.kubernetes.io/name: ztunnel-cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.encryption.ztunnel.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - hostNetwork: true - dnsPolicy: ClusterFirst - containers: - - name: istio-proxy - image: {{ include "cilium.image" .Values.encryption.ztunnel.image | quote }} - imagePullPolicy: {{ .Values.encryption.ztunnel.image.pullPolicy }} - args: - - proxy - - ztunnel - env: - - name: XDS_ADDRESS - value: "https://localhost:15012" - - name: XDS_ROOT_CA - value: "/etc/ztunnel/bootstrap-root.crt" - - name: CA_ROOT_CA - value: "/etc/ztunnel/bootstrap-root.crt" - - name: CA_ADDRESS - value: {{ .Values.encryption.ztunnel.caAddress | quote }} - - name: ISTIO_META_DNS_CAPTURE - value: "false" - - name: INPOD_UDS - value: "/var/run/cilium/ztunnel.sock" - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: ISTIO_META_ENABLE_HBONE - value: "true" - {{- with .Values.encryption.ztunnel.extraEnv }} - {{- toYaml . | trim | nindent 12 }} - {{- end }} - readinessProbe: - httpGet: - path: /healthz/ready - port: {{ .Values.encryption.ztunnel.healthPort }} - host: "127.0.0.1" - scheme: HTTP - initialDelaySeconds: {{ .Values.encryption.ztunnel.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.encryption.ztunnel.readinessProbe.periodSeconds }} - failureThreshold: {{ .Values.encryption.ztunnel.readinessProbe.failureThreshold }} - successThreshold: 1 - timeoutSeconds: 1 - {{- with .Values.encryption.ztunnel.resources }} - resources: - {{- toYaml . | trim | nindent 12 }} - {{- end }} - securityContext: - allowPrivilegeEscalation: true - capabilities: - add: - - NET_ADMIN - - SYS_ADMIN - - NET_RAW - drop: - - ALL - privileged: false - readOnlyRootFilesystem: true - runAsGroup: 1337 - runAsNonRoot: false - runAsUser: 0 - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - volumeMounts: - - mountPath: /var/run/cilium - name: cilium-dir - readOnly: false - - mountPath: /etc/ztunnel - name: cilium-ztunnel-secrets - readOnly: true - {{- with .Values.encryption.ztunnel.extraVolumeMounts }} - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.encryption.ztunnel.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.encryption.ztunnel.nodeSelector }} - nodeSelector: - {{- toYaml . | trim | nindent 8 }} - {{- end }} - {{- with .Values.encryption.ztunnel.tolerations }} - tolerations: - {{- toYaml . | trim | nindent 8 }} - {{- end }} - priorityClassName: {{ include "cilium.priorityClass" (list $ .Values.encryption.ztunnel.priorityClassName "system-node-critical") }} - restartPolicy: Always - terminationGracePeriodSeconds: {{ .Values.encryption.ztunnel.terminationGracePeriodSeconds }} - {{- if .Values.serviceAccounts.ztunnel.create }} - serviceAccountName: {{ .Values.serviceAccounts.ztunnel.name | quote }} - automountServiceAccountToken: {{ .Values.serviceAccounts.ztunnel.automount }} - {{- else }} - automountServiceAccountToken: false - {{- end }} - volumes: - - name: cilium-dir - hostPath: - path: /var/run/cilium - type: DirectoryOrCreate - - name: cilium-ztunnel-secrets - secret: - secretName: cilium-ztunnel-secrets - defaultMode: 420 - items: - - key: bootstrap-root.crt - path: bootstrap-root.crt - mode: 420 - {{- with .Values.encryption.ztunnel.extraVolumes }} - {{- toYaml . | nindent 8 }} - {{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/ztunnel/secret.yaml b/packages/system/cilium/charts/cilium/templates/ztunnel/secret.yaml deleted file mode 100644 index 520857dc..00000000 --- a/packages/system/cilium/charts/cilium/templates/ztunnel/secret.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") }} -{{- if .Values.encryption.ztunnel.secrets.bootstrapRootCert }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: cilium-ztunnel-secrets - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.encryption.ztunnel.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} - labels: - app.kubernetes.io/part-of: cilium - app.kubernetes.io/name: ztunnel-cilium - {{- with .Values.commonLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} -type: Opaque -data: - bootstrap-root.crt: {{ .Values.encryption.ztunnel.secrets.bootstrapRootCert | b64enc }} -{{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/templates/ztunnel/serviceaccount.yaml b/packages/system/cilium/charts/cilium/templates/ztunnel/serviceaccount.yaml deleted file mode 100644 index 4ef9e2bc..00000000 --- a/packages/system/cilium/charts/cilium/templates/ztunnel/serviceaccount.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if and .Values.encryption.enabled (eq .Values.encryption.type "ztunnel") .Values.serviceAccounts.ztunnel.create }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.serviceAccounts.ztunnel.name | quote }} - namespace: {{ include "cilium.namespace" . }} - {{- with .Values.commonLabels }} - labels: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if or .Values.serviceAccounts.ztunnel.annotations .Values.encryption.ztunnel.annotations }} - annotations: - {{- with .Values.encryption.ztunnel.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.serviceAccounts.ztunnel.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- end }} -{{- end }} diff --git a/packages/system/cilium/charts/cilium/values.schema.json b/packages/system/cilium/charts/cilium/values.schema.json index 65c84af5..fb1ea4c3 100644 --- a/packages/system/cilium/charts/cilium/values.schema.json +++ b/packages/system/cilium/charts/cilium/values.schema.json @@ -58,27 +58,6 @@ "properties": { "enabled": { "type": "boolean" - }, - "nodeSpec": { - "properties": { - "securityGroupTags": { - "items": {}, - "type": "array" - }, - "securityGroups": { - "items": {}, - "type": "array" - }, - "vSwitchTags": { - "items": {}, - "type": "array" - }, - "vSwitches": { - "items": {}, - "type": "array" - } - }, - "type": "object" } }, "type": "object" @@ -461,14 +440,6 @@ "properties": { "enabled": { "type": "boolean" - }, - "nodeSpec": { - "properties": { - "azureInterfaceName": { - "type": "string" - } - }, - "type": "object" } }, "type": "object" @@ -673,14 +644,6 @@ "monitorInterval": { "type": "string" }, - "monitorTraceIPOption": { - "minimum": 0, - "maximum": 255, - "type": [ - "null", - "integer" - ] - }, "natMax": { "type": [ "null", @@ -705,12 +668,6 @@ "integer" ] }, - "policyMapPressureMetricsThreshold": { - "type": [ - "null", - "number" - ] - }, "policyStatsMapMax": { "type": [ "null", @@ -757,17 +714,6 @@ }, "type": "object" }, - "cronJob": { - "properties": { - "failedJobsHistoryLimit": { - "type": "integer" - }, - "successfulJobsHistoryLimit": { - "type": "integer" - } - }, - "type": "object" - }, "extraVolumeMounts": { "items": {}, "type": "array" @@ -822,10 +768,7 @@ "type": "array" }, "ttlSecondsAfterFinished": { - "type": [ - "null", - "integer" - ] + "type": "integer" } }, "type": "object" @@ -1356,9 +1299,6 @@ "Cluster" ] }, - "externallyCreated": { - "type": "boolean" - }, "internalTrafficPolicy": { "enum": [ "Local", @@ -1429,6 +1369,17 @@ }, "type": "object" }, + "client": { + "properties": { + "cert": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "type": "object" + }, "enableSecrets": { "type": "boolean" }, @@ -1501,17 +1452,11 @@ }, "type": "object" }, - "cacheTTL": { - "type": "string" - }, "config": { "properties": { "clusters": { "items": {}, - "type": [ - "object", - "array" - ] + "type": "array" }, "domain": { "type": "string" @@ -1531,85 +1476,6 @@ "maxConnectedClusters": { "type": "integer" }, - "mcsapi": { - "properties": { - "corednsAutoConfigure": { - "properties": { - "affinity": { - "type": "object" - }, - "annotations": { - "type": "object" - }, - "coredns": { - "properties": { - "clusterDomain": { - "type": "string" - }, - "clustersetDomain": { - "type": "string" - }, - "configMapName": { - "type": "string" - }, - "deploymentName": { - "type": "string" - }, - "namespace": { - "type": "string" - }, - "serviceAccountName": { - "type": "string" - } - }, - "type": "object" - }, - "enabled": { - "type": "boolean" - }, - "extraArgs": { - "items": {}, - "type": "array" - }, - "extraVolumeMounts": { - "items": {}, - "type": "array" - }, - "extraVolumes": { - "items": {}, - "type": "array" - }, - "nodeSelector": { - "type": "object" - }, - "podLabels": { - "type": "object" - }, - "priorityClassName": { - "type": "string" - }, - "resources": { - "type": "object" - }, - "tolerations": { - "items": {}, - "type": "array" - }, - "ttlSecondsAfterFinished": { - "type": "integer" - } - }, - "type": "object" - }, - "enabled": { - "type": "boolean" - }, - "installCRDs": { - "type": "boolean" - } - }, - "type": "object" - }, "policyDefaultLocalCluster": { "type": "boolean" }, @@ -1671,27 +1537,10 @@ }, "resources": { "properties": { - "limits": { - "properties": { - "cpu": { - "type": [ - "integer", - "string" - ] - }, - "memory": { - "type": "string" - } - }, - "type": "object" - }, "requests": { "properties": { "cpu": { - "type": [ - "integer", - "string" - ] + "type": "string" }, "memory": { "type": "string" @@ -1714,21 +1563,6 @@ "object" ] }, - "configDriftDetection": { - "properties": { - "driftChecker": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "ignoredKeys": { - "items": {}, - "type": "array" - } - }, - "type": "object" - }, "connectivityProbeFrequencyRatio": { "type": [ "null", @@ -1744,6 +1578,14 @@ "crdWaitTimeout": { "type": "string" }, + "customCalls": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, "daemon": { "properties": { "allowedConfigOverrides": { @@ -1907,9 +1749,6 @@ "enableMasqueradeRouteSource": { "type": "boolean" }, - "enableNoServiceEndpointsRoutable": { - "type": "boolean" - }, "enableNonDefaultDenyPolicies": { "type": "boolean" }, @@ -1958,30 +1797,8 @@ "cidr": { "type": "string" }, - "egress": { - "properties": { - "allowRemoteNodeIdentities": { - "type": "boolean" - }, - "cidr": { - "type": "string" - }, - "enabled": { - "type": "boolean" - } - }, - "type": "object" - }, "enabled": { "type": "boolean" - }, - "ingress": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" } }, "type": "object" @@ -1996,184 +1813,6 @@ } }, "type": "object" - }, - "ztunnel": { - "properties": { - "affinity": { - "type": "object" - }, - "annotations": { - "type": "object" - }, - "caAddress": { - "type": "string" - }, - "extraEnv": { - "items": {}, - "type": "array" - }, - "extraVolumeMounts": { - "items": {}, - "type": "array" - }, - "extraVolumes": { - "items": {}, - "type": "array" - }, - "healthPort": { - "type": "integer" - }, - "image": { - "properties": { - "digest": { - "type": [ - "null", - "string" - ] - }, - "override": { - "type": [ - "null", - "string" - ] - }, - "pullPolicy": { - "type": "string" - }, - "repository": { - "type": "string" - }, - "tag": { - "type": "string" - }, - "useDigest": { - "type": "boolean" - } - }, - "type": "object" - }, - "nodeSelector": { - "properties": { - "kubernetes.io/os": { - "type": "string" - } - }, - "type": "object" - }, - "podAnnotations": { - "type": "object" - }, - "podLabels": { - "type": "object" - }, - "priorityClassName": { - "type": [ - "null", - "string" - ] - }, - "readinessProbe": { - "properties": { - "failureThreshold": { - "type": "integer" - }, - "initialDelaySeconds": { - "type": "integer" - }, - "periodSeconds": { - "type": "integer" - } - }, - "type": "object" - }, - "resources": { - "properties": { - "requests": { - "properties": { - "cpu": { - "type": "string" - }, - "memory": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "secrets": { - "properties": { - "bootstrapRootCert": { - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, - "terminationGracePeriodSeconds": { - "type": "integer" - }, - "tolerations": { - "items": { - "anyOf": [ - { - "properties": { - "effect": { - "type": "string" - }, - "operator": { - "type": "string" - } - } - }, - { - "properties": { - "key": { - "type": "string" - }, - "operator": { - "type": "string" - } - } - }, - { - "properties": { - "effect": { - "type": "string" - }, - "operator": { - "type": "string" - } - } - } - ] - }, - "type": "array" - }, - "updateStrategy": { - "properties": { - "rollingUpdate": { - "properties": { - "maxSurge": { - "type": "integer" - }, - "maxUnavailable": { - "type": "integer" - } - }, - "type": "object" - }, - "type": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" } }, "type": "object" @@ -2189,9 +1828,6 @@ "endpointLockdownOnMapOverflow": { "type": "boolean" }, - "endpointPolicyUpdateTimeoutDuration": { - "type": "null" - }, "endpointRoutes": { "properties": { "enabled": { @@ -2233,49 +1869,6 @@ "items": {}, "type": "array" }, - "nodeSpec": { - "properties": { - "deleteOnTermination": { - "type": [ - "null", - "boolean" - ] - }, - "disablePrefixDelegation": { - "type": "boolean" - }, - "excludeInterfaceTags": { - "items": {}, - "type": "array" - }, - "firstInterfaceIndex": { - "type": [ - "null", - "integer" - ] - }, - "securityGroupTags": { - "items": {}, - "type": "array" - }, - "securityGroups": { - "items": {}, - "type": "array" - }, - "subnetIDs": { - "items": {}, - "type": "array" - }, - "subnetTags": { - "items": {}, - "type": "array" - }, - "usePrimaryAddress": { - "type": "boolean" - } - }, - "type": "object" - }, "subnetIDsFilter": { "items": {}, "type": "array" @@ -2418,12 +2011,6 @@ "string" ] }, - "clusterMaxConnections": { - "type": "integer" - }, - "clusterMaxRequests": { - "type": "integer" - }, "connectTimeoutSeconds": { "type": "integer" }, @@ -2517,10 +2104,6 @@ }, "type": "object" }, - "initContainers": { - "items": {}, - "type": "array" - }, "initialFetchTimeoutSeconds": { "type": "integer" }, @@ -2588,9 +2171,6 @@ "maxConnectionDurationSeconds": { "type": "integer" }, - "maxGlobalDownstreamConnections": { - "type": "integer" - }, "maxRequestsPerConnection": { "type": "integer" }, @@ -2813,9 +2393,6 @@ }, "type": "object" }, - "useOriginalSourceAddress": { - "type": "boolean" - }, "xffNumTrustedHopsL7PolicyEgress": { "type": "integer" }, @@ -3037,17 +2614,10 @@ "anyOf": [ { "properties": { - "aggregationInterval": { - "type": "string" - }, "excludeFilters": { "items": {}, "type": "array" }, - "fieldAggregate": { - "items": {}, - "type": "array" - }, "fieldMask": { "items": {}, "type": "array" @@ -3091,9 +2661,6 @@ }, "static": { "properties": { - "aggregationInterval": { - "type": "string" - }, "allowList": { "items": {}, "type": "array" @@ -3105,10 +2672,6 @@ "enabled": { "type": "boolean" }, - "fieldAggregate": { - "items": {}, - "type": "array" - }, "fieldMask": { "items": {}, "type": "array" @@ -3474,23 +3037,6 @@ "listenPort": { "type": "string" }, - "logOptions": { - "properties": { - "format": { - "type": [ - "null", - "string" - ] - }, - "level": { - "type": [ - "null", - "string" - ] - } - }, - "type": "object" - }, "nodeSelector": { "properties": { "kubernetes.io/os": { @@ -3554,15 +3100,9 @@ "address": { "type": "string" }, - "blockProfileRate": { - "type": "integer" - }, "enabled": { "type": "boolean" }, - "mutexProfileFraction": { - "type": "integer" - }, "port": { "type": "integer" } @@ -4140,9 +3680,6 @@ }, "type": "object" }, - "tmpVolume": { - "type": "object" - }, "tolerations": { "items": {}, "type": "array" @@ -4384,33 +3921,6 @@ "multiPoolPreAllocation": { "type": "string" }, - "nodeSpec": { - "properties": { - "ipamMaxAllocate": { - "type": [ - "null", - "integer" - ] - }, - "ipamMinAllocate": { - "type": [ - "null", - "integer" - ] - }, - "ipamPreAllocate": { - "type": [ - "null", - "integer" - ] - }, - "ipamStaticIPTags": { - "items": {}, - "type": "array" - } - }, - "type": "object" - }, "operator": { "properties": { "autoCreateCiliumPodIPPools": { @@ -4677,9 +4187,6 @@ } }, "type": "object" - }, - "serviceTopology": { - "type": "boolean" } }, "type": "object" @@ -4771,6 +4278,9 @@ }, "enableHealthCheckLoadBalancerIP": { "type": "boolean" + }, + "enabled": { + "type": "boolean" } }, "type": "object" @@ -4884,10 +4394,7 @@ "requests": { "properties": { "cpu": { - "type": [ - "integer", - "string" - ] + "type": "string" }, "memory": { "type": "string" @@ -4979,9 +4486,6 @@ } }, "type": "object" - }, - "waitForCloudInit": { - "type": "boolean" } }, "type": "object" @@ -5190,15 +4694,9 @@ "address": { "type": "string" }, - "blockProfileRate": { - "type": "integer" - }, "enabled": { "type": "boolean" }, - "mutexProfileFraction": { - "type": "integer" - }, "port": { "type": "integer" } @@ -5256,30 +4754,6 @@ } }, "type": "object" - }, - "tls": { - "properties": { - "enabled": { - "type": "boolean" - }, - "server": { - "properties": { - "existingSecret": { - "type": "string" - }, - "mtls": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "type": "object" - } - }, - "type": "object" - } - }, - "type": "object" } }, "type": "object" @@ -5392,12 +4866,6 @@ }, "restart": { "type": "boolean" - }, - "selector": { - "type": [ - "null", - "string" - ] } }, "type": "object" @@ -5434,9 +4902,6 @@ "properties": { "enabled": { "type": "boolean" - }, - "packetizationLayerPMTUDMode": { - "type": "string" } }, "type": "object" @@ -5475,9 +4940,6 @@ "array" ] }, - "policyDenyResponse": { - "type": "string" - }, "policyEnforcementMode": { "type": "string" }, @@ -5486,15 +4948,9 @@ "address": { "type": "string" }, - "blockProfileRate": { - "type": "integer" - }, "enabled": { "type": "boolean" }, - "mutexProfileFraction": { - "type": "integer" - }, "port": { "type": "integer" } @@ -5907,9 +5363,6 @@ "secretsNamespaceAnnotations": { "type": "object" }, - "secretsNamespaceLabels": { - "type": "object" - }, "securityContext": { "properties": { "allowPrivilegeEscalation": { @@ -5969,9 +5422,6 @@ { "type": "string" }, - { - "type": "string" - }, { "type": "string" } @@ -6087,23 +5537,6 @@ }, "type": "object" }, - "corednsMCSAPI": { - "properties": { - "annotations": { - "type": "object" - }, - "automount": { - "type": "boolean" - }, - "create": { - "type": "boolean" - }, - "name": { - "type": "string" - } - }, - "type": "object" - }, "envoy": { "properties": { "annotations": { @@ -6225,23 +5658,6 @@ } }, "type": "object" - }, - "ztunnel": { - "properties": { - "annotations": { - "type": "object" - }, - "automount": { - "type": "boolean" - }, - "create": { - "type": "boolean" - }, - "name": { - "type": "string" - } - }, - "type": "object" } }, "type": "object" @@ -6260,86 +5676,6 @@ }, "type": "object" }, - "standaloneDnsProxy": { - "properties": { - "annotations": { - "type": "object" - }, - "automountServiceAccountToken": { - "type": "boolean" - }, - "debug": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "image": { - "properties": { - "digest": { - "type": "string" - }, - "override": { - "type": [ - "null", - "string" - ] - }, - "pullPolicy": { - "type": "string" - }, - "repository": { - "type": "string" - }, - "tag": { - "type": "string" - }, - "useDigest": { - "type": "boolean" - } - }, - "type": "object" - }, - "nodeSelector": { - "properties": { - "kubernetes.io/os": { - "type": "string" - } - }, - "type": "object" - }, - "rollOutPods": { - "type": "boolean" - }, - "serverPort": { - "type": "integer" - }, - "tolerations": { - "items": {}, - "type": "array" - }, - "updateStrategy": { - "properties": { - "rollingUpdate": { - "properties": { - "maxSurge": { - "type": "integer" - }, - "maxUnavailable": { - "type": "integer" - } - }, - "type": "object" - }, - "type": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, "startupProbe": { "properties": { "failureThreshold": { @@ -6351,6 +5687,9 @@ }, "type": "object" }, + "svcSourceRangeCheck": { + "type": "boolean" + }, "synchronizeK8sNodes": { "type": "boolean" }, @@ -6435,9 +5774,6 @@ }, "type": "object" }, - "tmpVolume": { - "type": "object" - }, "tolerations": { "items": { "anyOf": [ diff --git a/packages/system/cilium/charts/cilium/values.yaml b/packages/system/cilium/charts/cilium/values.yaml index 66f76982..eff7f902 100644 --- a/packages/system/cilium/charts/cilium/values.yaml +++ b/packages/system/cilium/charts/cilium/values.yaml @@ -6,6 +6,7 @@ # type: [null, string] # @schema # -- namespaceOverride allows to override the destination namespace for Cilium resources. +# This property allows to use Cilium as part of an Umbrella Chart with different targets. namespaceOverride: "" # @schema # type: [null, object] @@ -28,7 +29,7 @@ debug: # @schema # -- Configure verbosity levels for debug logging # This option is used to enable debug messages for operations related to such - # sub-system such as (e.g. kvstore, envoy, datapath, policy, or tagged), and flow is + # sub-system such as (e.g. kvstore, envoy, datapath or policy), and flow is # for enabling debug messages emitted per request, message and connection. # Multiple values can be set via a space-separated string (e.g. "datapath envoy"). # @@ -38,7 +39,6 @@ debug: # - envoy # - datapath # - policy - # - tagged verbose: ~ # -- Set the agent-internal metrics sampling frequency. This sets the # frequency of the internal sampling of the agent metrics. These are @@ -204,18 +204,6 @@ serviceAccounts: name: hubble-generate-certs automount: true annotations: {} - # -- CorednsMCSAPI is used if clustermesh.mcsapi.corednsAutoConfigure.enabled=true - corednsMCSAPI: - create: true - name: cilium-coredns-mcsapi-autoconfig - automount: true - annotations: {} - # -- Ztunnel is used if encryption.type=ztunnel - ztunnel: - create: true - name: ztunnel-cilium - automount: false - annotations: {} # -- Configure termination grace period for cilium-agent DaemonSet. terminationGracePeriodSeconds: 1 # -- Install the cilium agent resources. @@ -224,22 +212,6 @@ agent: true name: cilium # -- Roll out cilium agent pods automatically when configmap is updated. rollOutCiliumPods: false -# -- Configuration for the ConfigMap drift detection feature. -# When enabled, the agent continuously watches the cilium-config ConfigMap -# and exposes a cilium_drift_checker_config_delta Prometheus metric reporting -# the number of keys that differ between the ConfigMap and the agent's active -# settings. A non-zero value indicates that the agent has not yet applied all -# current ConfigMap changes and needs to be restarted. -configDriftDetection: - # -- Enable watching of the cilium-config ConfigMap and reflecting its - # contents into the agent's internal DynamicConfig table. - enabled: true - # -- Enable the drift checker which compares the DynamicConfig table against - # the agent's active settings and publishes the - # cilium_drift_checker_config_delta metric. - driftChecker: true - # -- List of config-map keys to ignore when computing the drift delta. - ignoredKeys: [] # -- Agent container image. image: # @schema @@ -247,10 +219,10 @@ image: # @schema override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.19.3" + tag: "v1.18.6" pullPolicy: "IfNotPresent" # cilium-digest - digest: sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10 + digest: sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4 useDigest: true # -- Scheduling configurations for cilium pods scheduling: @@ -391,8 +363,6 @@ securityContext: - SETGID # Allow to execute program that changes UID (e.g. required for package installation) - SETUID - # Allow to read dmesg and get kernel pointers when kptr_restrict=1 - - SYSLOG # -- Capabilities for the `mount-cgroup` init container mountCgroup: # Only used for 'mount' cgroup @@ -463,16 +433,9 @@ azure: # clientID: 00000000-0000-0000-0000-000000000000 # clientSecret: 00000000-0000-0000-0000-000000000000 # userAssignedIdentityID: 00000000-0000-0000-0000-000000000000 - nodeSpec: - azureInterfaceName: "" alibabacloud: # -- Enable AlibabaCloud ENI integration enabled: false - nodeSpec: - vSwitches: [] - vSwitchTags: [] - securityGroups: [] - securityGroupTags: [] # -- Enable bandwidth manager to optimize TCP and UDP workloads and allow # for rate-limiting traffic from individual Pods with EDT (Earliest Departure # Time) through the "kubernetes.io/egress-bandwidth" Pod annotation. @@ -505,7 +468,8 @@ l2podAnnouncements: interface: "eth0" # -- A regular expression matching interfaces used for sending Gratuitous ARP pod announcements # interfacePattern: "" -# -- This feature set enables virtual BGP routers to be created via BGP CRDs. +# -- This feature set enables virtual BGP routers to be created via +# CiliumBGPPeeringPolicy CRDs. bgpControlPlane: # -- Enables the BGP control plane. enabled: false @@ -515,9 +479,9 @@ bgpControlPlane: create: false # -- The name of the secret namespace to which Cilium agents are given read access name: kube-system - # -- Status reporting settings + # -- Status reporting settings (BGPv2 only) statusReport: - # -- Enable/Disable BGP status reporting + # -- Enable/Disable BGPv2 status reporting # It is recommended to enable status reporting in general, but if you have any issue # such as high API server load, you can disable it by setting this to false. enabled: true @@ -527,7 +491,7 @@ bgpControlPlane: mode: "default" # -- IP pool to allocate the BGP router-id from when the mode is ip-pool. ipPool: "" - # -- Legacy BGP ORIGIN attribute settings + # -- Legacy BGP ORIGIN attribute settings (BGPv2 only) legacyOriginAttribute: # -- Enable/Disable advertising LoadBalancerIP routes with the legacy # BGP ORIGIN attribute value INCOMPLETE (2) instead of the default IGP (0). @@ -537,11 +501,6 @@ pmtuDiscovery: # -- Enable path MTU discovery to send ICMP fragmentation-needed replies to # the client. enabled: false - # -- Enable kernel probing path MTU discovery for Pods which uses different message - # sizes to search for correct MTU value. - # Valid values are: always, blackhole, disabled and unset (or empty). If value - # is 'unset' or left empty then will not try to override setting. - packetizationLayerPMTUDMode: "blackhole" bpf: autoMount: # -- Enable automatic mount of BPF filesystem @@ -589,7 +548,7 @@ bpf: # Helm configuration for BPF events map rate limiting is experimental and might change # in upcoming releases. events: - # -- Default settings for all types of events except dbg. + # -- Default settings for all types of events except dbg and pcap. default: # @schema # type: [null, integer] @@ -649,12 +608,6 @@ bpf: # type: [null, integer] # @schema policyMapMax: 16384 - # -- (float64) Configure threshold for emitting pressure metrics of policy maps. - # @schema - # type: [null, number] - # @schema - # @default -- `0.1` - policyMapPressureMetricsThreshold: ~ # -- Configure the maximum number of entries in global policy stats map. # @schema # type: [null, integer] @@ -712,8 +665,7 @@ bpf: # type: [null, boolean] # @schema # -- (bool) Configure the eBPF-based TPROXY (beta) to reduce reliance on iptables rules - # for implementing Layer 7 policy. Note this is incompatible with netkit (`bpf.datapathMode=netkit`, - # `bpf.datapathMode=netkit-l2`). + # for implementing Layer 7 policy. # @default -- `false` tproxy: ~ # @schema @@ -723,15 +675,6 @@ bpf: # [0] will allow all VLAN id's without any filtering. # @default -- `[]` vlanBypass: ~ - # -- Configure the IP tracing option type. - # This option is used to specify the IP option type to use for tracing. - # The value must be an integer between 0 and 255. - # @schema - # type: [null, integer] - # minimum: 0 - # maximum: 255 - # @schema - monitorTraceIPOption: 0 # -- (bool) Disable ExternalIP mitigation (CVE-2020-8554) # @default -- `false` disableExternalIPMitigation: false @@ -739,8 +682,7 @@ bpf: # supported kernels. # @default -- `true` enableTCX: true - # -- (string) Mode for Pod devices for the core datapath (veth, netkit, netkit-l2). - # Note netkit is incompatible with TPROXY (`bpf.tproxy`). + # -- (string) Mode for Pod devices for the core datapath (veth, netkit, netkit-l2) # @default -- `veth` datapathMode: veth # -- Enable BPF clock source probing for more efficient tick retrieval. @@ -828,17 +770,8 @@ cni: # -- Specifies the resources for the cni initContainer resources: requests: - # @schema - # type: [integer, string] - # @schema cpu: 100m memory: 10Mi - limits: - # @schema - # type: [integer, string] - # @schema - cpu: 1 - memory: 1Gi # -- Enable route MTU for pod netns when CNI chaining is used enableRouteMTUForCNIChaining: false # -- Enable the removal of iptables rules created by the AWS CNI VPC plugin. @@ -863,6 +796,10 @@ conntrackGCMaxInterval: "" # -- (string) Configure timeout in which Cilium will exit if CRDs are not available # @default -- `"5m"` crdWaitTimeout: "" +# -- Tail call hooks for custom eBPF programs. +customCalls: + # -- Enable tail call hooks for custom eBPF programs. + enabled: false daemon: # -- Configure where Cilium runtime state should be stored. runPath: "/var/run/cilium" @@ -905,12 +842,6 @@ daemon: # # By default, this functionality is enabled enableSourceIPVerification: true -# -- Configure temporary volume for cilium-agent -tmpVolume: {} -# emptyDir: -# sizeLimit: "100Mi" -# medium: "Memory" - # -- Specify which network interfaces can run the eBPF datapath. This means # that a packet sent from a pod to a destination outside the cluster will be # masqueraded (to an output device IPv4 address), if the output device runs the @@ -929,6 +860,9 @@ forceDeviceDetection: false # -- Enable setting identity mark for local traffic. # enableIdentityMark: true +# -- Enable Kubernetes EndpointSlice feature in Cilium if the cluster supports it. +# enableK8sEndpointSlice: true + # -- CiliumEndpointSlice configuration options. ciliumEndpointSlice: # -- Enable Cilium EndpointSlice feature. @@ -1108,33 +1042,20 @@ enableXTSocketFallback: true encryption: # -- Enable transparent network encryption. enabled: false - # -- Encryption method. Can be one of ipsec, wireguard or ztunnel. + # -- Encryption method. Can be either ipsec or wireguard. type: ipsec # -- Enable encryption for pure node to node traffic. # This option is only effective when encryption.type is set to "wireguard". nodeEncryption: false - # -- Configure the Encryption Pod2Pod strict mode. + # -- Configure the WireGuard Pod2Pod strict mode. strictMode: - # -- Enable Encryption Pod2Pod strict mode. (deprecated: please use encryption.strictMode.egress.enabled) + # -- Enable WireGuard Pod2Pod strict mode. enabled: false - # -- CIDR for the Encryption Pod2Pod strict mode. (deprecated: please use encryption.strictMode.egress.cidr) + # -- CIDR for the WireGuard Pod2Pod strict mode. cidr: "" - # -- Allow dynamic lookup of remote node identities. (deprecated: please use encryption.strictMode.egress.allowRemoteNodeIdentities) + # -- Allow dynamic lookup of remote node identities. # This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. allowRemoteNodeIdentities: false - egress: - # -- Enable strict egress encryption. - enabled: false - # -- CIDR for the Encryption Pod2Pod strict egress mode. - cidr: "" - # -- Allow dynamic lookup of remote node identities. - # This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. - allowRemoteNodeIdentities: false - ingress: - # -- Enable strict ingress encryption. - # When enabled, all unencrypted overlay ingress traffic will be dropped. - # This option is only applicable when WireGuard and tunneling are enabled. - enabled: false ipsec: # -- Name of the key file inside the Kubernetes secret configured via secretName. keyFile: keys @@ -1155,89 +1076,9 @@ encryption: wireguard: # -- Controls WireGuard PersistentKeepalive option. Set 0s to disable. persistentKeepalive: 0s - # -- ztunnel encryption configuration. - # ztunnel is Istio's purpose-built, per-node proxy for handling L4 traffic in ambient mesh mode. - # These settings only apply when encryption.type is set to "ztunnel". - ztunnel: - # -- ztunnel container image. - image: - # @schema - # type: [null, string] - # @schema - override: ~ - repository: "docker.io/istio/ztunnel" - tag: "1.28.0-distroless" - pullPolicy: "IfNotPresent" - # @schema - # type: [null, string] - # @schema - digest: ~ - useDigest: false - # -- CA server address for certificate requests. - caAddress: "https://localhost:15012" - # -- TCP port for the health API. - healthPort: 15021 - # -- ztunnel resource limits & requests. - resources: - requests: - cpu: 200m - memory: 512Mi - # -- ztunnel update strategy. - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - # -- Configure termination grace period for ztunnel DaemonSet. - terminationGracePeriodSeconds: 30 - # -- Readiness probe configuration. - readinessProbe: - initialDelaySeconds: 0 - periodSeconds: 10 - failureThreshold: 3 - # -- Node selector for ztunnel pods. - nodeSelector: - kubernetes.io/os: linux - # -- Node tolerations for ztunnel scheduling. - tolerations: - - effect: NoSchedule - operator: Exists - - key: CriticalAddonsOnly - operator: Exists - - effect: NoExecute - operator: Exists - # -- Affinity for ztunnel pods. - affinity: {} - # @schema - # type: [null, string] - # @schema - # -- The priority class to use for ztunnel pods. - priorityClassName: ~ - # -- Annotations to be added to all ztunnel resources. - annotations: {} - # -- Annotations to be added to ztunnel pods. - podAnnotations: {} - # -- Labels to be added to ztunnel pods. - podLabels: {} - # -- Additional ztunnel container environment variables. - extraEnv: [] - # -- Additional ztunnel volumes. - extraVolumes: [] - # -- Additional ztunnel volumeMounts. - extraVolumeMounts: [] - # -- ztunnel secrets configuration. - secrets: - # -- Base64-encoded bootstrap root certificate content. - # If not provided, the secret must be created manually before deploying. - # @schema - # type: [null, string] - # @schema - bootstrapRootCert: ~ endpointHealthChecking: # -- Enable connectivity health checking between virtual endpoints. enabled: true -# -- Max duration to wait for envoy to respond to configuration changes. Default "10s". -endpointPolicyUpdateTimeoutDuration: null endpointRoutes: # @schema # type: [boolean, string] @@ -1286,32 +1127,6 @@ eni: # -- Filter via AWS EC2 Instance tags (k=v) which will dictate which AWS EC2 Instances # are going to be used to create new ENIs instanceTagsFilter: [] - # -- NodeSpec configuration for the ENI - nodeSpec: - # -- First interface index to use for IP allocation - # @schema - # type: [null, integer] - # @schema - firstInterfaceIndex: ~ - # -- Subnet IDs to use for IP allocation - subnetIDs: [] - # -- Subnet tags to use for IP allocation - subnetTags: [] - # -- Security groups to use for IP allocation - securityGroups: [] - # -- Security group tags to use for IP allocation - securityGroupTags: [] - # -- Exclude interface tags to use for IP allocation - excludeInterfaceTags: [] - # -- Use primary address for IP allocation - usePrimaryAddress: false - # -- Disable prefix delegation for IP allocation - disablePrefixDelegation: false - # -- Delete ENI on termination - # @schema - # type: [null, boolean] - # @schema - deleteOnTermination: ~ # fragmentTracking enables IPv4 fragment tracking support in the datapath. # fragmentTracking: true gke: @@ -1327,8 +1142,6 @@ healthCheckICMPFailureThreshold: 3 hostFirewall: # -- Enables the enforcement of host policies in the eBPF datapath. enabled: false -# -- Enable routing to a service that has zero endpoints -enableNoServiceEndpointsRoutable: true # -- Configure socket LB socketLB: # -- Enable socket LB @@ -1352,15 +1165,12 @@ certgen: # @schema override: ~ repository: "quay.io/cilium/certgen" - tag: "v0.4.1" - digest: "sha256:f0c656830e856d26b24b0e144df1f8b327d3b46748d76a630514111fc365b697" + tag: "v0.3.1" + digest: "sha256:2825dbfa6f89cbed882fd1d81e46a56c087e35885825139923aa29eb8aec47a9" useDigest: true pullPolicy: "IfNotPresent" - # @schema - # type: [null, integer] - # @schema # -- Seconds after which the completed job pod will be deleted - ttlSecondsAfterFinished: null + ttlSecondsAfterFinished: 1800 # -- Labels to be added to hubble-certgen pods podLabels: {} # -- Annotations to be added to the hubble-certgen initial Job and CronJob @@ -1385,11 +1195,6 @@ certgen: extraVolumeMounts: [] # -- Affinity for certgen affinity: {} - cronJob: - # -- The number of successful finished jobs to keep - successfulJobsHistoryLimit: 3 - # -- The number of failed finished jobs to keep - failedJobsHistoryLimit: 1 hubble: # -- Enable Hubble (true by default). enabled: true @@ -1405,9 +1210,6 @@ hubble: # 2047, 4095, 8191, 16383, 32767, 65535 # eventBufferCapacity: "4095" - # -- The interval at which Hubble will send out lost events from the Observer server, if any. - # lostEventSendInterval: 1s - # -- Hubble metrics configuration. # See https://docs.cilium.io/en/stable/observability/metrics/#hubble-metrics # for more comprehensive documentation about Hubble metrics. @@ -1701,9 +1503,9 @@ hubble: # @schema override: ~ repository: "quay.io/cilium/hubble-relay" - tag: "v1.19.3" + tag: "v1.18.6" # hubble-relay-digest - digest: sha256:5ee21d57b6ef2aa6db67e603a735fdceb162454b352b7335b651456e308f681b + digest: sha256:fb6135e34c31e5f175cb5e75f86cea52ef2ff12b49bcefb7088ed93f5009eb8e useDigest: true pullPolicy: "IfNotPresent" # -- Specifies the resources for the hubble-relay pods @@ -1914,24 +1716,6 @@ hubble: address: localhost # -- Configure pprof listen port for hubble-relay port: 6062 - # -- Enable mutex contention profiling for hubble-relay and set the fraction of sampled events (set to 1 to sample all events) - mutexProfileFraction: 0 - # -- Enable goroutine blocking profiling for hubble-relay and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) - blockProfileRate: 0 - # -- Logging configuration for hubble-relay. - logOptions: - # @schema - # type: [null, string] - # @schema - # -- Log format for hubble-relay. Valid values are: text, text-ts, json, json-ts. - # @default -- text-ts - format: ~ - # @schema - # type: [null, string] - # @schema - # -- Log level for hubble-relay. Valid values are: debug, info, warn, error. - # @default -- info - level: ~ ui: # -- Whether to enable the Hubble UI. enabled: false @@ -2127,11 +1911,6 @@ hubble: # - secretName: chart-example-tls # hosts: # - chart-example.local - # -- Configure temporary volume for hubble-ui - tmpVolume: {} - # emptyDir: - # # sizeLimit: "100Mi" - # # medium: "Memory" # -- Hubble flows export. export: # --- Static exporter configuration. @@ -2144,14 +1923,6 @@ hubble: # - source # - destination # - verdict - fieldAggregate: [] - # - time - # - source - # - destination - # - verdict - # --- Defines the interval at which to aggregate before exporting Hubble flows. - # Aggregation feature is only enabled when fieldAggregate is specified and aggregationInterval > 0s. - aggregationInterval: "0s" allowList: [] # - '{"verdict":["DROPPED","ERROR"]}' denyList: [] @@ -2177,8 +1948,6 @@ hubble: content: - name: all fieldMask: [] - fieldAggregate: [] - aggregationInterval: "0s" includeFilters: [] excludeFilters: [] filePath: "/var/run/cilium/hubble/events.log" @@ -2271,30 +2040,11 @@ ipam: # refill the bucket up to the burst size capacity. # @default -- `4.0` externalAPILimitQPS: ~ - # -- NodeSpec configuration for the IPAM - nodeSpec: - # -- IPAM min allocate - # @schema - # type: [null, integer] - # @schema - ipamMinAllocate: ~ - # -- IPAM pre allocate - # @schema - # type: [null, integer] - # @schema - ipamPreAllocate: ~ - # -- IPAM max allocate - # @schema - # type: [null, integer] - # @schema - ipamMaxAllocate: ~ - # -- IPAM static IP tags (currently only works with AWS and Azure) - ipamStaticIPTags: [] +# -- defaultLBServiceIPAM indicates the default LoadBalancer Service IPAM when +# no LoadBalancer class is set. Applicable values: lbipam, nodeipam, none # @schema # type: [string] # @schema -# -- defaultLBServiceIPAM indicates the default LoadBalancer Service IPAM when -# no LoadBalancer class is set. Applicable values: lbipam, nodeipam, none defaultLBServiceIPAM: lbipam nodeIPAM: # -- Configure Node IPAM @@ -2405,7 +2155,7 @@ maglev: {} # type: [null, boolean] # @schema # -- (bool) Enables masquerading of IPv4 traffic leaving the node from endpoints. -# @default -- `true` unless ipam eni mode is active +# @default -- `true` unless ipam eni mode is active enableIPv4Masquerade: ~ # -- Enables masquerading of IPv6 traffic leaving the node from endpoints. enableIPv6Masquerade: true @@ -2492,7 +2242,8 @@ loadBalancer: # -- serviceTopology enables K8s Topology Aware Hints -based service # endpoints filtering - serviceTopology: false + # serviceTopology: false + # -- L7 LoadBalancer l7: # -- Enable L7 service load balancing via envoy proxy. @@ -2515,6 +2266,8 @@ loadBalancer: algorithm: round_robin # -- Configure N-S k8s service loadbalancing nodePort: + # -- Enable the Cilium NodePort service implementation. + enabled: false # -- Port range to use for NodePort services. # range: "30000,32767" @@ -2558,10 +2311,6 @@ pprof: address: localhost # -- Configure pprof listen port for cilium-agent port: 6060 - # -- Enable mutex contention profiling for cilium-agent and set the fraction of sampled events (set to 1 to sample all events) - mutexProfileFraction: 0 - # -- Enable goroutine blocking profiling for cilium-agent and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) - blockProfileRate: 0 # -- Configure prometheus metrics on the configured port at /metrics prometheus: metricsService: false @@ -2686,12 +2435,6 @@ envoy: initialFetchTimeoutSeconds: 30 # -- Maximum number of concurrent retries on Envoy clusters maxConcurrentRetries: 128 - # -- Maximum number of connections on Envoy clusters - clusterMaxConnections: 1024 - # -- Maximum number of requests on Envoy clusters - clusterMaxRequests: 1024 - # -- Maximum number of global downstream connections - maxGlobalDownstreamConnections: 50000 # -- Maximum number of retries for each HTTP request httpRetryCount: 3 # -- ProxyMaxRequestsPerConnection specifies the max_requests_per_connection setting for Envoy @@ -2708,9 +2451,6 @@ envoy: xffNumTrustedHopsL7PolicyIngress: 0 # -- Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the egress L7 policy enforcement Envoy listeners. xffNumTrustedHopsL7PolicyEgress: 0 - # -- For cases when CiliumEnvoyConfig is not used directly (Ingress, Gateway), configures Cilium BPF Metadata listener filter - # to use the original source address when extracting the metadata for a request. - useOriginalSourceAddress: true # @schema # type: [null, string] # @schema @@ -2725,12 +2465,10 @@ envoy: # @schema override: ~ repository: "quay.io/cilium/cilium-envoy" - tag: "v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa" + tag: "v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9" pullPolicy: "IfNotPresent" - digest: "sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d" + digest: "sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86" useDigest: true - # -- Init containers added to the cilium Envoy DaemonSet. - initContainers: [] # -- Additional containers added to the cilium Envoy DaemonSet. extraContainers: [] # -- Additional envoy container arguments. @@ -2961,15 +2699,16 @@ resourceQuotas: pods: "15" # Need to document default ################## +#sessionAffinity: false # -- Annotations to be added to all cilium-secret namespaces (resources under templates/cilium-secrets-namespace) secretsNamespaceAnnotations: {} -# -- Labels to be added to all cilium-secret namespaces (resources under templates/cilium-secrets-namespace) -secretsNamespaceLabels: {} # -- Do not run Cilium agent when running with clean mode. Useful to completely # uninstall Cilium as it will stop Cilium from starting and create artifacts # in the node. sleepAfterInit: false +# -- Enable check of service source ranges (currently, only for LoadBalancer). +svcSourceRangeCheck: true # -- Synchronize Kubernetes nodes to kvstore and perform CNP GC. synchronizeK8sNodes: true # -- Configure TLS configuration in the agent. @@ -3052,9 +2791,6 @@ tls: # @default -- `"vxlan"` tunnelProtocol: "" # -- IP family for the underlay. -# Possible values: -# - "ipv4" -# - "ipv6" # @default -- `"ipv4"` underlayProtocol: "" # -- Enable native-routing mode or tunneling mode. @@ -3075,11 +2811,6 @@ tunnelSourcePortRange: 0-0 # - reject (default) # - drop serviceNoBackendResponse: reject -# -- Configure what the response should be to pod egress traffic denied by network policy. -# Possible values: -# - none (default) -# - icmp -policyDenyResponse: none # -- Configure the underlying network MTU to overwrite auto-detected MTU. # This value doesn't change the host network interface MTU i.e. eth0 or ens0. # It changes the MTU for cilium_net@cilium_host, cilium_host@cilium_net, @@ -3110,15 +2841,15 @@ operator: # @schema override: ~ repository: "quay.io/cilium/operator" - tag: "v1.19.3" + tag: "v1.18.6" # operator-generic-digest - genericDigest: sha256:205b09b0ed6accbf9fe688d312a9f0fcfc6a316fc081c23fbffb472af5dd62cd + genericDigest: sha256:34a827ce9ed021c8adf8f0feca131f53b3c54a3ef529053d871d0347ec4d69af # operator-azure-digest - azureDigest: sha256:699c1571a3df1a98882ee13610d47cffb7b34ee7e8d276096db798a5f6c7e4cb + azureDigest: sha256:a57aff47aeb32eccfedaa2a49d1af984d996d6d6de79609c232e0c4cf9ce97a1 # operator-aws-digest - awsDigest: sha256:a53dcbfb77282bf2ddd3abbe60f6d49762e7c1389a36cb35b71d504644a56640 + awsDigest: sha256:47dbc1a5bd483fec170dab7fb0bf2cca3585a4893675b0324d41d97bac8be5eb # operator-alibabacloud-digest - alibabacloudDigest: sha256:176321a65123373ff8c7823b25183102cbad98375e8d6c80b96d68b6e8491103 + alibabacloudDigest: sha256:212c4cbe27da3772bcb952b8f8cbaa0b0eef72488b52edf90ad2b32072a3ca4c useDigest: true pullPolicy: "IfNotPresent" suffix: "" @@ -3257,10 +2988,6 @@ operator: address: localhost # -- Configure pprof listen port for cilium-operator port: 6061 - # -- Enable mutex contention profiling for cilium-operator and set the fraction of sampled events (set to 1 to sample all events) - mutexProfileFraction: 0 - # -- Enable goroutine blocking profiling for cilium-operator and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) - blockProfileRate: 0 # -- Enable prometheus metrics for cilium-operator on the configured port at # /metrics prometheus: @@ -3294,17 +3021,6 @@ operator: # @schema # -- Metrics relabeling configs for the ServiceMonitor cilium-operator metricRelabelings: ~ - # -- TLS configuration for Prometheus - tls: - enabled: false - server: - # -- Name of the Secret containing the certificate, key and CA files for the Prometheus server. - existingSecret: "" - mtls: - # When set to true enforces mutual TLS between Operator Prometheus server and its clients. - # False allow non-mutual TLS connections. - # This option has no effect when TLS is disabled. - enabled: false # -- Grafana dashboards for cilium-operator # grafana can import dashboards based on the label and value # ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards @@ -3338,12 +3054,6 @@ operator: # -- Interval, in seconds, to check if there are any pods that are not # managed by Cilium. intervalSeconds: 15 - # -- Selector for pods that should be restarted when not managed by Cilium. - # If not set, defaults to built-in selector "k8s-app=kube-dns". Set to empty string to select all pods. - # @schema - # type: [null, string] - # @schema - selector: ~ nodeinit: # -- Enable the node initialization DaemonSet enabled: false @@ -3354,8 +3064,8 @@ nodeinit: # @schema override: ~ repository: "quay.io/cilium/startup-script" - tag: "1763560095-8f36c34" - digest: "sha256:50b9cf9c280096b59b80d2fc8ee6638facef79ac18998a22f0cbc40d5d28c16f" + tag: "1755531540-60ee83e" + digest: "sha256:5bdca3c2dec2c79f58d45a7a560bf1098c2126350c901379fe850b7f78d3d757" useDigest: true pullPolicy: "IfNotPresent" # -- The priority class to use for the nodeinit pod. @@ -3398,9 +3108,6 @@ nodeinit: # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: requests: - # @schema - # type: [integer, string] - # @schema cpu: 100m memory: 100Mi # -- Security context to be added to nodeinit pods. @@ -3423,8 +3130,6 @@ nodeinit: # -- bootstrapFile is the location of the file where the bootstrap timestamp is # written by the node-init DaemonSet bootstrapFile: "/tmp/cilium-bootstrap.d/cilium-bootstrap-time" - # -- wait for Cloud init to finish on the host and assume the node has cloud init installed - waitForCloudInit: false # -- startup offers way to customize startup nodeinit script (pre and post position) startup: preScript: "" @@ -3443,9 +3148,9 @@ preflight: # @schema override: ~ repository: "quay.io/cilium/cilium" - tag: "v1.19.3" + tag: "v1.18.6" # cilium-digest - digest: sha256:2e61680593cddca8b6c055f6d4c849d87a26a1c91c7e3b8b56c7fb76ab7b7b10 + digest: sha256:42ec562a5ff6c8a860c0639f5a7611685e253fd9eb2d2fcdade693724c9166a4 useDigest: true pullPolicy: "IfNotPresent" envoy: @@ -3456,9 +3161,9 @@ preflight: # @schema override: ~ repository: "quay.io/cilium/cilium-envoy" - tag: "v1.36.6-1776000132-2437d2edeaf4d9b56ef279bd0d71127440c067aa" + tag: "v1.35.9-1767794330-db497dd19e346b39d81d7b5c0dedf6c812bcc5c9" pullPolicy: "IfNotPresent" - digest: "sha256:ba0ab8adac082d50d525fd2c5ba096c8facea3a471561b7c61c7a5b9c2e0de0d" + digest: "sha256:81398e449f2d3d0a6a70527e4f641aaa685d3156bea0bb30712fae3fd8822b86" useDigest: true # -- The priority class to use for the preflight pod. priorityClassName: "" @@ -3558,9 +3263,7 @@ enableCriticalPriorityClass: true # on AArch64 as the images do not currently ship a version of Envoy. #disableEnvoyVersionCheck: false clustermesh: - # -- Deploy clustermesh-apiserver for clustermesh. This option is typically - # used with ``clustermesh.config.enabled=true``. Refer to the - # ``clustermesh.config.enabled=true``documentation for more information. + # -- Deploy clustermesh-apiserver for clustermesh useAPIServer: false # -- The maximum number of clusters to support in a ClusterMesh. This value # cannot be changed on running clusters, and all clusters in a ClusterMesh @@ -3568,132 +3271,44 @@ clustermesh: # maximum allocatable cluster-local identities. # Supported values are 255 and 511. maxConnectedClusters: 255 - # -- The time to live for the cache of a remote cluster after connectivity is - # lost. If the connection is not re-established within this duration, the - # cached data is revoked to prevent stale state. If not specified or set to - # 0s, the cache is never revoked (default). - cacheTTL: "0s" # -- Enable the synchronization of Kubernetes EndpointSlices corresponding to # the remote endpoints of appropriately-annotated global services through ClusterMesh enableEndpointSliceSynchronization: false - # -- Enable Multi-Cluster Services API support (deprecated; use clustermesh.mcsapi.enabled) + # -- Enable Multi-Cluster Services API support enableMCSAPISupport: false # -- Control whether policy rules assume by default the local cluster if not explicitly selected - policyDefaultLocalCluster: true + policyDefaultLocalCluster: false # -- Annotations to be added to all top-level clustermesh objects (resources under templates/clustermesh-apiserver and templates/clustermesh-config) annotations: {} # -- Clustermesh explicit configuration. config: # -- Enable the Clustermesh explicit configuration. - # If set to false, you need to provide the following resources yourself: - # - (Secret) cilium-clustermesh (used by cilium-agent/cilium-operator to connect to - # the local etcd instance if KVStoreMesh is enabled or the remote clusters - # if KVStoreMesh is disabled) - # - (Secret) cilium-kvstoremesh (used by KVStoreMesh to connect to the remote clusters) - # - (ConfigMap) clustermesh-remote-users (used to create one etcd user per remote cluster - # if clustermesh-apiserver is used and `clustermesh.apiserver.tls.authMode` is not - # set to `legacy`) enabled: false # -- Default dns domain for the Clustermesh API servers # This is used in the case cluster addresses are not provided # and IPs are used. domain: mesh.cilium.io - # -- Clusters to be peered in the mesh. - # @schema - # type: [object, array] - # @schema + # -- List of clusters to be peered in the mesh. clusters: [] - # You can use a dict of clusters (recommended): # clusters: - # # -- Name of the cluster - # cluster1: - # # -- Whether to enable this cluster in the mesh. Optional, defaults to true. - # enabled: true - # # -- Address of the cluster, use this if you created DNS records for - # # the cluster Clustermesh API server. - # address: cluster1.mesh.cilium.io - # # -- Port of the cluster Clustermesh API server. - # port: 2379 - # # -- IPs of the cluster Clustermesh API server, use multiple ones when - # # you have multiple IPs to access the Clustermesh API server. - # ips: - # - 172.18.255.201 - # # -- (deprecated) base64 encoded PEM values for the cluster client certificate, private key and certificate authority. - # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the - # # "remote" private key and certificate available in the local cluster are automatically used instead. - # tls: - # cert: "" - # key: "" - # caCert: "" - # - # Or alternatively you can use a list of clusters: - # clusters: - # # -- Name of the cluster + # # -- Name of the cluster # - name: cluster1 - # # -- Address of the cluster, use this if you created DNS records for - # # the cluster Clustermesh API server. + # # -- Address of the cluster, use this if you created DNS records for + # # the cluster Clustermesh API server. # address: cluster1.mesh.cilium.io - # # -- Port of the cluster Clustermesh API server. + # # -- Port of the cluster Clustermesh API server. # port: 2379 - # # -- IPs of the cluster Clustermesh API server, use multiple ones when - # # you have multiple IPs to access the Clustermesh API server. + # # -- IPs of the cluster Clustermesh API server, use multiple ones when + # # you have multiple IPs to access the Clustermesh API server. # ips: # - 172.18.255.201 - # # -- (deprecated) base64 encoded PEM values for the cluster client certificate, private key and certificate authority. - # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the - # # "remote" private key and certificate available in the local cluster are automatically used instead. + # # -- base64 encoded PEM values for the cluster client certificate, private key and certificate authority. + # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the + # # "remote" private key and certificate available in the local cluster are automatically used instead. # tls: # cert: "" # key: "" # caCert: "" - mcsapi: - # -- Enable Multi-Cluster Services API support - enabled: false - # -- Enabled MCS-API CRDs auto-installation - installCRDs: true - corednsAutoConfigure: - # -- Enable auto-configuration of CoreDNS for Multi-Cluster Services API. - # CoreDNS MUST be at least in version v1.12.2 to run this. - enabled: false - coredns: - # -- The Deployment for the cluster CoreDNS service - deploymentName: coredns - # -- The Service Account name for the cluster CoreDNS service - serviceAccountName: coredns - # -- The ConfigMap name for the cluster CoreDNS service - configMapName: coredns - # -- The namespace for the cluster CoreDNS service - namespace: kube-system - # -- The cluster domain for the cluster CoreDNS service - clusterDomain: cluster.local - # -- The clusterset domain for the cluster CoreDNS service - clustersetDomain: clusterset.local - # -- Additional arguments to `clustermesh-apiserver coredns-mcsapi-auto-configure`. - extraArgs: [] - # -- Seconds after which the completed job pod will be deleted - ttlSecondsAfterFinished: 1800 - # -- Labels to be added to coredns-mcsapi-autoconfig pods - podLabels: {} - # -- Annotations to be added to the coredns-mcsapi-autoconfig Job - annotations: {} - # -- Node selector for coredns-mcsapi-autoconfig - # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector - nodeSelector: {} - # -- Priority class for coredns-mcsapi-autoconfig - # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass - priorityClassName: "" - # -- Node tolerations for pod assignment on nodes with taints - # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ - tolerations: [] - # -- Resource limits for coredns-mcsapi-autoconfig - # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers - resources: {} - # -- Additional coredns-mcsapi-autoconfig volumes. - extraVolumes: [] - # -- Additional coredns-mcsapi-autoconfig volumeMounts. - extraVolumeMounts: [] - # -- Affinity for coredns-mcsapi-autoconfig - affinity: {} apiserver: # -- Clustermesh API server image. image: @@ -3702,9 +3317,9 @@ clustermesh: # @schema override: ~ repository: "quay.io/cilium/clustermesh-apiserver" - tag: "v1.19.3" + tag: "v1.18.6" # clustermesh-apiserver-digest - digest: sha256:a8136a7615d6c6041d3aa6f2674d17beaec238170d669507ccc05328a778e2b7 + digest: sha256:8ee142912a0e261850c0802d9256ddbe3729e1cd35c6bea2d93077f334c3cf3b useDigest: true pullPolicy: "IfNotPresent" # -- TCP port for the clustermesh-apiserver health API. @@ -3793,12 +3408,17 @@ clustermesh: # - "external": ``clustermesh-apiserver`` will sync remote cluster information to the etcd used as kvstore. This can't be enabled with crd identity allocation mode. kvstoreMode: "internal" service: - # -- (bool) Set externallyCreated to true to create the clustermesh-apiserver service outside this helm chart. - # For example after external load balancer controllers are created. - externallyCreated: false # -- The type of service used for apiserver access. type: NodePort # -- Optional port to use as the node port for apiserver access. + # + # WARNING: make sure to configure a different NodePort in each cluster if + # kube-proxy replacement is enabled, as Cilium is currently affected by a known + # bug (#24692) when NodePorts are handled by the KPR implementation. If a service + # with the same NodePort exists both in the local and the remote cluster, all + # traffic originating from inside the cluster and targeting the corresponding + # NodePort will be redirected to a local backend, regardless of whether the + # destination node belongs to the local or the remote cluster. nodePort: 32379 # -- Annotations for the clustermesh-apiserver service. # Example annotations to configure an internal load balancer on different cloud providers: @@ -3967,15 +3587,13 @@ clustermesh: # The "remote" certificate must be generated with CN=remote- # if provided manually. Cluster mode is meaningful only when the same # CA is shared across all clusters part of the mesh. - authMode: migration - # -- (deprecated) Allow users to provide their own certificates + authMode: legacy + # -- Allow users to provide their own certificates # Users may need to provide their certificates using # a mechanism that requires they provide their own secrets. # This setting does not apply to any of the auto-generated # mechanisms below, it only restricts the creation of secrets # via the `tls-provided` templates. - # This option is deprecated as secrets are expected to be created - # externally when 'auto' is not enabled. enableSecrets: true # -- Configure automatic TLS certificates generation. # A Kubernetes CronJob is used the generate any @@ -3984,14 +3602,7 @@ clustermesh: auto: # -- When set to true, automatically generate a CA and certificates to # enable mTLS between clustermesh-apiserver and external workload instances. - # - # When set to false you need to pre-create the following secrets: - # - clustermesh-apiserver-server-cert - # - clustermesh-apiserver-admin-cert - # - clustermesh-apiserver-remote-cert - # - clustermesh-apiserver-local-cert - # The above secret should at least contains the keys `tls.crt` and `tls.key` - # and optionally `ca.crt` if a CA bundle is not configured. + # If set to false, the certs to be provided by setting appropriate values below. enabled: true # Sets the method to auto-generate certificates. Supported values: # - helm: This method uses Helm to generate all certificates. @@ -4026,9 +3637,7 @@ clustermesh: # -- base64 encoded PEM values for the clustermesh-apiserver server certificate and private key. # Used if 'auto' is not enabled. server: - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. cert: "" - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. key: "" # -- Extra DNS names added to certificate when it's auto generated extraDnsNames: [] @@ -4037,16 +3646,17 @@ clustermesh: # -- base64 encoded PEM values for the clustermesh-apiserver admin certificate and private key. # Used if 'auto' is not enabled. admin: - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. cert: "" - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver client certificate and private key. + # Used if 'auto' is not enabled. + client: + cert: "" key: "" # -- base64 encoded PEM values for the clustermesh-apiserver remote cluster certificate and private key. # Used if 'auto' is not enabled. remote: - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. cert: "" - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. key: "" # clustermesh-apiserver Prometheus metrics configuration metrics: @@ -4201,7 +3811,7 @@ authentication: # -- Enable authentication processing and garbage collection. # Note that if disabled, policy enforcement will still block requests that require authentication. # But the resulting authentication requests for these requests will not be processed, therefore the requests not be allowed. - enabled: false + enabled: true # -- Buffer size of the channel Cilium uses to receive authentication events from the signal map. queueSize: 1024 # -- Buffer size of the channel Cilium uses to receive certificate expiration events from auth handlers. @@ -4239,7 +3849,7 @@ authentication: override: ~ repository: "docker.io/library/busybox" tag: "1.37.0" - digest: "sha256:1487d0af5f52b4ba31c7e465126ee2123fe3f2305d638e7827681e7cf6c83d5e" + digest: "sha256:2383baad1860bbe9d8a7a843775048fd07d8afe292b94bd876df64a69aae7cb1" useDigest: true pullPolicy: "IfNotPresent" # SPIRE agent configuration @@ -4253,8 +3863,8 @@ authentication: # @schema override: ~ repository: "ghcr.io/spiffe/spire-agent" - tag: "1.9.6" - digest: "sha256:5106ac601272a88684db14daf7f54b9a45f31f77bb16a906bd5e87756ee7b97c" + tag: "1.12.4" + digest: "sha256:163970884fba18860cac93655dc32b6af85a5dcf2ebb7e3e119a10888eff8fcd" useDigest: true pullPolicy: "IfNotPresent" # -- SPIRE agent service account @@ -4308,8 +3918,8 @@ authentication: # @schema override: ~ repository: "ghcr.io/spiffe/spire-server" - tag: "1.9.6" - digest: "sha256:59a0b92b39773515e25e68a46c40d3b931b9c1860bc445a79ceb45a805cab8b4" + tag: "1.12.4" + digest: "sha256:34147f27066ab2be5cc10ca1d4bfd361144196467155d46c45f3519f41596e49" useDigest: true pullPolicy: "IfNotPresent" # -- SPIRE server service account @@ -4394,41 +4004,3 @@ authentication: enableInternalTrafficPolicy: true # -- Enable LoadBalancer IP Address Management enableLBIPAM: true -# -- Standalone DNS Proxy Configuration -# Note: The standalone DNS proxy uses the agent's dnsProxy.* configuration -# for DNS settings (proxyPort, enableDnsCompression) to ensure consistency. -standaloneDnsProxy: - # -- Enable standalone DNS proxy (alpha feature) - enabled: false - # -- Roll out Standalone DNS proxy automatically when configmap is updated. - rollOutPods: false - # -- Standalone DNS proxy annotations - annotations: {} - # -- Standalone DNS proxy debug mode - debug: false - # -- Standalone DNS proxy server port - serverPort: 10095 - # -- Standalone DNS proxy Node Selector - nodeSelector: - kubernetes.io/os: linux - # -- Standalone DNS proxy tolerations - tolerations: [] - # -- Standalone DNS proxy auto mount service account token - automountServiceAccountToken: false - # -- Standalone DNS proxy update strategy - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 2 - maxUnavailable: 0 - # -- Standalone DNS proxy image - image: - # @schema - # type: [null, string] - # @schema - override: ~ - repository: "" - tag: "" - digest: "" - useDigest: true - pullPolicy: "IfNotPresent" diff --git a/packages/system/cilium/charts/cilium/values.yaml.tmpl b/packages/system/cilium/charts/cilium/values.yaml.tmpl index 8039b40c..83b87cfd 100644 --- a/packages/system/cilium/charts/cilium/values.yaml.tmpl +++ b/packages/system/cilium/charts/cilium/values.yaml.tmpl @@ -3,6 +3,7 @@ # type: [null, string] # @schema # -- namespaceOverride allows to override the destination namespace for Cilium resources. +# This property allows to use Cilium as part of an Umbrella Chart with different targets. namespaceOverride: "" # @schema # type: [null, object] @@ -26,7 +27,7 @@ debug: # @schema # -- Configure verbosity levels for debug logging # This option is used to enable debug messages for operations related to such - # sub-system such as (e.g. kvstore, envoy, datapath, policy, or tagged), and flow is + # sub-system such as (e.g. kvstore, envoy, datapath or policy), and flow is # for enabling debug messages emitted per request, message and connection. # Multiple values can be set via a space-separated string (e.g. "datapath envoy"). # @@ -36,7 +37,6 @@ debug: # - envoy # - datapath # - policy - # - tagged verbose: ~ # -- Set the agent-internal metrics sampling frequency. This sets the @@ -207,18 +207,6 @@ serviceAccounts: name: hubble-generate-certs automount: true annotations: {} - # -- CorednsMCSAPI is used if clustermesh.mcsapi.corednsAutoConfigure.enabled=true - corednsMCSAPI: - create: true - name: cilium-coredns-mcsapi-autoconfig - automount: true - annotations: {} - # -- Ztunnel is used if encryption.type=ztunnel - ztunnel: - create: true - name: ztunnel-cilium - automount: false - annotations: {} # -- Configure termination grace period for cilium-agent DaemonSet. terminationGracePeriodSeconds: 1 # -- Install the cilium agent resources. @@ -227,22 +215,6 @@ agent: true name: cilium # -- Roll out cilium agent pods automatically when configmap is updated. rollOutCiliumPods: false -# -- Configuration for the ConfigMap drift detection feature. -# When enabled, the agent continuously watches the cilium-config ConfigMap -# and exposes a cilium_drift_checker_config_delta Prometheus metric reporting -# the number of keys that differ between the ConfigMap and the agent's active -# settings. A non-zero value indicates that the agent has not yet applied all -# current ConfigMap changes and needs to be restarted. -configDriftDetection: - # -- Enable watching of the cilium-config ConfigMap and reflecting its - # contents into the agent's internal DynamicConfig table. - enabled: true - # -- Enable the drift checker which compares the DynamicConfig table against - # the agent's active settings and publishes the - # cilium_drift_checker_config_delta metric. - driftChecker: true - # -- List of config-map keys to ignore when computing the drift delta. - ignoredKeys: [] # -- Agent container image. image: # @schema @@ -396,8 +368,6 @@ securityContext: - SETGID # Allow to execute program that changes UID (e.g. required for package installation) - SETUID - # Allow to read dmesg and get kernel pointers when kptr_restrict=1 - - SYSLOG # -- Capabilities for the `mount-cgroup` init container mountCgroup: # Only used for 'mount' cgroup @@ -470,16 +440,9 @@ azure: # clientID: 00000000-0000-0000-0000-000000000000 # clientSecret: 00000000-0000-0000-0000-000000000000 # userAssignedIdentityID: 00000000-0000-0000-0000-000000000000 - nodeSpec: - azureInterfaceName: "" alibabacloud: # -- Enable AlibabaCloud ENI integration enabled: false - nodeSpec: - vSwitches: [] - vSwitchTags: [] - securityGroups: [] - securityGroupTags: [] # -- Enable bandwidth manager to optimize TCP and UDP workloads and allow # for rate-limiting traffic from individual Pods with EDT (Earliest Departure # Time) through the "kubernetes.io/egress-bandwidth" Pod annotation. @@ -512,7 +475,8 @@ l2podAnnouncements: interface: "eth0" # -- A regular expression matching interfaces used for sending Gratuitous ARP pod announcements # interfacePattern: "" -# -- This feature set enables virtual BGP routers to be created via BGP CRDs. +# -- This feature set enables virtual BGP routers to be created via +# CiliumBGPPeeringPolicy CRDs. bgpControlPlane: # -- Enables the BGP control plane. enabled: false @@ -522,9 +486,9 @@ bgpControlPlane: create: false # -- The name of the secret namespace to which Cilium agents are given read access name: kube-system - # -- Status reporting settings + # -- Status reporting settings (BGPv2 only) statusReport: - # -- Enable/Disable BGP status reporting + # -- Enable/Disable BGPv2 status reporting # It is recommended to enable status reporting in general, but if you have any issue # such as high API server load, you can disable it by setting this to false. enabled: true @@ -534,7 +498,7 @@ bgpControlPlane: mode: "default" # -- IP pool to allocate the BGP router-id from when the mode is ip-pool. ipPool: "" - # -- Legacy BGP ORIGIN attribute settings + # -- Legacy BGP ORIGIN attribute settings (BGPv2 only) legacyOriginAttribute: # -- Enable/Disable advertising LoadBalancerIP routes with the legacy # BGP ORIGIN attribute value INCOMPLETE (2) instead of the default IGP (0). @@ -544,11 +508,6 @@ pmtuDiscovery: # -- Enable path MTU discovery to send ICMP fragmentation-needed replies to # the client. enabled: false - # -- Enable kernel probing path MTU discovery for Pods which uses different message - # sizes to search for correct MTU value. - # Valid values are: always, blackhole, disabled and unset (or empty). If value - # is 'unset' or left empty then will not try to override setting. - packetizationLayerPMTUDMode: "blackhole" bpf: autoMount: # -- Enable automatic mount of BPF filesystem @@ -596,7 +555,7 @@ bpf: # Helm configuration for BPF events map rate limiting is experimental and might change # in upcoming releases. events: - # -- Default settings for all types of events except dbg. + # -- Default settings for all types of events except dbg and pcap. default: # @schema # type: [null, integer] @@ -656,12 +615,6 @@ bpf: # type: [null, integer] # @schema policyMapMax: 16384 - # -- (float64) Configure threshold for emitting pressure metrics of policy maps. - # @schema - # type: [null, number] - # @schema - # @default -- `0.1` - policyMapPressureMetricsThreshold: ~ # -- Configure the maximum number of entries in global policy stats map. # @schema # type: [null, integer] @@ -719,8 +672,7 @@ bpf: # type: [null, boolean] # @schema # -- (bool) Configure the eBPF-based TPROXY (beta) to reduce reliance on iptables rules - # for implementing Layer 7 policy. Note this is incompatible with netkit (`bpf.datapathMode=netkit`, - # `bpf.datapathMode=netkit-l2`). + # for implementing Layer 7 policy. # @default -- `false` tproxy: ~ # @schema @@ -730,15 +682,6 @@ bpf: # [0] will allow all VLAN id's without any filtering. # @default -- `[]` vlanBypass: ~ - # -- Configure the IP tracing option type. - # This option is used to specify the IP option type to use for tracing. - # The value must be an integer between 0 and 255. - # @schema - # type: [null, integer] - # minimum: 0 - # maximum: 255 - # @schema - monitorTraceIPOption: 0 # -- (bool) Disable ExternalIP mitigation (CVE-2020-8554) # @default -- `false` disableExternalIPMitigation: false @@ -746,8 +689,7 @@ bpf: # supported kernels. # @default -- `true` enableTCX: true - # -- (string) Mode for Pod devices for the core datapath (veth, netkit, netkit-l2). - # Note netkit is incompatible with TPROXY (`bpf.tproxy`). + # -- (string) Mode for Pod devices for the core datapath (veth, netkit, netkit-l2) # @default -- `veth` datapathMode: veth # -- Enable BPF clock source probing for more efficient tick retrieval. @@ -836,17 +778,8 @@ cni: # -- Specifies the resources for the cni initContainer resources: requests: - # @schema - # type: [integer, string] - # @schema cpu: 100m memory: 10Mi - limits: - # @schema - # type: [integer, string] - # @schema - cpu: 1 - memory: 1Gi # -- Enable route MTU for pod netns when CNI chaining is used enableRouteMTUForCNIChaining: false # -- Enable the removal of iptables rules created by the AWS CNI VPC plugin. @@ -871,6 +804,10 @@ conntrackGCMaxInterval: "" # -- (string) Configure timeout in which Cilium will exit if CRDs are not available # @default -- `"5m"` crdWaitTimeout: "" +# -- Tail call hooks for custom eBPF programs. +customCalls: + # -- Enable tail call hooks for custom eBPF programs. + enabled: false daemon: # -- Configure where Cilium runtime state should be stored. runPath: "/var/run/cilium" @@ -913,13 +850,6 @@ daemon: # # By default, this functionality is enabled enableSourceIPVerification: true - -# -- Configure temporary volume for cilium-agent -tmpVolume: {} - # emptyDir: - # sizeLimit: "100Mi" - # medium: "Memory" - # -- Specify which network interfaces can run the eBPF datapath. This means # that a packet sent from a pod to a destination outside the cluster will be # masqueraded (to an output device IPv4 address), if the output device runs the @@ -939,6 +869,9 @@ forceDeviceDetection: false # -- Enable setting identity mark for local traffic. # enableIdentityMark: true +# -- Enable Kubernetes EndpointSlice feature in Cilium if the cluster supports it. +# enableK8sEndpointSlice: true + # -- CiliumEndpointSlice configuration options. ciliumEndpointSlice: # -- Enable Cilium EndpointSlice feature. @@ -1123,33 +1056,20 @@ enableXTSocketFallback: true encryption: # -- Enable transparent network encryption. enabled: false - # -- Encryption method. Can be one of ipsec, wireguard or ztunnel. + # -- Encryption method. Can be either ipsec or wireguard. type: ipsec # -- Enable encryption for pure node to node traffic. # This option is only effective when encryption.type is set to "wireguard". nodeEncryption: false - # -- Configure the Encryption Pod2Pod strict mode. + # -- Configure the WireGuard Pod2Pod strict mode. strictMode: - # -- Enable Encryption Pod2Pod strict mode. (deprecated: please use encryption.strictMode.egress.enabled) + # -- Enable WireGuard Pod2Pod strict mode. enabled: false - # -- CIDR for the Encryption Pod2Pod strict mode. (deprecated: please use encryption.strictMode.egress.cidr) + # -- CIDR for the WireGuard Pod2Pod strict mode. cidr: "" - # -- Allow dynamic lookup of remote node identities. (deprecated: please use encryption.strictMode.egress.allowRemoteNodeIdentities) + # -- Allow dynamic lookup of remote node identities. # This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. allowRemoteNodeIdentities: false - egress: - # -- Enable strict egress encryption. - enabled: false - # -- CIDR for the Encryption Pod2Pod strict egress mode. - cidr: "" - # -- Allow dynamic lookup of remote node identities. - # This is required when tunneling is used or direct routing is used and the node CIDR and pod CIDR overlap. - allowRemoteNodeIdentities: false - ingress: - # -- Enable strict ingress encryption. - # When enabled, all unencrypted overlay ingress traffic will be dropped. - # This option is only applicable when WireGuard and tunneling are enabled. - enabled: false ipsec: # -- Name of the key file inside the Kubernetes secret configured via secretName. keyFile: keys @@ -1170,89 +1090,9 @@ encryption: wireguard: # -- Controls WireGuard PersistentKeepalive option. Set 0s to disable. persistentKeepalive: 0s - # -- ztunnel encryption configuration. - # ztunnel is Istio's purpose-built, per-node proxy for handling L4 traffic in ambient mesh mode. - # These settings only apply when encryption.type is set to "ztunnel". - ztunnel: - # -- ztunnel container image. - image: - # @schema - # type: [null, string] - # @schema - override: ~ - repository: "docker.io/istio/ztunnel" - tag: "1.28.0-distroless" - pullPolicy: "IfNotPresent" - # @schema - # type: [null, string] - # @schema - digest: ~ - useDigest: false - # -- CA server address for certificate requests. - caAddress: "https://localhost:15012" - # -- TCP port for the health API. - healthPort: 15021 - # -- ztunnel resource limits & requests. - resources: - requests: - cpu: 200m - memory: 512Mi - # -- ztunnel update strategy. - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 1 - maxUnavailable: 0 - # -- Configure termination grace period for ztunnel DaemonSet. - terminationGracePeriodSeconds: 30 - # -- Readiness probe configuration. - readinessProbe: - initialDelaySeconds: 0 - periodSeconds: 10 - failureThreshold: 3 - # -- Node selector for ztunnel pods. - nodeSelector: - kubernetes.io/os: linux - # -- Node tolerations for ztunnel scheduling. - tolerations: - - effect: NoSchedule - operator: Exists - - key: CriticalAddonsOnly - operator: Exists - - effect: NoExecute - operator: Exists - # -- Affinity for ztunnel pods. - affinity: {} - # @schema - # type: [null, string] - # @schema - # -- The priority class to use for ztunnel pods. - priorityClassName: ~ - # -- Annotations to be added to all ztunnel resources. - annotations: {} - # -- Annotations to be added to ztunnel pods. - podAnnotations: {} - # -- Labels to be added to ztunnel pods. - podLabels: {} - # -- Additional ztunnel container environment variables. - extraEnv: [] - # -- Additional ztunnel volumes. - extraVolumes: [] - # -- Additional ztunnel volumeMounts. - extraVolumeMounts: [] - # -- ztunnel secrets configuration. - secrets: - # -- Base64-encoded bootstrap root certificate content. - # If not provided, the secret must be created manually before deploying. - # @schema - # type: [null, string] - # @schema - bootstrapRootCert: ~ endpointHealthChecking: # -- Enable connectivity health checking between virtual endpoints. enabled: true -# -- Max duration to wait for envoy to respond to configuration changes. Default "10s". -endpointPolicyUpdateTimeoutDuration: null endpointRoutes: # @schema # type: [boolean, string] @@ -1301,33 +1141,6 @@ eni: # -- Filter via AWS EC2 Instance tags (k=v) which will dictate which AWS EC2 Instances # are going to be used to create new ENIs instanceTagsFilter: [] - # -- NodeSpec configuration for the ENI - nodeSpec: - # -- First interface index to use for IP allocation - # @schema - # type: [null, integer] - # @schema - firstInterfaceIndex: ~ - # -- Subnet IDs to use for IP allocation - subnetIDs: [] - # -- Subnet tags to use for IP allocation - subnetTags: [] - # -- Security groups to use for IP allocation - securityGroups: [] - # -- Security group tags to use for IP allocation - securityGroupTags: [] - # -- Exclude interface tags to use for IP allocation - excludeInterfaceTags: [] - # -- Use primary address for IP allocation - usePrimaryAddress: false - # -- Disable prefix delegation for IP allocation - disablePrefixDelegation: false - # -- Delete ENI on termination - # @schema - # type: [null, boolean] - # @schema - deleteOnTermination: ~ - # fragmentTracking enables IPv4 fragment tracking support in the datapath. # fragmentTracking: true gke: @@ -1343,8 +1156,6 @@ healthCheckICMPFailureThreshold: 3 hostFirewall: # -- Enables the enforcement of host policies in the eBPF datapath. enabled: false -# -- Enable routing to a service that has zero endpoints -enableNoServiceEndpointsRoutable: true # -- Configure socket LB socketLB: # -- Enable socket LB @@ -1372,11 +1183,8 @@ certgen: digest: "${CERTGEN_DIGEST}" useDigest: true pullPolicy: "${PULL_POLICY}" - # @schema - # type: [null, integer] - # @schema # -- Seconds after which the completed job pod will be deleted - ttlSecondsAfterFinished: null + ttlSecondsAfterFinished: 1800 # -- Labels to be added to hubble-certgen pods podLabels: {} # -- Annotations to be added to the hubble-certgen initial Job and CronJob @@ -1401,11 +1209,6 @@ certgen: extraVolumeMounts: [] # -- Affinity for certgen affinity: {} - cronJob: - # -- The number of successful finished jobs to keep - successfulJobsHistoryLimit: 3 - # -- The number of failed finished jobs to keep - failedJobsHistoryLimit: 1 hubble: # -- Enable Hubble (true by default). enabled: true @@ -1421,9 +1224,6 @@ hubble: # 2047, 4095, 8191, 16383, 32767, 65535 # eventBufferCapacity: "4095" - # -- The interval at which Hubble will send out lost events from the Observer server, if any. - # lostEventSendInterval: 1s - # -- Hubble metrics configuration. # See https://docs.cilium.io/en/stable/observability/metrics/#hubble-metrics # for more comprehensive documentation about Hubble metrics. @@ -1930,24 +1730,6 @@ hubble: address: localhost # -- Configure pprof listen port for hubble-relay port: 6062 - # -- Enable mutex contention profiling for hubble-relay and set the fraction of sampled events (set to 1 to sample all events) - mutexProfileFraction: 0 - # -- Enable goroutine blocking profiling for hubble-relay and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) - blockProfileRate: 0 - # -- Logging configuration for hubble-relay. - logOptions: - # @schema - # type: [null, string] - # @schema - # -- Log format for hubble-relay. Valid values are: text, text-ts, json, json-ts. - # @default -- text-ts - format: ~ - # @schema - # type: [null, string] - # @schema - # -- Log level for hubble-relay. Valid values are: debug, info, warn, error. - # @default -- info - level: ~ ui: # -- Whether to enable the Hubble UI. enabled: false @@ -2143,13 +1925,6 @@ hubble: # - secretName: chart-example-tls # hosts: # - chart-example.local - - # -- Configure temporary volume for hubble-ui - tmpVolume: {} - # emptyDir: - # # sizeLimit: "100Mi" - # # medium: "Memory" - # -- Hubble flows export. export: # --- Static exporter configuration. @@ -2162,14 +1937,6 @@ hubble: # - source # - destination # - verdict - fieldAggregate: [] - # - time - # - source - # - destination - # - verdict - # --- Defines the interval at which to aggregate before exporting Hubble flows. - # Aggregation feature is only enabled when fieldAggregate is specified and aggregationInterval > 0s. - aggregationInterval: "0s" allowList: [] # - '{"verdict":["DROPPED","ERROR"]}' denyList: [] @@ -2195,8 +1962,6 @@ hubble: content: - name: all fieldMask: [] - fieldAggregate: [] - aggregationInterval: "0s" includeFilters: [] excludeFilters: [] filePath: "/var/run/cilium/hubble/events.log" @@ -2291,30 +2056,11 @@ ipam: # refill the bucket up to the burst size capacity. # @default -- `4.0` externalAPILimitQPS: ~ - # -- NodeSpec configuration for the IPAM - nodeSpec: - # -- IPAM min allocate - # @schema - # type: [null, integer] - # @schema - ipamMinAllocate: ~ - # -- IPAM pre allocate - # @schema - # type: [null, integer] - # @schema - ipamPreAllocate: ~ - # -- IPAM max allocate - # @schema - # type: [null, integer] - # @schema - ipamMaxAllocate: ~ - # -- IPAM static IP tags (currently only works with AWS and Azure) - ipamStaticIPTags: [] +# -- defaultLBServiceIPAM indicates the default LoadBalancer Service IPAM when +# no LoadBalancer class is set. Applicable values: lbipam, nodeipam, none # @schema # type: [string] # @schema -# -- defaultLBServiceIPAM indicates the default LoadBalancer Service IPAM when -# no LoadBalancer class is set. Applicable values: lbipam, nodeipam, none defaultLBServiceIPAM: lbipam nodeIPAM: # -- Configure Node IPAM @@ -2401,7 +2147,7 @@ localRedirectPolicy: false localRedirectPolicies: # -- Enable local redirect policies. enabled: false - + # -- Limit the allowed addresses in Address Matcher rule of # Local Redirect Policies to the given CIDRs. # @schema@ @@ -2431,7 +2177,7 @@ maglev: {} # type: [null, boolean] # @schema # -- (bool) Enables masquerading of IPv4 traffic leaving the node from endpoints. -# @default -- `true` unless ipam eni mode is active +# @default -- `true` unless ipam eni mode is active enableIPv4Masquerade: ~ # -- Enables masquerading of IPv6 traffic leaving the node from endpoints. enableIPv6Masquerade: true @@ -2520,7 +2266,7 @@ loadBalancer: # -- serviceTopology enables K8s Topology Aware Hints -based service # endpoints filtering - serviceTopology: false + # serviceTopology: false # -- L7 LoadBalancer l7: @@ -2544,6 +2290,8 @@ loadBalancer: algorithm: round_robin # -- Configure N-S k8s service loadbalancing nodePort: + # -- Enable the Cilium NodePort service implementation. + enabled: false # -- Port range to use for NodePort services. # range: "30000,32767" @@ -2588,10 +2336,6 @@ pprof: address: localhost # -- Configure pprof listen port for cilium-agent port: 6060 - # -- Enable mutex contention profiling for cilium-agent and set the fraction of sampled events (set to 1 to sample all events) - mutexProfileFraction: 0 - # -- Enable goroutine blocking profiling for cilium-agent and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) - blockProfileRate: 0 # -- Configure prometheus metrics on the configured port at /metrics prometheus: metricsService: false @@ -2716,12 +2460,6 @@ envoy: initialFetchTimeoutSeconds: 30 # -- Maximum number of concurrent retries on Envoy clusters maxConcurrentRetries: 128 - # -- Maximum number of connections on Envoy clusters - clusterMaxConnections: 1024 - # -- Maximum number of requests on Envoy clusters - clusterMaxRequests: 1024 - # -- Maximum number of global downstream connections - maxGlobalDownstreamConnections: 50000 # -- Maximum number of retries for each HTTP request httpRetryCount: 3 # -- ProxyMaxRequestsPerConnection specifies the max_requests_per_connection setting for Envoy @@ -2738,9 +2476,6 @@ envoy: xffNumTrustedHopsL7PolicyIngress: 0 # -- Number of trusted hops regarding the x-forwarded-for and related HTTP headers for the egress L7 policy enforcement Envoy listeners. xffNumTrustedHopsL7PolicyEgress: 0 - # -- For cases when CiliumEnvoyConfig is not used directly (Ingress, Gateway), configures Cilium BPF Metadata listener filter - # to use the original source address when extracting the metadata for a request. - useOriginalSourceAddress: true # @schema # type: [null, string] # @schema @@ -2759,8 +2494,6 @@ envoy: pullPolicy: "${PULL_POLICY}" digest: "${CILIUM_ENVOY_DIGEST}" useDigest: true - # -- Init containers added to the cilium Envoy DaemonSet. - initContainers: [] # -- Additional containers added to the cilium Envoy DaemonSet. extraContainers: [] # -- Additional envoy container arguments. @@ -2993,16 +2726,17 @@ resourceQuotas: pods: "15" # Need to document default ################## +#sessionAffinity: false # -- Annotations to be added to all cilium-secret namespaces (resources under templates/cilium-secrets-namespace) secretsNamespaceAnnotations: {} -# -- Labels to be added to all cilium-secret namespaces (resources under templates/cilium-secrets-namespace) -secretsNamespaceLabels: {} # -- Do not run Cilium agent when running with clean mode. Useful to completely # uninstall Cilium as it will stop Cilium from starting and create artifacts # in the node. sleepAfterInit: false +# -- Enable check of service source ranges (currently, only for LoadBalancer). +svcSourceRangeCheck: true # -- Synchronize Kubernetes nodes to kvstore and perform CNP GC. synchronizeK8sNodes: true # -- Configure TLS configuration in the agent. @@ -3085,9 +2819,6 @@ tls: # @default -- `"vxlan"` tunnelProtocol: "" # -- IP family for the underlay. -# Possible values: -# - "ipv4" -# - "ipv6" # @default -- `"ipv4"` underlayProtocol: "" # -- Enable native-routing mode or tunneling mode. @@ -3108,11 +2839,6 @@ tunnelSourcePortRange: 0-0 # - reject (default) # - drop serviceNoBackendResponse: reject -# -- Configure what the response should be to pod egress traffic denied by network policy. -# Possible values: -# - none (default) -# - icmp -policyDenyResponse: none # -- Configure the underlying network MTU to overwrite auto-detected MTU. # This value doesn't change the host network interface MTU i.e. eth0 or ens0. # It changes the MTU for cilium_net@cilium_host, cilium_host@cilium_net, @@ -3198,7 +2924,7 @@ operator: # @schema # type: [null, array] # @schema - tolerations: + tolerations: - key: "node-role.kubernetes.io/control-plane" operator: Exists - key: "node-role.kubernetes.io/master" #deprecated @@ -3290,10 +3016,6 @@ operator: address: localhost # -- Configure pprof listen port for cilium-operator port: 6061 - # -- Enable mutex contention profiling for cilium-operator and set the fraction of sampled events (set to 1 to sample all events) - mutexProfileFraction: 0 - # -- Enable goroutine blocking profiling for cilium-operator and set the rate of sampled events in nanoseconds (set to 1 to sample all events [warning: performance overhead]) - blockProfileRate: 0 # -- Enable prometheus metrics for cilium-operator on the configured port at # /metrics prometheus: @@ -3327,17 +3049,6 @@ operator: # @schema # -- Metrics relabeling configs for the ServiceMonitor cilium-operator metricRelabelings: ~ - # -- TLS configuration for Prometheus - tls: - enabled: false - server: - # -- Name of the Secret containing the certificate, key and CA files for the Prometheus server. - existingSecret: "" - mtls: - # When set to true enforces mutual TLS between Operator Prometheus server and its clients. - # False allow non-mutual TLS connections. - # This option has no effect when TLS is disabled. - enabled: false # -- Grafana dashboards for cilium-operator # grafana can import dashboards based on the label and value # ref: https://github.com/grafana/helm-charts/tree/main/charts/grafana#sidecar-for-dashboards @@ -3371,12 +3082,6 @@ operator: # -- Interval, in seconds, to check if there are any pods that are not # managed by Cilium. intervalSeconds: 15 - # -- Selector for pods that should be restarted when not managed by Cilium. - # If not set, defaults to built-in selector "k8s-app=kube-dns". Set to empty string to select all pods. - # @schema - # type: [null, string] - # @schema - selector: ~ nodeinit: # -- Enable the node initialization DaemonSet enabled: false @@ -3431,9 +3136,6 @@ nodeinit: # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources: requests: - # @schema - # type: [integer, string] - # @schema cpu: 100m memory: 100Mi # -- Security context to be added to nodeinit pods. @@ -3458,8 +3160,6 @@ nodeinit: # -- bootstrapFile is the location of the file where the bootstrap timestamp is # written by the node-init DaemonSet bootstrapFile: "/tmp/cilium-bootstrap.d/cilium-bootstrap-time" - # -- wait for Cloud init to finish on the host and assume the node has cloud init installed - waitForCloudInit: false # -- startup offers way to customize startup nodeinit script (pre and post position) startup: preScript: "" @@ -3593,9 +3293,7 @@ enableCriticalPriorityClass: true # on AArch64 as the images do not currently ship a version of Envoy. #disableEnvoyVersionCheck: false clustermesh: - # -- Deploy clustermesh-apiserver for clustermesh. This option is typically - # used with ``clustermesh.config.enabled=true``. Refer to the - # ``clustermesh.config.enabled=true``documentation for more information. + # -- Deploy clustermesh-apiserver for clustermesh useAPIServer: false # -- The maximum number of clusters to support in a ClusterMesh. This value # cannot be changed on running clusters, and all clusters in a ClusterMesh @@ -3603,133 +3301,45 @@ clustermesh: # maximum allocatable cluster-local identities. # Supported values are 255 and 511. maxConnectedClusters: 255 - # -- The time to live for the cache of a remote cluster after connectivity is - # lost. If the connection is not re-established within this duration, the - # cached data is revoked to prevent stale state. If not specified or set to - # 0s, the cache is never revoked (default). - cacheTTL: "0s" # -- Enable the synchronization of Kubernetes EndpointSlices corresponding to # the remote endpoints of appropriately-annotated global services through ClusterMesh enableEndpointSliceSynchronization: false - # -- Enable Multi-Cluster Services API support (deprecated; use clustermesh.mcsapi.enabled) + # -- Enable Multi-Cluster Services API support enableMCSAPISupport: false # -- Control whether policy rules assume by default the local cluster if not explicitly selected - policyDefaultLocalCluster: true + policyDefaultLocalCluster: false # -- Annotations to be added to all top-level clustermesh objects (resources under templates/clustermesh-apiserver and templates/clustermesh-config) annotations: {} # -- Clustermesh explicit configuration. config: # -- Enable the Clustermesh explicit configuration. - # If set to false, you need to provide the following resources yourself: - # - (Secret) cilium-clustermesh (used by cilium-agent/cilium-operator to connect to - # the local etcd instance if KVStoreMesh is enabled or the remote clusters - # if KVStoreMesh is disabled) - # - (Secret) cilium-kvstoremesh (used by KVStoreMesh to connect to the remote clusters) - # - (ConfigMap) clustermesh-remote-users (used to create one etcd user per remote cluster - # if clustermesh-apiserver is used and `clustermesh.apiserver.tls.authMode` is not - # set to `legacy`) enabled: false # -- Default dns domain for the Clustermesh API servers # This is used in the case cluster addresses are not provided # and IPs are used. domain: mesh.cilium.io - # -- Clusters to be peered in the mesh. - # @schema - # type: [object, array] - # @schema + # -- List of clusters to be peered in the mesh. clusters: [] - # You can use a dict of clusters (recommended): # clusters: - # # -- Name of the cluster - # cluster1: - # # -- Whether to enable this cluster in the mesh. Optional, defaults to true. - # enabled: true - # # -- Address of the cluster, use this if you created DNS records for - # # the cluster Clustermesh API server. - # address: cluster1.mesh.cilium.io - # # -- Port of the cluster Clustermesh API server. - # port: 2379 - # # -- IPs of the cluster Clustermesh API server, use multiple ones when - # # you have multiple IPs to access the Clustermesh API server. - # ips: - # - 172.18.255.201 - # # -- (deprecated) base64 encoded PEM values for the cluster client certificate, private key and certificate authority. - # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the - # # "remote" private key and certificate available in the local cluster are automatically used instead. - # tls: - # cert: "" - # key: "" - # caCert: "" - # - # Or alternatively you can use a list of clusters: - # clusters: - # # -- Name of the cluster + # # -- Name of the cluster # - name: cluster1 - # # -- Address of the cluster, use this if you created DNS records for - # # the cluster Clustermesh API server. + # # -- Address of the cluster, use this if you created DNS records for + # # the cluster Clustermesh API server. # address: cluster1.mesh.cilium.io - # # -- Port of the cluster Clustermesh API server. + # # -- Port of the cluster Clustermesh API server. # port: 2379 - # # -- IPs of the cluster Clustermesh API server, use multiple ones when - # # you have multiple IPs to access the Clustermesh API server. + # # -- IPs of the cluster Clustermesh API server, use multiple ones when + # # you have multiple IPs to access the Clustermesh API server. # ips: # - 172.18.255.201 - # # -- (deprecated) base64 encoded PEM values for the cluster client certificate, private key and certificate authority. - # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the - # # "remote" private key and certificate available in the local cluster are automatically used instead. + # # -- base64 encoded PEM values for the cluster client certificate, private key and certificate authority. + # # These fields can (and should) be omitted in case the CA is shared across clusters. In that case, the + # # "remote" private key and certificate available in the local cluster are automatically used instead. # tls: # cert: "" # key: "" # caCert: "" - mcsapi: - # -- Enable Multi-Cluster Services API support - enabled: false - # -- Enabled MCS-API CRDs auto-installation - installCRDs: true - corednsAutoConfigure: - # -- Enable auto-configuration of CoreDNS for Multi-Cluster Services API. - # CoreDNS MUST be at least in version v1.12.2 to run this. - enabled: false - coredns: - # -- The Deployment for the cluster CoreDNS service - deploymentName: coredns - # -- The Service Account name for the cluster CoreDNS service - serviceAccountName: coredns - # -- The ConfigMap name for the cluster CoreDNS service - configMapName: coredns - # -- The namespace for the cluster CoreDNS service - namespace: kube-system - # -- The cluster domain for the cluster CoreDNS service - clusterDomain: cluster.local - # -- The clusterset domain for the cluster CoreDNS service - clustersetDomain: clusterset.local - # -- Additional arguments to `clustermesh-apiserver coredns-mcsapi-auto-configure`. - extraArgs: [] - # -- Seconds after which the completed job pod will be deleted - ttlSecondsAfterFinished: 1800 - # -- Labels to be added to coredns-mcsapi-autoconfig pods - podLabels: {} - # -- Annotations to be added to the coredns-mcsapi-autoconfig Job - annotations: {} - # -- Node selector for coredns-mcsapi-autoconfig - # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector - nodeSelector: {} - # -- Priority class for coredns-mcsapi-autoconfig - # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass - priorityClassName: "" - # -- Node tolerations for pod assignment on nodes with taints - # ref: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ - tolerations: [] - # -- Resource limits for coredns-mcsapi-autoconfig - # ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers - resources: {} - # -- Additional coredns-mcsapi-autoconfig volumes. - extraVolumes: [] - # -- Additional coredns-mcsapi-autoconfig volumeMounts. - extraVolumeMounts: [] - # -- Affinity for coredns-mcsapi-autoconfig - affinity: {} apiserver: # -- Clustermesh API server image. image: @@ -3835,12 +3445,17 @@ clustermesh: # - "external": ``clustermesh-apiserver`` will sync remote cluster information to the etcd used as kvstore. This can't be enabled with crd identity allocation mode. kvstoreMode: "internal" service: - # -- (bool) Set externallyCreated to true to create the clustermesh-apiserver service outside this helm chart. - # For example after external load balancer controllers are created. - externallyCreated: false # -- The type of service used for apiserver access. type: NodePort # -- Optional port to use as the node port for apiserver access. + # + # WARNING: make sure to configure a different NodePort in each cluster if + # kube-proxy replacement is enabled, as Cilium is currently affected by a known + # bug (#24692) when NodePorts are handled by the KPR implementation. If a service + # with the same NodePort exists both in the local and the remote cluster, all + # traffic originating from inside the cluster and targeting the corresponding + # NodePort will be redirected to a local backend, regardless of whether the + # destination node belongs to the local or the remote cluster. nodePort: 32379 # -- Annotations for the clustermesh-apiserver service. # Example annotations to configure an internal load balancer on different cloud providers: @@ -4009,15 +3624,13 @@ clustermesh: # The "remote" certificate must be generated with CN=remote- # if provided manually. Cluster mode is meaningful only when the same # CA is shared across all clusters part of the mesh. - authMode: migration - # -- (deprecated) Allow users to provide their own certificates + authMode: legacy + # -- Allow users to provide their own certificates # Users may need to provide their certificates using # a mechanism that requires they provide their own secrets. # This setting does not apply to any of the auto-generated # mechanisms below, it only restricts the creation of secrets # via the `tls-provided` templates. - # This option is deprecated as secrets are expected to be created - # externally when 'auto' is not enabled. enableSecrets: true # -- Configure automatic TLS certificates generation. # A Kubernetes CronJob is used the generate any @@ -4026,14 +3639,7 @@ clustermesh: auto: # -- When set to true, automatically generate a CA and certificates to # enable mTLS between clustermesh-apiserver and external workload instances. - # - # When set to false you need to pre-create the following secrets: - # - clustermesh-apiserver-server-cert - # - clustermesh-apiserver-admin-cert - # - clustermesh-apiserver-remote-cert - # - clustermesh-apiserver-local-cert - # The above secret should at least contains the keys `tls.crt` and `tls.key` - # and optionally `ca.crt` if a CA bundle is not configured. + # If set to false, the certs to be provided by setting appropriate values below. enabled: true # Sets the method to auto-generate certificates. Supported values: # - helm: This method uses Helm to generate all certificates. @@ -4065,13 +3671,10 @@ clustermesh: # name: ca-issuer # -- certmanager issuer used when clustermesh.apiserver.tls.auto.method=certmanager. certManagerIssuerRef: {} - # -- base64 encoded PEM values for the clustermesh-apiserver server certificate and private key. # Used if 'auto' is not enabled. server: - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. cert: "" - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. key: "" # -- Extra DNS names added to certificate when it's auto generated extraDnsNames: [] @@ -4080,16 +3683,17 @@ clustermesh: # -- base64 encoded PEM values for the clustermesh-apiserver admin certificate and private key. # Used if 'auto' is not enabled. admin: - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. cert: "" - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. + key: "" + # -- base64 encoded PEM values for the clustermesh-apiserver client certificate and private key. + # Used if 'auto' is not enabled. + client: + cert: "" key: "" # -- base64 encoded PEM values for the clustermesh-apiserver remote cluster certificate and private key. # Used if 'auto' is not enabled. remote: - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. cert: "" - # -- Deprecated, as secrets will always need to be created externally if `auto` is disabled. key: "" # clustermesh-apiserver Prometheus metrics configuration metrics: @@ -4244,7 +3848,7 @@ authentication: # -- Enable authentication processing and garbage collection. # Note that if disabled, policy enforcement will still block requests that require authentication. # But the resulting authentication requests for these requests will not be processed, therefore the requests not be allowed. - enabled: false + enabled: true # -- Buffer size of the channel Cilium uses to receive authentication events from the signal map. queueSize: 1024 # -- Buffer size of the channel Cilium uses to receive certificate expiration events from auth handlers. @@ -4437,41 +4041,4 @@ authentication: enableInternalTrafficPolicy: true # -- Enable LoadBalancer IP Address Management enableLBIPAM: true -# -- Standalone DNS Proxy Configuration -# Note: The standalone DNS proxy uses the agent's dnsProxy.* configuration -# for DNS settings (proxyPort, enableDnsCompression) to ensure consistency. -standaloneDnsProxy: - # -- Enable standalone DNS proxy (alpha feature) - enabled: false - # -- Roll out Standalone DNS proxy automatically when configmap is updated. - rollOutPods: false - # -- Standalone DNS proxy annotations - annotations: {} - # -- Standalone DNS proxy debug mode - debug: false - # -- Standalone DNS proxy server port - serverPort: 10095 - # -- Standalone DNS proxy Node Selector - nodeSelector: - kubernetes.io/os: linux - # -- Standalone DNS proxy tolerations - tolerations: [] - # -- Standalone DNS proxy auto mount service account token - automountServiceAccountToken: false - # -- Standalone DNS proxy update strategy - updateStrategy: - type: RollingUpdate - rollingUpdate: - maxSurge: 2 - maxUnavailable: 0 - # -- Standalone DNS proxy image - image: - # @schema - # type: [null, string] - # @schema - override: ~ - repository: "${STANDALONE_DNS_PROXY_REPO}" - tag: "${STANDALONE_DNS_PROXY_VERSION}" - digest: "${STANDALONE_DNS_PROXY_DIGEST}" - useDigest: ${USE_DIGESTS} - pullPolicy: "${PULL_POLICY}" + diff --git a/packages/system/cilium/images/cilium/Dockerfile b/packages/system/cilium/images/cilium/Dockerfile index 32fc6fb8..ebe65c83 100644 --- a/packages/system/cilium/images/cilium/Dockerfile +++ b/packages/system/cilium/images/cilium/Dockerfile @@ -1,2 +1,2 @@ -ARG VERSION=v1.19.3 +ARG VERSION=v1.18.6 FROM quay.io/cilium/cilium:${VERSION} diff --git a/packages/system/cilium/values-apparmor.yaml b/packages/system/cilium/values-apparmor.yaml deleted file mode 100644 index 0712836c..00000000 --- a/packages/system/cilium/values-apparmor.yaml +++ /dev/null @@ -1,20 +0,0 @@ -cilium: - # Opt out of the cri-containerd.apparmor.d profile for containers that invoke - # nsenter to join the host cgroup/mount namespace. The kernel reports the - # denial as a blocked "ptrace" operation. Required on Ubuntu 22.04+ and - # other distros that load this AppArmor profile by default, where the - # denial otherwise puts cilium-agent into Init:CrashLoopBackOff. - # The deprecated annotations are used because k8s >= 1.30 pod-level - # appArmorProfile: Unconfined is not honoured by containerd CRI today - # (kubernetes/kubernetes#125069). - # Only applied on non-Talos cilium variants where cgroup.autoMount.enabled is - # true — on Talos mount-cgroup is not rendered and the kube-apiserver would - # reject an annotation referencing a non-existent container. - # mount-bpf-fs is intentionally excluded: it renders with its own - # securityContext.privileged=true, and the kernel does not apply AppArmor - # profiles to privileged containers. - podAnnotations: - container.apparmor.security.beta.kubernetes.io/cilium-agent: unconfined - container.apparmor.security.beta.kubernetes.io/clean-cilium-state: unconfined - container.apparmor.security.beta.kubernetes.io/mount-cgroup: unconfined - container.apparmor.security.beta.kubernetes.io/apply-sysctl-overwrites: unconfined diff --git a/packages/system/cilium/values-kilo.yaml b/packages/system/cilium/values-kilo.yaml deleted file mode 100644 index c303ef0a..00000000 --- a/packages/system/cilium/values-kilo.yaml +++ /dev/null @@ -1,3 +0,0 @@ -cilium: - hostFirewall: - enabled: false diff --git a/packages/system/cilium/values.yaml b/packages/system/cilium/values.yaml index 9aba7cb9..49a028f0 100644 --- a/packages/system/cilium/values.yaml +++ b/packages/system/cilium/values.yaml @@ -15,11 +15,10 @@ cilium: mode: "kubernetes" image: repository: ghcr.io/cozystack/cozystack/cilium - tag: 1.19.3 - digest: "sha256:700f06f4803a838a8e830be5ace4650e3ad82bdefabfb2f4d110368d307a5efb" + tag: 1.18.6 + digest: "sha256:4f4585f8adc3b8becd15d3999f3900a4d3d650f2ab7f85ca8c661f3807113d01" envoy: enabled: false rollOutCiliumPods: true operator: rollOutPods: true - replicas: 1 diff --git a/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml b/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml index 3655a8db..eb6c67f6 100644 --- a/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml +++ b/packages/system/clickhouse-rd/cozyrds/clickhouse.yaml @@ -8,7 +8,7 @@ spec: singular: clickhouse plural: clickhouses openAPISchema: |- - {"title":"Chart Values","type":"object","properties":{"replicas":{"description":"Number of ClickHouse replicas.","type":"integer","default":2},"shards":{"description":"Number of ClickHouse shards.","type":"integer","default":1},"resources":{"description":"Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted.","type":"string","default":"small","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"10Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"logStorageSize":{"description":"Size of Persistent Volume for logs.","default":"2Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"logTTL":{"description":"TTL (expiration time) for `query_log` and `query_thread_log`.","type":"integer","default":15},"users":{"description":"Users configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"password":{"description":"Password for the user.","type":"string"},"readonly":{"description":"User is readonly (default: false).","type":"boolean"}}}},"backup":{"description":"Backup configuration.","type":"object","default":{},"required":["cleanupStrategy","enabled","resticPassword","s3AccessKey","s3Bucket","s3Region","s3SecretKey","schedule"],"properties":{"cleanupStrategy":{"description":"Retention strategy for cleaning up old backups.","type":"string","default":"--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"},"enabled":{"description":"Enable regular backups (default: false).","type":"boolean","default":false},"resticPassword":{"description":"Password for Restic backup encryption.","type":"string","default":""},"s3AccessKey":{"description":"Access key for S3 authentication.","type":"string","default":""},"s3Bucket":{"description":"S3 bucket used for storing backups.","type":"string","default":"s3.example.org/clickhouse-backups"},"s3Region":{"description":"AWS S3 region where backups are stored.","type":"string","default":"us-east-1"},"s3SecretKey":{"description":"Secret key for S3 authentication.","type":"string","default":""},"schedule":{"description":"Cron schedule for automated backups.","type":"string","default":"0 2 * * *"}}},"clickhouseKeeper":{"description":"ClickHouse Keeper configuration.","type":"object","default":{},"properties":{"enabled":{"description":"Deploy ClickHouse Keeper for cluster coordination.","type":"boolean","default":true},"replicas":{"description":"Number of Keeper replicas.","type":"integer","default":3},"resourcesPreset":{"description":"Default sizing preset.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}}}} + {"title":"Chart Values","type":"object","properties":{"backup":{"description":"Backup configuration.","type":"object","default":{},"required":["cleanupStrategy","enabled","resticPassword","s3AccessKey","s3Bucket","s3Region","s3SecretKey","schedule"],"properties":{"cleanupStrategy":{"description":"Retention strategy for cleaning up old backups.","type":"string","default":"--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"},"enabled":{"description":"Enable regular backups (default: false).","type":"boolean","default":false},"resticPassword":{"description":"Password for Restic backup encryption.","type":"string","default":""},"s3AccessKey":{"description":"Access key for S3 authentication.","type":"string","default":""},"s3Bucket":{"description":"S3 bucket used for storing backups.","type":"string","default":"s3.example.org/clickhouse-backups"},"s3Region":{"description":"AWS S3 region where backups are stored.","type":"string","default":"us-east-1"},"s3SecretKey":{"description":"Secret key for S3 authentication.","type":"string","default":""},"schedule":{"description":"Cron schedule for automated backups.","type":"string","default":"0 2 * * *"}}},"clickhouseKeeper":{"description":"ClickHouse Keeper configuration.","type":"object","default":{},"properties":{"enabled":{"description":"Deploy ClickHouse Keeper for cluster coordination.","type":"boolean","default":true},"replicas":{"description":"Number of Keeper replicas.","type":"integer","default":3},"resourcesPreset":{"description":"Default sizing preset.","type":"string","default":"micro","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"logStorageSize":{"description":"Size of Persistent Volume for logs.","default":"2Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"logTTL":{"description":"TTL (expiration time) for `query_log` and `query_thread_log`.","type":"integer","default":15},"replicas":{"description":"Number of ClickHouse replicas.","type":"integer","default":2},"resources":{"description":"Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each replica.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted.","type":"string","default":"small","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"shards":{"description":"Number of ClickHouse shards.","type":"integer","default":1},"size":{"description":"Persistent Volume Claim size available for application data.","default":"10Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"users":{"description":"Users configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"password":{"description":"Password for the user.","type":"string"},"readonly":{"description":"User is readonly (default: false).","type":"boolean"}}}}}} release: prefix: clickhouse- labels: diff --git a/packages/system/cluster-autoscaler/Chart.yaml b/packages/system/cluster-autoscaler/Chart.yaml deleted file mode 100644 index 9aa2bb43..00000000 --- a/packages/system/cluster-autoscaler/Chart.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v2 -name: cozy-cluster-autoscaler -description: Cluster Autoscaler for automatic node scaling -version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/cluster-autoscaler/Makefile b/packages/system/cluster-autoscaler/Makefile deleted file mode 100644 index 605d4d4e..00000000 --- a/packages/system/cluster-autoscaler/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -export NAME=cluster-autoscaler -export NAMESPACE=cozy-$(NAME) - -include ../../../hack/package.mk - -update: - rm -rf charts - helm repo add autoscaler https://kubernetes.github.io/autoscaler - helm repo update autoscaler - helm pull autoscaler/cluster-autoscaler --untar --untardir charts diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/.helmignore b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/.helmignore deleted file mode 100644 index 0e8a0eb3..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/.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/packages/system/cluster-autoscaler/charts/cluster-autoscaler/Chart.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/Chart.yaml deleted file mode 100644 index 0c46f2c8..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/Chart.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v2 -appVersion: 1.35.0 -description: Scales Kubernetes worker nodes within autoscaling groups. -home: https://github.com/kubernetes/autoscaler -icon: https://github.com/kubernetes/kubernetes/raw/master/logo/logo.png -maintainers: -- email: guyjtempleton@googlemail.com - name: gjtempleton -name: cluster-autoscaler -sources: -- https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler -type: application -version: 9.55.0 diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/README.md b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/README.md deleted file mode 100644 index 8a9da750..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/README.md +++ /dev/null @@ -1,545 +0,0 @@ -# cluster-autoscaler - -Scales Kubernetes worker nodes within autoscaling groups. - -## TL;DR - -```console -$ helm repo add autoscaler https://kubernetes.github.io/autoscaler - -# Method 1 - Using Autodiscovery -$ helm install my-release autoscaler/cluster-autoscaler \ - --set 'autoDiscovery.clusterName'= - -# Method 2 - Specifying groups manually -$ helm install my-release autoscaler/cluster-autoscaler \ - --set "autoscalingGroups[0].name=your-asg-name" \ - --set "autoscalingGroups[0].maxSize=10" \ - --set "autoscalingGroups[0].minSize=1" -``` - -## Introduction - -This chart bootstraps a cluster-autoscaler deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -## Prerequisites - -- Helm 3+ -- Kubernetes 1.8+ - - [Older versions](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#releases) may work by overriding the `image`. Cluster autoscaler internally simulates the scheduler and bugs between mismatched versions may be subtle. -- Azure AKS specific Prerequisites: - - Kubernetes 1.10+ with RBAC-enabled. - -## Previous Helm Chart - -The previous `cluster-autoscaler` Helm chart hosted at [helm/charts](https://github.com/helm/charts) has been moved to this repository in accordance with the [Deprecation timeline](https://github.com/helm/charts#deprecation-timeline). Note that a few things have changed between this version and the old version: - -- This repository **only** supports Helm chart installations using Helm 3+ since the `apiVersion` on the charts has been marked as `v2`. -- Previous versions of the Helm chart have not been migrated - -## Migration from 1.X to 9.X+ versions of this Chart - -**TL;DR:** -You should choose to use versions >=9.0.0 of the `cluster-autoscaler` chart published from this repository; previous versions, and the `cluster-autoscaler-chart` with versioning 1.X.X published from this repository are deprecated. - -
- Previous versions of this chart - further details -On initial migration of this chart from the `helm/charts` repository this chart was renamed from `cluster-autoscaler` to `cluster-autoscaler-chart` due to technical limitations. This affected all `1.X` releases of the chart, version 2.0.0 of this chart exists only to mark the [`cluster-autoscaler-chart` chart](https://artifacthub.io/packages/helm/cluster-autoscaler/cluster-autoscaler-chart) as deprecated. - -Releases of the chart from `9.0.0` onwards return the naming of the chart to `cluster-autoscaler` and return to following the versioning established by the chart's previous location at . - -To migrate from a 1.X release of the chart to a `9.0.0` or later release, you should first uninstall your `1.X` install of the `cluster-autoscaler-chart` chart, before performing the installation of the new `cluster-autoscaler` chart. -
- -## Migration from 9.0 to 9.1 - -Starting from `9.1.0` the `envFromConfigMap` value is expected to contain the name of a ConfigMap that is used as ref for `envFrom`, similar to `envFromSecret`. If you want to keep the previous behaviour of `envFromConfigMap` you must rename it to `extraEnvConfigMaps`. - -## Installing the Chart - -**By default, no deployment is created and nothing will autoscale**. - -You must provide some minimal configuration, either to specify instance groups or enable auto-discovery. It is not recommended to do both. - -Either: - -- Set `autoDiscovery.clusterName` and provide additional autodiscovery options if necessary **or** -- Set static node group configurations for one or more node groups (using `autoscalingGroups` or `autoscalingGroupsnamePrefix`). - -To create a valid configuration, follow instructions for your cloud provider: - -- [AWS](#aws---using-auto-discovery-of-tagged-instance-groups) -- [GCE](#gce) -- [Azure](#azure) -- [OpenStack Magnum](#openstack-magnum) -- [Cluster API](#cluster-api) -- [Exoscale](#exoscale) -- [Hetzner Cloud](#hetzner-cloud) -- [Civo](#civo) - -### Templating the autoDiscovery.clusterName - -The cluster name can be templated in the `autoDiscovery.clusterName` variable. This is useful when the cluster name is dynamically generated based on other values coming from external systems like Argo CD or Flux. This also allows you to use global Helm values to set the cluster name, e.g., `autoDiscovery.clusterName={{ .Values.global.clusterName }}`, so that you don't need to set it in more than 1 location in the values file. - -### AWS - Using auto-discovery of tagged instance groups - -Auto-discovery finds ASGs tags as below and automatically manages them based on the min and max size specified in the ASG. `cloudProvider=aws` only. - -- Tag the ASGs with keys to match `.Values.autoDiscovery.tags`, by default: `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/` -- Verify the [IAM Permissions](#aws---iam) -- Set `autoDiscovery.clusterName=` -- Set `awsRegion=` -- Set (option) `awsAccessKeyID=` and `awsSecretAccessKey=` if you want to [use AWS credentials directly instead of an instance role](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials) - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set autoDiscovery.clusterName= \ - --set awsRegion= -``` - -Alternatively with your own AWS credentials - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set autoDiscovery.clusterName= \ - --set awsRegion= \ - --set awsAccessKeyID= \ - --set awsSecretAccessKey= -``` - -#### Specifying groups manually - -Without autodiscovery, specify an array of elements each containing ASG name, min size, max size. The sizes specified here will be applied to the ASG, assuming IAM permissions are correctly configured. - -- Verify the [IAM Permissions](#aws---iam) -- Either provide a yaml file setting `autoscalingGroups` (see values.yaml) or use `--set` e.g.: - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set "autoscalingGroups[0].name=your-asg-name" \ - --set "autoscalingGroups[0].maxSize=10" \ - --set "autoscalingGroups[0].minSize=1" -``` - -#### Auto-discovery - -For auto-discovery of instances to work, they must be tagged with the keys in `.Values.autoDiscovery.tags`, which by default are `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/`. - -The value of the tag does not matter, only the key. - -An example kops spec excerpt: - -```yaml -apiVersion: kops/v1alpha2 -kind: Cluster -metadata: - name: my.cluster.internal -spec: - additionalPolicies: - node: | - [ - {"Effect":"Allow","Action":["autoscaling:DescribeAutoScalingGroups","autoscaling:DescribeAutoScalingInstances","autoscaling:DescribeLaunchConfigurations","autoscaling:DescribeTags","autoscaling:SetDesiredCapacity","autoscaling:TerminateInstanceInAutoScalingGroup"],"Resource":"*"} - ] - ... ---- -apiVersion: kops/v1alpha2 -kind: InstanceGroup -metadata: - labels: - kops.k8s.io/cluster: my.cluster.internal - name: my-instances -spec: - cloudLabels: - k8s.io/cluster-autoscaler/enabled: "" - k8s.io/cluster-autoscaler/my.cluster.internal: "" - image: kops.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-01-14 - machineType: r4.large - maxSize: 4 - minSize: 0 -``` - -In this example you would need to `--set autoDiscovery.clusterName=my.cluster.internal` when installing. - -It is not recommended to try to mix this with setting `autoscalingGroups`. - -See [autoscaler AWS documentation](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup) for a more discussion of the setup. - -### GCE - -The following parameters are required: - -- `autoDiscovery.clusterName=any-name` -- `cloud-provider=gce` -- `autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1` - -To use Managed Instance Group (MIG) auto-discovery, provide a YAML file setting `autoscalingGroupsnamePrefix` (see values.yaml) or use `--set` when installing the Chart - e.g. - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set "autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1" \ - --set autoDiscovery.clusterName= \ - --set cloudProvider=gce -``` - -Note that `your-ig-prefix` should be a _prefix_ matching one or more MIGs, and _not_ the full name of the MIG. For example, to match multiple instance groups - `k8s-node-group-a-standard`, `k8s-node-group-b-gpu`, you would use a prefix of `k8s-node-group-`. - -Prefixes will be rendered using `tpl` function so you can use any value of your choice if that's a valid prefix. For instance (ignore escaping characters): `gke-{{ .Values.autoDiscovery.clusterName }}` - -In the event you want to explicitly specify MIGs instead of using auto-discovery, set members of the `autoscalingGroups` array directly - e.g. - -``` -# where 'n' is the index, starting at 0 ---set autoscalingGroups[n].name=https://content.googleapis.com/compute/v1/projects/$PROJECTID/zones/$ZONENAME/instanceGroups/$FULL-MIG-NAME,autoscalingGroups[n].maxSize=$MAXSIZE,autoscalingGroups[n].minSize=$MINSIZE -``` - -### Azure - -The following parameters are required: - -- `cloudProvider=azure` -- `autoscalingGroups[0].name=your-vmss,autoscalingGroups[0].maxSize=10,autoscalingGroups[0].minSize=1` -- `azureClientID: "your-service-principal-app-id"` -- `azureClientSecret: "your-service-principal-client-secret"` -- `azureSubscriptionID: "your-azure-subscription-id"` -- `azureTenantID: "your-azure-tenant-id"` -- `azureResourceGroup: "your-aks-cluster-resource-group-name"` -- `azureVMType: "vmss"` - -### OpenStack Magnum - -`cloudProvider: magnum` must be set, and then one of - -- `magnumClusterName=` and `autoscalingGroups` with the names of node groups and min/max node counts -- or `autoDiscovery.clusterName=` with one or more `autoDiscovery.roles`. - -Additionally, `cloudConfigPath: "/etc/kubernetes/cloud-config"` must be set as this should be the location of the cloud-config file on the host. - -Example values files can be found [here](../../cluster-autoscaler/cloudprovider/magnum/examples). - -Install the chart with - -```console -$ helm install my-release autoscaler/cluster-autoscaler -f myvalues.yaml -``` - -### Cluster-API - -`cloudProvider: clusterapi` must be set, and then one or more of - -- `autoDiscovery.clusterName` -- or `autoDiscovery.namespace` -- or `autoDiscovery.labels` - -See [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery) for more details. - -Additional config parameters available, see the `values.yaml` for more details - -- `clusterAPIMode` -- `clusterAPIKubeconfigSecret` -- `clusterAPIWorkloadKubeconfigPath` -- `clusterAPICloudConfigPath` - -### Exoscale - -Create a `values.yaml` file with the following content: -```yaml -cloudProvider: exoscale -autoDiscovery: - clusterName: cluster.local # this value is not used, but must be set -``` - -Optionally, you may specify the minimum and maximum size of a particular nodepool by adding the following to the `values.yaml` file: -```yaml -autoscalingGroups: - - name: your-nodepool-name - maxSize: 10 - minSize: 1 -``` - -Create an Exoscale API key with appropriate permissions as described in [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md). -A secret of name `-exoscale-cluster-autoscaler` needs to be created, containing the api key and secret, as well as the zone. - -```console -$ kubectl create secret generic my-release-exoscale-cluster-autoscaler \ - --from-literal=api-key="EXOxxxxxxxxxxxxxxxxxxxxxxxx" \ - --from-literal=api-secret="xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --from-literal=api-zone="ch-gva-2" -``` - -After creating the secret, the chart may be installed: - -```console -$ helm install my-release autoscaler/cluster-autoscaler -f values.yaml -``` - -Read [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md) for further information on the setup without helm. - -### Hetzner Cloud - -The following parameters are required: - -- `cloudProvider=hetzner` -- `extraEnv.HCLOUD_TOKEN=...` -- `autoscalingGroups=...` - -Each autoscaling group requires an additional `instanceType` and `region` key to be set. - -Read [cluster-autoscaler/cloudprovider/hetzner/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/hetzner/README.md) for further information on the setup without helm. - -### Civo - -The following parameters are required: - -- `cloudProvider=civo` -- `autoscalingGroups=...` - -When installing the helm chart to the namespace `kube-system`, you can set `secretKeyRefNameOverride` to `civo-api-access`. -Otherwise specify the following parameters: - -- `civoApiUrl=https://api.civo.com` -- `civoApiKey=...` -- `civoClusterID=...` -- `civoRegion=...` - -Read [cluster-autoscaler/cloudprovider/civo/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/civo/README.md) for further information on the setup without helm. - -## Uninstalling the Chart - -To uninstall `my-release`: - -```console -$ helm uninstall my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -> **Tip**: List all releases using `helm list` or start clean with `helm uninstall my-release` - -## Additional Configuration - -### AWS - IAM - -The worker running the cluster autoscaler will need access to certain resources and actions depending on the version you run and your configuration of it. - -For the up-to-date IAM permissions required, please see the [cluster autoscaler's AWS Cloudprovider Readme](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#iam-policy) and switch to the tag of the cluster autoscaler image you are using. - -### AWS - IAM Roles for Service Accounts (IRSA) - -For Kubernetes clusters that use Amazon EKS, the service account can be configured with an IAM role using [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) to avoid needing to grant access to the worker nodes for AWS resources. - -In order to accomplish this, you will first need to create a new IAM role with the above mentions policies. Take care in [configuring the trust relationship](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html#iam-role-configuration) to restrict access just to the service account used by cluster autoscaler. - -Once you have the IAM role configured, you would then need to `--set rbac.serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789012:role/MyRoleName` when installing. Alternatively, you can embed templates in values (ignore escaping characters): - -```yaml -rbac: - serviceAccount: - annotations: - eks.amazonaws.com/role-arn: "{{ .Values.aws.myroleARN }}" -``` - -### Azure - Using azure workload identity - -You can use the project [Azure workload identity](https://github.com/Azure/azure-workload-identity), to automatically configure the correct setup for your pods to use federated identity with Azure. - -You can also set the correct settings yourself instead of relying on this project. - -For example the following configuration will configure the Autoscaler to use your federated identity: - -```yaml -azureUseWorkloadIdentityExtension: true -extraEnv: - AZURE_CLIENT_ID: USER ASSIGNED IDENTITY CLIENT ID - AZURE_TENANT_ID: USER ASSIGNED IDENTITY TENANT ID - AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/tokens/azure-identity-token - AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ -extraVolumes: -- name: azure-identity-token - projected: - defaultMode: 420 - sources: - - serviceAccountToken: - audience: api://AzureADTokenExchange - expirationSeconds: 3600 - path: azure-identity-token -extraVolumeMounts: -- mountPath: /var/run/secrets/tokens - name: azure-identity-token - readOnly: true -``` - -### Custom arguments - -You can use the `customArgs` value to give any argument to cluster autoscaler command. - -Typical use case is to give an environment variable as an argument which will be interpolated at execution time. - -This is helpful when you need to inject values from configmap or secret. - -## Troubleshooting - -The chart will succeed even if the container arguments are incorrect. A few minutes after starting `kubectl logs -l "app=aws-cluster-autoscaler" --tail=50` should loop through something like - -``` -polling_autoscaler.go:111] Poll finished -static_autoscaler.go:97] Starting main loop -utils.go:435] No pod using affinity / antiaffinity found in cluster, disabling affinity predicate for this loop -static_autoscaler.go:230] Filtering out schedulables -``` - -If not, find a pod that the deployment created and `describe` it, paying close attention to the arguments under `Command`. e.g.: - -``` -Containers: - cluster-autoscaler: - Command: - ./cluster-autoscaler - --cloud-provider=aws -# if specifying ASGs manually - --nodes=1:10:your-scaling-group-name -# if using autodiscovery - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/ - --v=4 -``` - -### PodSecurityPolicy - -Though enough for the majority of installations, the default PodSecurityPolicy _could_ be too restrictive depending on the specifics of your release. Please make sure to check that the template fits with any customizations made or disable it by setting `rbac.pspEnabled` to `false`. - -### VerticalPodAutoscaler - -The CA Helm Chart can install a [`VerticalPodAutoscaler`](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/README.md) object from Chart version `9.27.0` -onwards for the Cluster Autoscaler Deployment to scale the CA as appropriate, but for that, we -need to install the VPA to the cluster separately. A VPA can help minimize wasted resources -when usage spikes periodically or remediate containers that are being OOMKilled. - -The following example snippet can be used to install VPA that allows scaling down from the default recommendations of the deployment template: - -```yaml -vpa: - enabled: true - containerPolicy: - minAllowed: - cpu: 20m - memory: 50Mi -``` - -## Values - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| additionalLabels | object | `{}` | Labels to add to each object of the chart. | -| affinity | object | `{}` | Affinity for pod assignment | -| autoDiscovery.clusterName | string | `nil` | Enable autodiscovery for `cloudProvider=aws`, for groups matching `autoDiscovery.tags`. autoDiscovery.clusterName -- Enable autodiscovery for `cloudProvider=azure`, using tags defined in https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/azure/README.md#auto-discovery-setup. Enable autodiscovery for `cloudProvider=clusterapi`, for groups matching `autoDiscovery.labels`. Enable autodiscovery for `cloudProvider=gce`, but no MIG tagging required. Enable autodiscovery for `cloudProvider=magnum`, for groups matching `autoDiscovery.roles`. | -| autoDiscovery.labels | list | `[]` | Cluster-API labels to match https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery | -| autoDiscovery.namespace | string | `nil` | Enable autodiscovery via cluster namespace for for `cloudProvider=clusterapi` | -| autoDiscovery.roles | list | `["worker"]` | Magnum node group roles to match. | -| autoDiscovery.tags | list | `["k8s.io/cluster-autoscaler/enabled","k8s.io/cluster-autoscaler/{{ .Values.autoDiscovery.clusterName }}"]` | ASG tags to match, run through `tpl`. | -| autoscalingGroups | list | `[]` | For AWS, Azure AKS, Exoscale or Magnum. At least one element is required if not using `autoDiscovery`. For example:
 - name: asg1
maxSize: 2
minSize: 1
For Hetzner Cloud, the `instanceType` and `region` keys are also required.
 - name: mypool
maxSize: 2
minSize: 1
instanceType: CPX21
region: FSN1
| -| autoscalingGroupsnamePrefix | list | `[]` | For GCE. At least one element is required if not using `autoDiscovery`. For example:
 - name: ig01
maxSize: 10
minSize: 0
| -| awsAccessKeyID | string | `""` | AWS access key ID ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) | -| awsRegion | string | `""` | AWS region (required if `cloudProvider=aws`) | -| awsSecretAccessKey | string | `""` | AWS access secret key ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) | -| azureClientID | string | `""` | Service Principal ClientID with contributor permission to Cluster and Node ResourceGroup. Required if `cloudProvider=azure` | -| azureClientSecret | string | `""` | Service Principal ClientSecret with contributor permission to Cluster and Node ResourceGroup. Required if `cloudProvider=azure` | -| azureEnableForceDelete | bool | `false` | Whether to force delete VMs or VMSS instances when scaling down. | -| azureResourceGroup | string | `""` | Azure resource group that the cluster is located. Required if `cloudProvider=azure` | -| azureSubscriptionID | string | `""` | Azure subscription where the resources are located. Required if `cloudProvider=azure` | -| azureTenantID | string | `""` | Azure tenant where the resources are located. Required if `cloudProvider=azure` | -| azureUseManagedIdentityExtension | bool | `false` | Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID, resource group, and azure AKS cluster name are set. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. | -| azureUseWorkloadIdentityExtension | bool | `false` | Whether to use Azure's workload identity extension for credentials. See the project here: https://github.com/Azure/azure-workload-identity for more details. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. | -| azureUserAssignedIdentityID | string | `""` | When vmss has multiple user assigned identity assigned, azureUserAssignedIdentityID specifies which identity to be used | -| azureVMType | string | `"vmss"` | Azure VM type. | -| civoApiKey | string | `""` | API key for the Civo API. Required if `cloudProvider=civo` | -| civoApiUrl | string | `"https://api.civo.com"` | URL for the Civo API. Required if `cloudProvider=civo` | -| civoClusterID | string | `""` | Cluster ID for the Civo cluster. Required if `cloudProvider=civo` | -| civoRegion | string | `""` | Region for the Civo cluster. Required if `cloudProvider=civo` | -| cloudConfigPath | string | `""` | Configuration file for cloud provider. | -| cloudProvider | string | `"aws"` | The cloud provider where the autoscaler runs. Currently only `gce`, `aws`, `azure`, `magnum`, `clusterapi`, `civo` and `coreweave` are supported. `aws` supported for AWS. `gce` for GCE. `azure` for Azure AKS. `magnum` for OpenStack Magnum, `clusterapi` for Cluster API. `civo` for Civo Cloud. `coreweave` for CoreWeave. | -| clusterAPICloudConfigPath | string | `"/etc/kubernetes/mgmt-kubeconfig"` | Path to kubeconfig for connecting to Cluster API Management Cluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or incluster-kubeconfig` | -| clusterAPIConfigMapsNamespace | string | `""` | Namespace on the workload cluster to store Leader election and status configmaps | -| clusterAPIKubeconfigSecret | string | `""` | Secret containing kubeconfig for connecting to Cluster API managed workloadcluster Required if `cloudProvider=clusterapi` and `clusterAPIMode=kubeconfig-kubeconfig,kubeconfig-incluster or incluster-kubeconfig` | -| clusterAPIMode | string | `"incluster-incluster"` | Cluster API mode, see https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#connecting-cluster-autoscaler-to-cluster-api-management-and-workload-clusters Syntax: workloadClusterMode-ManagementClusterMode for `kubeconfig-kubeconfig`, `incluster-kubeconfig` and `single-kubeconfig` you always must mount the external kubeconfig using either `extraVolumeSecrets` or `extraMounts` and `extraVolumes` if you dont set `clusterAPIKubeconfigSecret`and thus use an in-cluster config or want to use a non capi generated kubeconfig you must do so for the workload kubeconfig as well | -| clusterAPIWorkloadKubeconfigPath | string | `"/etc/kubernetes/value"` | Path to kubeconfig for connecting to Cluster API managed workloadcluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or kubeconfig-incluster` | -| containerSecurityContext | object | `{}` | [Security context for container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) | -| customArgs | list | `[]` | Additional custom container arguments. Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler parameters and their default values. List of arguments as strings. | -| deployment.annotations | object | `{}` | Annotations to add to the Deployment object. | -| deployment.selector | object | `{}` | Labels for Deployment `spec.selector.matchLabels`. | -| dnsConfig | object | `{}` | [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config) | -| dnsPolicy | string | `"ClusterFirst"` | Defaults to `ClusterFirst`. Valid values are: `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`. If autoscaler does not depend on cluster DNS, recommended to set this to `Default`. | -| envFromConfigMap | string | `""` | ConfigMap name to use as envFrom. | -| envFromSecret | string | `""` | Secret name to use as envFrom. | -| expanderPriorities | object | `{}` | The expanderPriorities is used if `extraArgs.expander` contains `priority` and expanderPriorities is also set with the priorities. If `extraArgs.expander` contains `priority`, then expanderPriorities is used to define cluster-autoscaler-priority-expander priorities. See: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/expander/priority/readme.md | -| extraArgs | object | `{"logtostderr":true,"stderrthreshold":"info","v":4}` | Additional container arguments. Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler parameters and their default values. Everything after the first _ will be ignored allowing the use of multi-string arguments. | -| extraEnv | object | `{}` | Additional container environment variables. | -| extraEnvConfigMaps | object | `{}` | Additional container environment variables from ConfigMaps. | -| extraEnvSecrets | object | `{}` | Additional container environment variables from Secrets. | -| extraObjects | list | `[]` | Extra K8s manifests to deploy | -| extraVolumeMounts | list | `[]` | Additional volumes to mount. | -| extraVolumeSecrets | object | `{}` | Additional volumes to mount from Secrets. | -| extraVolumes | list | `[]` | Additional volumes. | -| fullnameOverride | string | `""` | String to fully override `cluster-autoscaler.fullname` template. | -| hostNetwork | bool | `false` | Whether to expose network interfaces of the host machine to pods. | -| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | -| image.pullSecrets | list | `[]` | Image pull secrets | -| image.repository | string | `"registry.k8s.io/autoscaling/cluster-autoscaler"` | Image repository | -| image.tag | string | `"v1.34.2"` | Image tag | -| initContainers | list | `[]` | Any additional init containers. | -| kubeTargetVersionOverride | string | `""` | Allow overriding the `.Capabilities.KubeVersion.GitVersion` check. Useful for `helm template` commands. | -| kwokConfigMapName | string | `"kwok-provider-config"` | configmap for configuring kwok provider | -| magnumCABundlePath | string | `"/etc/kubernetes/ca-bundle.crt"` | Path to the host's CA bundle, from `ca-file` in the cloud-config file. | -| magnumClusterName | string | `""` | Cluster name or ID in Magnum. Required if `cloudProvider=magnum` and not setting `autoDiscovery.clusterName`. | -| nameOverride | string | `""` | String to partially override `cluster-autoscaler.fullname` template (will maintain the release name) | -| nodeSelector | object | `{}` | Node labels for pod assignment. Ref: https://kubernetes.io/docs/user-guide/node-selection/. | -| podAnnotations | object | `{}` | Annotations to add to each pod. | -| podDisruptionBudget | object | `{"annotations":{},"maxUnavailable":1,"selector":{}}` | Pod disruption budget. | -| podDisruptionBudget.annotations | object | `{}` | Annotations to add to the PodDisruptionBudget. | -| podDisruptionBudget.selector | object | `{}` | Override labels for PodDisruptionBudget `spec.selector.matchLabels`. | -| podLabels | object | `{}` | Labels to add to each pod. | -| priorityClassName | string | `"system-cluster-critical"` | priorityClassName | -| priorityConfigMapAnnotations | object | `{}` | Annotations to add to `cluster-autoscaler-priority-expander` ConfigMap. | -| prometheusRule.additionalLabels | object | `{}` | Additional labels to be set in metadata. | -| prometheusRule.enabled | bool | `false` | If true, creates a Prometheus Operator PrometheusRule. | -| prometheusRule.interval | string | `nil` | How often rules in the group are evaluated (falls back to `global.evaluation_interval` if not set). | -| prometheusRule.namespace | string | `"monitoring"` | Namespace which Prometheus is running in. | -| prometheusRule.rules | list | `[]` | Rules spec template (see https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#rule). | -| rbac.additionalRules | list | `[]` | Additional rules for role/clusterrole | -| rbac.annotations | object | `{}` | Additional annotations to add to RBAC resources (Role/RoleBinding/ClusterRole/ClusterRoleBinding). | -| rbac.clusterScoped | bool | `true` | if set to false will only provision RBAC to alter resources in the current namespace. Most useful for Cluster-API | -| rbac.create | bool | `true` | If `true`, create and use RBAC resources. | -| rbac.pspEnabled | bool | `false` | If `true`, creates and uses RBAC resources required in the cluster with [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) enabled. Must be used with `rbac.create` set to `true`. | -| rbac.serviceAccount.annotations | object | `{}` | Additional Service Account annotations. | -| rbac.serviceAccount.automountServiceAccountToken | bool | `true` | Automount API credentials for a Service Account. | -| rbac.serviceAccount.create | bool | `true` | If `true` and `rbac.create` is also true, a Service Account will be created. | -| rbac.serviceAccount.name | string | `""` | The name of the ServiceAccount to use. If not set and create is `true`, a name is generated using the fullname template. | -| replicaCount | int | `1` | Desired number of pods | -| resources | object | `{}` | Pod resource requests and limits. | -| revisionHistoryLimit | int | `10` | The number of revisions to keep. | -| secretKeyRefNameOverride | string | `""` | Overrides the name of the Secret to use when loading the secretKeyRef for AWS, Azure and Civo env variables | -| securityContext | object | `{}` | [Security context for pod](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) | -| service.annotations | object | `{}` | Annotations to add to service | -| service.clusterIP | string | `""` | IP address to assign to service | -| service.create | bool | `true` | If `true`, a Service will be created. | -| service.externalIPs | list | `[]` | List of IP addresses at which the service is available. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips. | -| service.labels | object | `{}` | Labels to add to service | -| service.loadBalancerIP | string | `""` | IP address to assign to load balancer (if supported). | -| service.loadBalancerSourceRanges | list | `[]` | List of IP CIDRs allowed access to load balancer (if supported). | -| service.portName | string | `"http"` | Name for service port. | -| service.selector | object | `{}` | Override labels for Service `spec.selector`. | -| service.servicePort | int | `8085` | Service port to expose. | -| service.type | string | `"ClusterIP"` | Type of service to create. | -| serviceMonitor.annotations | object | `{}` | Annotations to add to service monitor | -| serviceMonitor.enabled | bool | `false` | If true, creates a Prometheus Operator ServiceMonitor. | -| serviceMonitor.interval | string | `"10s"` | Interval that Prometheus scrapes Cluster Autoscaler metrics. | -| serviceMonitor.metricRelabelings | object | `{}` | MetricRelabelConfigs to apply to samples before ingestion. | -| serviceMonitor.namespace | string | `"monitoring"` | Namespace which Prometheus is running in. | -| serviceMonitor.path | string | `"/metrics"` | The path to scrape for metrics; autoscaler exposes `/metrics` (this is standard) | -| serviceMonitor.relabelings | object | `{}` | RelabelConfigs to apply to metrics before scraping. | -| serviceMonitor.selector | object | `{"release":"prometheus-operator"}` | Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install. | -| tolerations | list | `[]` | List of node taints to tolerate (requires Kubernetes >= 1.6). | -| topologySpreadConstraints | list | `[]` | You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19). | -| updateStrategy | object | `{}` | [Deployment update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) | -| vpa | object | `{"containerPolicy":{},"enabled":false,"recommender":"default","updateMode":"Auto"}` | Configure a VerticalPodAutoscaler for the cluster-autoscaler Deployment. | -| vpa.containerPolicy | object | `{}` | [ContainerResourcePolicy](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L159). The containerName is always set to the deployment's container name. This value is required if VPA is enabled. | -| vpa.enabled | bool | `false` | If true, creates a VerticalPodAutoscaler. | -| vpa.recommender | string | `"default"` | Name of the VPA recommender that will provide recommendations for vertical scaling. | -| vpa.updateMode | string | `"Auto"` | [UpdateMode](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L124) | diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/README.md.gotmpl b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/README.md.gotmpl deleted file mode 100644 index 0567e283..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/README.md.gotmpl +++ /dev/null @@ -1,426 +0,0 @@ -{{ template "chart.header" . }} - -{{ template "chart.description" . }} - -## TL;DR - -```console -$ helm repo add autoscaler https://kubernetes.github.io/autoscaler - -# Method 1 - Using Autodiscovery -$ helm install my-release autoscaler/cluster-autoscaler \ - --set 'autoDiscovery.clusterName'= - -# Method 2 - Specifying groups manually -$ helm install my-release autoscaler/cluster-autoscaler \ - --set "autoscalingGroups[0].name=your-asg-name" \ - --set "autoscalingGroups[0].maxSize=10" \ - --set "autoscalingGroups[0].minSize=1" -``` - -## Introduction - -This chart bootstraps a cluster-autoscaler deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -## Prerequisites - -- Helm 3+ -- Kubernetes 1.8+ - - [Older versions](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#releases) may work by overriding the `image`. Cluster autoscaler internally simulates the scheduler and bugs between mismatched versions may be subtle. -- Azure AKS specific Prerequisites: - - Kubernetes 1.10+ with RBAC-enabled. - -## Previous Helm Chart - -The previous `cluster-autoscaler` Helm chart hosted at [helm/charts](https://github.com/helm/charts) has been moved to this repository in accordance with the [Deprecation timeline](https://github.com/helm/charts#deprecation-timeline). Note that a few things have changed between this version and the old version: - -- This repository **only** supports Helm chart installations using Helm 3+ since the `apiVersion` on the charts has been marked as `v2`. -- Previous versions of the Helm chart have not been migrated - -## Migration from 1.X to 9.X+ versions of this Chart - -**TL;DR:** -You should choose to use versions >=9.0.0 of the `cluster-autoscaler` chart published from this repository; previous versions, and the `cluster-autoscaler-chart` with versioning 1.X.X published from this repository are deprecated. - -
- Previous versions of this chart - further details -On initial migration of this chart from the `helm/charts` repository this chart was renamed from `cluster-autoscaler` to `cluster-autoscaler-chart` due to technical limitations. This affected all `1.X` releases of the chart, version 2.0.0 of this chart exists only to mark the [`cluster-autoscaler-chart` chart](https://artifacthub.io/packages/helm/cluster-autoscaler/cluster-autoscaler-chart) as deprecated. - -Releases of the chart from `9.0.0` onwards return the naming of the chart to `cluster-autoscaler` and return to following the versioning established by the chart's previous location at . - -To migrate from a 1.X release of the chart to a `9.0.0` or later release, you should first uninstall your `1.X` install of the `cluster-autoscaler-chart` chart, before performing the installation of the new `cluster-autoscaler` chart. -
- -## Migration from 9.0 to 9.1 - -Starting from `9.1.0` the `envFromConfigMap` value is expected to contain the name of a ConfigMap that is used as ref for `envFrom`, similar to `envFromSecret`. If you want to keep the previous behaviour of `envFromConfigMap` you must rename it to `extraEnvConfigMaps`. - -## Installing the Chart - -**By default, no deployment is created and nothing will autoscale**. - -You must provide some minimal configuration, either to specify instance groups or enable auto-discovery. It is not recommended to do both. - -Either: - -- Set `autoDiscovery.clusterName` and provide additional autodiscovery options if necessary **or** -- Set static node group configurations for one or more node groups (using `autoscalingGroups` or `autoscalingGroupsnamePrefix`). - -To create a valid configuration, follow instructions for your cloud provider: - -- [AWS](#aws---using-auto-discovery-of-tagged-instance-groups) -- [GCE](#gce) -- [Azure](#azure) -- [OpenStack Magnum](#openstack-magnum) -- [Cluster API](#cluster-api) -- [Exoscale](#exoscale) -- [Hetzner Cloud](#hetzner-cloud) -- [Civo](#civo) - -### Templating the autoDiscovery.clusterName - -The cluster name can be templated in the `autoDiscovery.clusterName` variable. This is useful when the cluster name is dynamically generated based on other values coming from external systems like Argo CD or Flux. This also allows you to use global Helm values to set the cluster name, e.g., `autoDiscovery.clusterName={{`{{ .Values.global.clusterName }}`}}`, so that you don't need to set it in more than 1 location in the values file. - -### AWS - Using auto-discovery of tagged instance groups - -Auto-discovery finds ASGs tags as below and automatically manages them based on the min and max size specified in the ASG. `cloudProvider=aws` only. - -- Tag the ASGs with keys to match `.Values.autoDiscovery.tags`, by default: `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/` -- Verify the [IAM Permissions](#aws---iam) -- Set `autoDiscovery.clusterName=` -- Set `awsRegion=` -- Set (option) `awsAccessKeyID=` and `awsSecretAccessKey=` if you want to [use AWS credentials directly instead of an instance role](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials) - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set autoDiscovery.clusterName= \ - --set awsRegion= -``` - -Alternatively with your own AWS credentials - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set autoDiscovery.clusterName= \ - --set awsRegion= \ - --set awsAccessKeyID= \ - --set awsSecretAccessKey= -``` - -#### Specifying groups manually - -Without autodiscovery, specify an array of elements each containing ASG name, min size, max size. The sizes specified here will be applied to the ASG, assuming IAM permissions are correctly configured. - -- Verify the [IAM Permissions](#aws---iam) -- Either provide a yaml file setting `autoscalingGroups` (see values.yaml) or use `--set` e.g.: - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set "autoscalingGroups[0].name=your-asg-name" \ - --set "autoscalingGroups[0].maxSize=10" \ - --set "autoscalingGroups[0].minSize=1" -``` - -#### Auto-discovery - -For auto-discovery of instances to work, they must be tagged with the keys in `.Values.autoDiscovery.tags`, which by default are `k8s.io/cluster-autoscaler/enabled` and `k8s.io/cluster-autoscaler/`. - -The value of the tag does not matter, only the key. - -An example kops spec excerpt: - -```yaml -apiVersion: kops/v1alpha2 -kind: Cluster -metadata: - name: my.cluster.internal -spec: - additionalPolicies: - node: | - [ - {"Effect":"Allow","Action":["autoscaling:DescribeAutoScalingGroups","autoscaling:DescribeAutoScalingInstances","autoscaling:DescribeLaunchConfigurations","autoscaling:DescribeTags","autoscaling:SetDesiredCapacity","autoscaling:TerminateInstanceInAutoScalingGroup"],"Resource":"*"} - ] - ... ---- -apiVersion: kops/v1alpha2 -kind: InstanceGroup -metadata: - labels: - kops.k8s.io/cluster: my.cluster.internal - name: my-instances -spec: - cloudLabels: - k8s.io/cluster-autoscaler/enabled: "" - k8s.io/cluster-autoscaler/my.cluster.internal: "" - image: kops.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-01-14 - machineType: r4.large - maxSize: 4 - minSize: 0 -``` - -In this example you would need to `--set autoDiscovery.clusterName=my.cluster.internal` when installing. - -It is not recommended to try to mix this with setting `autoscalingGroups`. - -See [autoscaler AWS documentation](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup) for a more discussion of the setup. - -### GCE - -The following parameters are required: - -- `autoDiscovery.clusterName=any-name` -- `cloud-provider=gce` -- `autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1` - -To use Managed Instance Group (MIG) auto-discovery, provide a YAML file setting `autoscalingGroupsnamePrefix` (see values.yaml) or use `--set` when installing the Chart - e.g. - -```console -$ helm install my-release autoscaler/cluster-autoscaler \ - --set "autoscalingGroupsnamePrefix[0].name=your-ig-prefix,autoscalingGroupsnamePrefix[0].maxSize=10,autoscalingGroupsnamePrefix[0].minSize=1" \ - --set autoDiscovery.clusterName= \ - --set cloudProvider=gce -``` - -Note that `your-ig-prefix` should be a _prefix_ matching one or more MIGs, and _not_ the full name of the MIG. For example, to match multiple instance groups - `k8s-node-group-a-standard`, `k8s-node-group-b-gpu`, you would use a prefix of `k8s-node-group-`. - -Prefixes will be rendered using `tpl` function so you can use any value of your choice if that's a valid prefix. For instance (ignore escaping characters): `gke-{{`{{ .Values.autoDiscovery.clusterName }}`}}` - -In the event you want to explicitly specify MIGs instead of using auto-discovery, set members of the `autoscalingGroups` array directly - e.g. - -``` -# where 'n' is the index, starting at 0 ---set autoscalingGroups[n].name=https://content.googleapis.com/compute/v1/projects/$PROJECTID/zones/$ZONENAME/instanceGroups/$FULL-MIG-NAME,autoscalingGroups[n].maxSize=$MAXSIZE,autoscalingGroups[n].minSize=$MINSIZE -``` - -### Azure - -The following parameters are required: - -- `cloudProvider=azure` -- `autoscalingGroups[0].name=your-vmss,autoscalingGroups[0].maxSize=10,autoscalingGroups[0].minSize=1` -- `azureClientID: "your-service-principal-app-id"` -- `azureClientSecret: "your-service-principal-client-secret"` -- `azureSubscriptionID: "your-azure-subscription-id"` -- `azureTenantID: "your-azure-tenant-id"` -- `azureResourceGroup: "your-aks-cluster-resource-group-name"` -- `azureVMType: "vmss"` - -### OpenStack Magnum - -`cloudProvider: magnum` must be set, and then one of - -- `magnumClusterName=` and `autoscalingGroups` with the names of node groups and min/max node counts -- or `autoDiscovery.clusterName=` with one or more `autoDiscovery.roles`. - -Additionally, `cloudConfigPath: "/etc/kubernetes/cloud-config"` must be set as this should be the location of the cloud-config file on the host. - -Example values files can be found [here](../../cluster-autoscaler/cloudprovider/magnum/examples). - -Install the chart with - -```console -$ helm install my-release autoscaler/cluster-autoscaler -f myvalues.yaml -``` - -### Cluster-API - -`cloudProvider: clusterapi` must be set, and then one or more of - -- `autoDiscovery.clusterName` -- or `autoDiscovery.namespace` -- or `autoDiscovery.labels` - -See [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery) for more details. - -Additional config parameters available, see the `values.yaml` for more details - -- `clusterAPIMode` -- `clusterAPIKubeconfigSecret` -- `clusterAPIWorkloadKubeconfigPath` -- `clusterAPICloudConfigPath` - -### Exoscale - -Create a `values.yaml` file with the following content: -```yaml -cloudProvider: exoscale -autoDiscovery: - clusterName: cluster.local # this value is not used, but must be set -``` - -Optionally, you may specify the minimum and maximum size of a particular nodepool by adding the following to the `values.yaml` file: -```yaml -autoscalingGroups: - - name: your-nodepool-name - maxSize: 10 - minSize: 1 -``` - -Create an Exoscale API key with appropriate permissions as described in [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md). -A secret of name `-exoscale-cluster-autoscaler` needs to be created, containing the api key and secret, as well as the zone. - -```console -$ kubectl create secret generic my-release-exoscale-cluster-autoscaler \ - --from-literal=api-key="EXOxxxxxxxxxxxxxxxxxxxxxxxx" \ - --from-literal=api-secret="xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --from-literal=api-zone="ch-gva-2" -``` - -After creating the secret, the chart may be installed: - -```console -$ helm install my-release autoscaler/cluster-autoscaler -f values.yaml -``` - -Read [cluster-autoscaler/cloudprovider/exoscale/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/exoscale/README.md) for further information on the setup without helm. - -### Hetzner Cloud - -The following parameters are required: - -- `cloudProvider=hetzner` -- `extraEnv.HCLOUD_TOKEN=...` -- `autoscalingGroups=...` - -Each autoscaling group requires an additional `instanceType` and `region` key to be set. - -Read [cluster-autoscaler/cloudprovider/hetzner/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/hetzner/README.md) for further information on the setup without helm. - -### Civo - -The following parameters are required: - -- `cloudProvider=civo` -- `autoscalingGroups=...` - -When installing the helm chart to the namespace `kube-system`, you can set `secretKeyRefNameOverride` to `civo-api-access`. -Otherwise specify the following parameters: - -- `civoApiUrl=https://api.civo.com` -- `civoApiKey=...` -- `civoClusterID=...` -- `civoRegion=...` - -Read [cluster-autoscaler/cloudprovider/civo/README.md](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/civo/README.md) for further information on the setup without helm. - -## Uninstalling the Chart - -To uninstall `my-release`: - -```console -$ helm uninstall my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -> **Tip**: List all releases using `helm list` or start clean with `helm uninstall my-release` - -## Additional Configuration - -### AWS - IAM - -The worker running the cluster autoscaler will need access to certain resources and actions depending on the version you run and your configuration of it. - -For the up-to-date IAM permissions required, please see the [cluster autoscaler's AWS Cloudprovider Readme](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#iam-policy) and switch to the tag of the cluster autoscaler image you are using. - -### AWS - IAM Roles for Service Accounts (IRSA) - -For Kubernetes clusters that use Amazon EKS, the service account can be configured with an IAM role using [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) to avoid needing to grant access to the worker nodes for AWS resources. - -In order to accomplish this, you will first need to create a new IAM role with the above mentions policies. Take care in [configuring the trust relationship](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html#iam-role-configuration) to restrict access just to the service account used by cluster autoscaler. - -Once you have the IAM role configured, you would then need to `--set rbac.serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789012:role/MyRoleName` when installing. Alternatively, you can embed templates in values (ignore escaping characters): - -```yaml -rbac: - serviceAccount: - annotations: - eks.amazonaws.com/role-arn: "{{`{{ .Values.aws.myroleARN `}}}}" -``` - -### Azure - Using azure workload identity - -You can use the project [Azure workload identity](https://github.com/Azure/azure-workload-identity), to automatically configure the correct setup for your pods to use federated identity with Azure. - -You can also set the correct settings yourself instead of relying on this project. - -For example the following configuration will configure the Autoscaler to use your federated identity: - -```yaml -azureUseWorkloadIdentityExtension: true -extraEnv: - AZURE_CLIENT_ID: USER ASSIGNED IDENTITY CLIENT ID - AZURE_TENANT_ID: USER ASSIGNED IDENTITY TENANT ID - AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/tokens/azure-identity-token - AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/ -extraVolumes: -- name: azure-identity-token - projected: - defaultMode: 420 - sources: - - serviceAccountToken: - audience: api://AzureADTokenExchange - expirationSeconds: 3600 - path: azure-identity-token -extraVolumeMounts: -- mountPath: /var/run/secrets/tokens - name: azure-identity-token - readOnly: true -``` - -### Custom arguments - -You can use the `customArgs` value to give any argument to cluster autoscaler command. - -Typical use case is to give an environment variable as an argument which will be interpolated at execution time. - -This is helpful when you need to inject values from configmap or secret. - -## Troubleshooting - -The chart will succeed even if the container arguments are incorrect. A few minutes after starting `kubectl logs -l "app=aws-cluster-autoscaler" --tail=50` should loop through something like - -``` -polling_autoscaler.go:111] Poll finished -static_autoscaler.go:97] Starting main loop -utils.go:435] No pod using affinity / antiaffinity found in cluster, disabling affinity predicate for this loop -static_autoscaler.go:230] Filtering out schedulables -``` - -If not, find a pod that the deployment created and `describe` it, paying close attention to the arguments under `Command`. e.g.: - -``` -Containers: - cluster-autoscaler: - Command: - ./cluster-autoscaler - --cloud-provider=aws -# if specifying ASGs manually - --nodes=1:10:your-scaling-group-name -# if using autodiscovery - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/ - --v=4 -``` - -### PodSecurityPolicy - -Though enough for the majority of installations, the default PodSecurityPolicy _could_ be too restrictive depending on the specifics of your release. Please make sure to check that the template fits with any customizations made or disable it by setting `rbac.pspEnabled` to `false`. - -### VerticalPodAutoscaler - -The CA Helm Chart can install a [`VerticalPodAutoscaler`](https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/README.md) object from Chart version `9.27.0` -onwards for the Cluster Autoscaler Deployment to scale the CA as appropriate, but for that, we -need to install the VPA to the cluster separately. A VPA can help minimize wasted resources -when usage spikes periodically or remediate containers that are being OOMKilled. - -The following example snippet can be used to install VPA that allows scaling down from the default recommendations of the deployment template: - -```yaml -vpa: - enabled: true - containerPolicy: - minAllowed: - cpu: 20m - memory: 50Mi -``` - -{{ template "chart.valuesSection" . }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/NOTES.txt b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/NOTES.txt deleted file mode 100644 index 1a87a3d1..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/NOTES.txt +++ /dev/null @@ -1,18 +0,0 @@ -{{- if or ( or .Values.autoDiscovery.clusterName .Values.autoDiscovery.namespace .Values.autoDiscovery.labels ) .Values.autoscalingGroups }} - -To verify that cluster-autoscaler has started, run: - - kubectl --namespace={{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ template "cluster-autoscaler.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" - -{{- else -}} - -############################################################################## -#### ERROR: You must specify values for either #### -#### autoDiscovery or autoscalingGroups[] #### -############################################################################## - -The deployment and pod will not be created and the installation is not functional -See README: - open https://github.com/kubernetes/autoscaler/tree/master/charts/cluster-autoscaler - -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/_helpers.tpl b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/_helpers.tpl deleted file mode 100644 index c7e80f4d..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/_helpers.tpl +++ /dev/null @@ -1,160 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "cluster-autoscaler.name" -}} -{{- default (printf "%s-%s" .Values.cloudProvider .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). -*/}} -{{- define "cluster-autoscaler.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default (printf "%s-%s" .Values.cloudProvider .Chart.Name) .Values.nameOverride -}} -{{- if ne $name .Release.Name -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s" $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "cluster-autoscaler.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Return instance and name labels. -*/}} -{{- define "cluster-autoscaler.instance-name" -}} -app.kubernetes.io/instance: {{ .Release.Name | quote }} -app.kubernetes.io/name: {{ include "cluster-autoscaler.name" . | quote }} -{{- end -}} - - -{{/* -Return labels, including instance and name. -*/}} -{{- define "cluster-autoscaler.labels" -}} -{{ include "cluster-autoscaler.instance-name" . }} -app.kubernetes.io/managed-by: {{ .Release.Service | quote }} -helm.sh/chart: {{ include "cluster-autoscaler.chart" . | quote }} -{{- if .Values.additionalLabels }} -{{ toYaml .Values.additionalLabels }} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for deployment. -*/}} -{{- define "deployment.apiVersion" -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "<1.9-0" $kubeTargetVersion -}} -{{- print "apps/v1beta2" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for podsecuritypolicy. -*/}} -{{- define "podsecuritypolicy.apiVersion" -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "<1.10-0" $kubeTargetVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "policy/v1beta1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for podDisruptionBudget. -*/}} -{{- define "podDisruptionBudget.apiVersion" -}} -{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} -{{- if semverCompare "<1.21-0" $kubeTargetVersion -}} -{{- print "policy/v1beta1" -}} -{{- else -}} -{{- print "policy/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the service account name used by the pod. -*/}} -{{- define "cluster-autoscaler.serviceAccountName" -}} -{{- if .Values.rbac.serviceAccount.create -}} - {{ default (include "cluster-autoscaler.fullname" .) .Values.rbac.serviceAccount.name }} -{{- else -}} - {{ default "default" .Values.rbac.serviceAccount.name }} -{{- end -}} -{{- end -}} - -{{/* -Return true if the priority expander is enabled -*/}} -{{- define "cluster-autoscaler.priorityExpanderEnabled" -}} -{{- $expanders := splitList "," (default "" .Values.extraArgs.expander) -}} -{{- if has "priority" $expanders -}} -{{- true -}} -{{- end -}} -{{- end -}} - -{{/* -autoDiscovery.clusterName for clusterapi. -*/}} -{{- define "cluster-autoscaler.capiAutodiscovery.clusterName" -}} -{{- print "clusterName=" -}}{{ tpl (.Values.autoDiscovery.clusterName) . }} -{{- end -}} - -{{/* -autoDiscovery.namespace for clusterapi. -*/}} -{{- define "cluster-autoscaler.capiAutodiscovery.namespace" -}} -{{- print "namespace=" }}{{ .Values.autoDiscovery.namespace -}} -{{- end -}} - -{{/* -autoDiscovery.labels for clusterapi. -*/}} -{{- define "cluster-autoscaler.capiAutodiscovery.labels" -}} -{{- range $i, $el := .Values.autoDiscovery.labels -}} -{{- if $i -}}{{- print "," -}}{{- end -}} -{{- range $key, $val := $el -}} -{{- $key -}}{{- print "=" -}}{{- $val -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Return the autodiscoveryparameters for clusterapi. -*/}} -{{- define "cluster-autoscaler.capiAutodiscoveryConfig" -}} -{{- if .Values.autoDiscovery.clusterName -}} -{{ include "cluster-autoscaler.capiAutodiscovery.clusterName" . }} - {{- if .Values.autoDiscovery.namespace }} - {{- print "," -}} - {{ include "cluster-autoscaler.capiAutodiscovery.namespace" . }} - {{- end -}} - {{- if .Values.autoDiscovery.labels }} - {{- print "," -}} - {{ include "cluster-autoscaler.capiAutodiscovery.labels" . }} - {{- end -}} -{{- else if .Values.autoDiscovery.namespace -}} -{{ include "cluster-autoscaler.capiAutodiscovery.namespace" . }} - {{- if .Values.autoDiscovery.labels }} - {{- print "," -}} - {{ include "cluster-autoscaler.capiAutodiscovery.labels" . }} - {{- end -}} -{{- else if .Values.autoDiscovery.labels -}} - {{ include "cluster-autoscaler.capiAutodiscovery.labels" . }} -{{- end -}} -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/clusterrole.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/clusterrole.yaml deleted file mode 100644 index e6a9018e..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/clusterrole.yaml +++ /dev/null @@ -1,210 +0,0 @@ -{{- if and .Values.rbac.create .Values.rbac.clusterScoped -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: -{{- with .Values.rbac.annotations }} - annotations: - {{- range $k, $v := . }} - {{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }} - {{- end }} -{{- end }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.fullname" . }} -rules: -{{- if (eq .Values.cloudProvider "coreweave") }} - - apiGroups: - - "compute.coreweave.com" - resources: - - nodepools - verbs: - - get - - list - - patch - - update -{{- end }} - - apiGroups: - - "" - resources: - - events - - endpoints - verbs: - - create - - patch - - apiGroups: - - "" - resources: - - pods/eviction - verbs: - - create - - apiGroups: - - "" - resources: - - pods/status - verbs: - - update - - apiGroups: - - "" - resources: - - endpoints - resourceNames: - - cluster-autoscaler - verbs: - - get - - update - - apiGroups: - - "" - resources: - - nodes - verbs: - - watch - - list -{{- if (eq .Values.cloudProvider "kwok") }} - - create -{{- end }} -{{- if or (eq .Values.cloudProvider "kwok") (eq .Values.cloudProvider "huaweicloud") }} - - delete -{{- end }} - - get - - update - - apiGroups: - - resource.k8s.io - resources: - - resourceslices - - deviceclasses - - resourceclaims - verbs: - - watch - - list - - get - - apiGroups: - - "" - resources: - - namespaces - - pods - - services - - replicationcontrollers - - persistentvolumeclaims - - persistentvolumes - verbs: - - watch - - list - - get - - apiGroups: - - batch - resources: - - jobs - - cronjobs - verbs: - - watch - - list - - get - - apiGroups: - - batch - - extensions - resources: - - jobs - verbs: - - get - - list - - patch - - watch - - apiGroups: - - extensions - resources: - - replicasets - - daemonsets - verbs: - - watch - - list - - get - - apiGroups: - - policy - resources: - - poddisruptionbudgets - verbs: - - watch - - list - - apiGroups: - - apps - resources: - - daemonsets - - replicasets - - statefulsets - verbs: - - watch - - list - - get - - apiGroups: - - storage.k8s.io - resources: - - storageclasses - - csinodes - - csidrivers - - csistoragecapacities - - volumeattachments - verbs: - - watch - - list - - get - - apiGroups: - - "" - resources: - - configmaps - verbs: - - list - - watch - - get - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - apiGroups: - - coordination.k8s.io - resourceNames: - - cluster-autoscaler - resources: - - leases - verbs: - - get - - update -{{- if .Values.rbac.pspEnabled }} - - apiGroups: - - extensions - - policy - resources: - - podsecuritypolicies - resourceNames: - - {{ template "cluster-autoscaler.fullname" . }} - verbs: - - use -{{- end -}} -{{- if and ( and ( eq .Values.cloudProvider "clusterapi" ) ( .Values.rbac.clusterScoped ) ( or ( eq .Values.clusterAPIMode "incluster-incluster" ) ( eq .Values.clusterAPIMode "kubeconfig-incluster" ) ))}} - - apiGroups: - - cluster.x-k8s.io - resources: - - machinedeployments - - machinepools - - machines - - machinesets - verbs: - - get - - list - - update - - watch - - apiGroups: - - cluster.x-k8s.io - resources: - - machinedeployments/scale - - machinepools/scale - verbs: - - get - - patch - - update -{{- end }} -{{- if .Values.rbac.additionalRules }} -{{ toYaml .Values.rbac.additionalRules | indent 2 }} -{{- end }} -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/clusterrolebinding.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/clusterrolebinding.yaml deleted file mode 100644 index 59e6ef67..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if and .Values.rbac.create .Values.rbac.clusterScoped -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: -{{- with .Values.rbac.annotations }} - annotations: - {{- range $k, $v := . }} - {{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }} - {{- end }} -{{- end }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.fullname" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "cluster-autoscaler.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "cluster-autoscaler.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/configmap.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/configmap.yaml deleted file mode 100644 index 6cd0c406..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/configmap.yaml +++ /dev/null @@ -1,416 +0,0 @@ -{{- if or (eq .Values.cloudProvider "kwok") }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Values.kwokConfigMapName | default "kwok-provider-config" }} - namespace: {{ .Release.Namespace }} -data: - config: |- - # if you see '\n' everywhere, remove all the trailing spaces - apiVersion: v1alpha1 - readNodesFrom: configmap # possible values: [cluster,configmap] - nodegroups: - # to specify how to group nodes into a nodegroup - # e.g., you want to treat nodes with same instance type as a nodegroup - # node1: m5.xlarge - # node2: c5.xlarge - # node3: m5.xlarge - # nodegroup1: [node1,node3] - # nodegroup2: [node2] - fromNodeLabelKey: "kwok-nodegroup" - # you can either specify fromNodeLabelKey OR fromNodeAnnotation - # (both are not allowed) - # fromNodeAnnotation: "eks.amazonaws.com/nodegroup" - nodes: - # gpuConfig: - # # to tell kwok provider what label should be considered as GPU label - # gpuLabelKey: "k8s.amazonaws.com/accelerator" - # availableGPUTypes: - # "nvidia-tesla-k80": {} - # "nvidia-tesla-p100": {} - configmap: - name: kwok-provider-templates - kwok: {} # default: fetch latest release of kwok from github and install it - # # you can also manually specify which kwok release you want to install - # # for example: - # kwok: - # release: v0.3.0 - # # you can also disable installing kwok in CA code (and install your own kwok release) - # kwok: - # install: false (true if not specified) ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: kwok-provider-templates - namespace: {{ .Release.Namespace }} -data: - templates: |- - # if you see '\n' everywhere, remove all the trailing spaces - apiVersion: v1 - items: - - apiVersion: v1 - kind: Node - metadata: - annotations: - kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock - node.alpha.kubernetes.io/ttl: "0" - volumes.kubernetes.io/controller-managed-attach-detach: "true" - creationTimestamp: "2023-05-31T04:39:16Z" - labels: - beta.kubernetes.io/arch: amd64 - beta.kubernetes.io/os: linux - kubernetes.io/arch: amd64 - kubernetes.io/hostname: kind-control-plane - kwok-nodegroup: control-plane - kubernetes.io/os: linux - node-role.kubernetes.io/control-plane: "" - node.kubernetes.io/exclude-from-external-load-balancers: "" - name: kind-control-plane - resourceVersion: "506" - uid: 86716ec7-3071-4091-b055-77b4361d1dca - spec: - podCIDR: 10.244.0.0/24 - podCIDRs: - - 10.244.0.0/24 - providerID: kind://docker/kind/kind-control-plane - taints: - - effect: NoSchedule - key: node-role.kubernetes.io/control-plane - status: - addresses: - - address: 172.18.0.2 - type: InternalIP - - address: kind-control-plane - type: Hostname - allocatable: - cpu: "12" - ephemeral-storage: 959786032Ki - hugepages-1Gi: "0" - hugepages-2Mi: "0" - memory: 32781516Ki - pods: "110" - capacity: - cpu: "12" - ephemeral-storage: 959786032Ki - hugepages-1Gi: "0" - hugepages-2Mi: "0" - memory: 32781516Ki - pods: "110" - conditions: - - lastHeartbeatTime: "2023-05-31T04:39:58Z" - lastTransitionTime: "2023-05-31T04:39:13Z" - message: kubelet has sufficient memory available - reason: KubeletHasSufficientMemory - status: "False" - type: MemoryPressure - - lastHeartbeatTime: "2023-05-31T04:39:58Z" - lastTransitionTime: "2023-05-31T04:39:13Z" - message: kubelet has no disk pressure - reason: KubeletHasNoDiskPressure - status: "False" - type: DiskPressure - - lastHeartbeatTime: "2023-05-31T04:39:58Z" - lastTransitionTime: "2023-05-31T04:39:13Z" - message: kubelet has sufficient PID available - reason: KubeletHasSufficientPID - status: "False" - type: PIDPressure - - lastHeartbeatTime: "2023-05-31T04:39:58Z" - lastTransitionTime: "2023-05-31T04:39:46Z" - message: kubelet is posting ready status - reason: KubeletReady - status: "True" - type: Ready - daemonEndpoints: - kubeletEndpoint: - Port: 10250 - images: - - names: - - registry.k8s.io/etcd:3.5.6-0 - sizeBytes: 102542580 - - names: - - docker.io/library/import-2023-03-30@sha256:ba097b515c8c40689733c0f19de377e9bf8995964b7d7150c2045f3dfd166657 - - registry.k8s.io/kube-apiserver:v1.26.3 - sizeBytes: 80392681 - - names: - - docker.io/library/import-2023-03-30@sha256:8dbb345de79d1c44f59a7895da702a5f71997ae72aea056609445c397b0c10dc - - registry.k8s.io/kube-controller-manager:v1.26.3 - sizeBytes: 68538487 - - names: - - docker.io/library/import-2023-03-30@sha256:44db4d50a5f9c8efbac0d37ea974d1c0419a5928f90748d3d491a041a00c20b5 - - registry.k8s.io/kube-proxy:v1.26.3 - sizeBytes: 67217404 - - names: - - docker.io/library/import-2023-03-30@sha256:3dd2337f70af979c7362b5e52bbdfcb3a5fd39c78d94d02145150cd2db86ba39 - - registry.k8s.io/kube-scheduler:v1.26.3 - sizeBytes: 57761399 - - names: - - docker.io/kindest/kindnetd:v20230330-48f316cd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af - - docker.io/kindest/kindnetd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af - sizeBytes: 27726335 - - names: - - docker.io/kindest/local-path-provisioner:v0.0.23-kind.0@sha256:f2d0a02831ff3a03cf51343226670d5060623b43a4cfc4808bd0875b2c4b9501 - sizeBytes: 18664669 - - names: - - registry.k8s.io/coredns/coredns:v1.9.3 - sizeBytes: 14837849 - - names: - - docker.io/kindest/local-path-helper:v20230330-48f316cd@sha256:135203f2441f916fb13dad1561d27f60a6f11f50ec288b01a7d2ee9947c36270 - sizeBytes: 3052037 - - names: - - registry.k8s.io/pause:3.7 - sizeBytes: 311278 - nodeInfo: - architecture: amd64 - bootID: 2d71b318-5d07-4de2-9e61-2da28cf5bbf0 - containerRuntimeVersion: containerd://1.6.19-46-g941215f49 - kernelVersion: 5.15.0-72-generic - kubeProxyVersion: v1.26.3 - kubeletVersion: v1.26.3 - machineID: 96f8c8b8c8ae4600a3654341f207586e - operatingSystem: linux - osImage: Ubuntu 22.04.2 LTS - systemUUID: 111aa932-7f99-4bef-aaf7-36aa7fb9b012 - - apiVersion: v1 - kind: Node - metadata: - annotations: - kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock - node.alpha.kubernetes.io/ttl: "0" - volumes.kubernetes.io/controller-managed-attach-detach: "true" - creationTimestamp: "2023-05-31T04:39:57Z" - labels: - beta.kubernetes.io/arch: amd64 - beta.kubernetes.io/os: linux - kubernetes.io/arch: amd64 - kubernetes.io/hostname: kind-worker - kwok-nodegroup: kind-worker - kubernetes.io/os: linux - name: kind-worker - resourceVersion: "577" - uid: 2ac0eb71-e5cf-4708-bbbf-476e8f19842b - spec: - podCIDR: 10.244.2.0/24 - podCIDRs: - - 10.244.2.0/24 - providerID: kind://docker/kind/kind-worker - status: - addresses: - - address: 172.18.0.3 - type: InternalIP - - address: kind-worker - type: Hostname - allocatable: - cpu: "12" - ephemeral-storage: 959786032Ki - hugepages-1Gi: "0" - hugepages-2Mi: "0" - memory: 32781516Ki - pods: "110" - capacity: - cpu: "12" - ephemeral-storage: 959786032Ki - hugepages-1Gi: "0" - hugepages-2Mi: "0" - memory: 32781516Ki - pods: "110" - conditions: - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:39:57Z" - message: kubelet has sufficient memory available - reason: KubeletHasSufficientMemory - status: "False" - type: MemoryPressure - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:39:57Z" - message: kubelet has no disk pressure - reason: KubeletHasNoDiskPressure - status: "False" - type: DiskPressure - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:39:57Z" - message: kubelet has sufficient PID available - reason: KubeletHasSufficientPID - status: "False" - type: PIDPressure - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:40:05Z" - message: kubelet is posting ready status - reason: KubeletReady - status: "True" - type: Ready - daemonEndpoints: - kubeletEndpoint: - Port: 10250 - images: - - names: - - registry.k8s.io/etcd:3.5.6-0 - sizeBytes: 102542580 - - names: - - docker.io/library/import-2023-03-30@sha256:ba097b515c8c40689733c0f19de377e9bf8995964b7d7150c2045f3dfd166657 - - registry.k8s.io/kube-apiserver:v1.26.3 - sizeBytes: 80392681 - - names: - - docker.io/library/import-2023-03-30@sha256:8dbb345de79d1c44f59a7895da702a5f71997ae72aea056609445c397b0c10dc - - registry.k8s.io/kube-controller-manager:v1.26.3 - sizeBytes: 68538487 - - names: - - docker.io/library/import-2023-03-30@sha256:44db4d50a5f9c8efbac0d37ea974d1c0419a5928f90748d3d491a041a00c20b5 - - registry.k8s.io/kube-proxy:v1.26.3 - sizeBytes: 67217404 - - names: - - docker.io/library/import-2023-03-30@sha256:3dd2337f70af979c7362b5e52bbdfcb3a5fd39c78d94d02145150cd2db86ba39 - - registry.k8s.io/kube-scheduler:v1.26.3 - sizeBytes: 57761399 - - names: - - docker.io/kindest/kindnetd:v20230330-48f316cd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af - - docker.io/kindest/kindnetd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af - sizeBytes: 27726335 - - names: - - docker.io/kindest/local-path-provisioner:v0.0.23-kind.0@sha256:f2d0a02831ff3a03cf51343226670d5060623b43a4cfc4808bd0875b2c4b9501 - sizeBytes: 18664669 - - names: - - registry.k8s.io/coredns/coredns:v1.9.3 - sizeBytes: 14837849 - - names: - - docker.io/kindest/local-path-helper:v20230330-48f316cd@sha256:135203f2441f916fb13dad1561d27f60a6f11f50ec288b01a7d2ee9947c36270 - sizeBytes: 3052037 - - names: - - registry.k8s.io/pause:3.7 - sizeBytes: 311278 - nodeInfo: - architecture: amd64 - bootID: 2d71b318-5d07-4de2-9e61-2da28cf5bbf0 - containerRuntimeVersion: containerd://1.6.19-46-g941215f49 - kernelVersion: 5.15.0-72-generic - kubeProxyVersion: v1.26.3 - kubeletVersion: v1.26.3 - machineID: a98a13ff474d476294935341f1ba9816 - operatingSystem: linux - osImage: Ubuntu 22.04.2 LTS - systemUUID: 5f3c1af8-a385-4776-85e4-73d7f4252b44 - - apiVersion: v1 - kind: Node - metadata: - annotations: - kubeadm.alpha.kubernetes.io/cri-socket: unix:///run/containerd/containerd.sock - node.alpha.kubernetes.io/ttl: "0" - volumes.kubernetes.io/controller-managed-attach-detach: "true" - creationTimestamp: "2023-05-31T04:39:57Z" - labels: - beta.kubernetes.io/arch: amd64 - beta.kubernetes.io/os: linux - kubernetes.io/arch: amd64 - kubernetes.io/hostname: kind-worker2 - kwok-nodegroup: kind-worker2 - kubernetes.io/os: linux - name: kind-worker2 - resourceVersion: "578" - uid: edc7df38-feb2-4089-9955-780562bdd21e - spec: - podCIDR: 10.244.1.0/24 - podCIDRs: - - 10.244.1.0/24 - providerID: kind://docker/kind/kind-worker2 - status: - addresses: - - address: 172.18.0.4 - type: InternalIP - - address: kind-worker2 - type: Hostname - allocatable: - cpu: "12" - ephemeral-storage: 959786032Ki - hugepages-1Gi: "0" - hugepages-2Mi: "0" - memory: 32781516Ki - pods: "110" - capacity: - cpu: "12" - ephemeral-storage: 959786032Ki - hugepages-1Gi: "0" - hugepages-2Mi: "0" - memory: 32781516Ki - pods: "110" - conditions: - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:39:57Z" - message: kubelet has sufficient memory available - reason: KubeletHasSufficientMemory - status: "False" - type: MemoryPressure - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:39:57Z" - message: kubelet has no disk pressure - reason: KubeletHasNoDiskPressure - status: "False" - type: DiskPressure - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:39:57Z" - message: kubelet has sufficient PID available - reason: KubeletHasSufficientPID - status: "False" - type: PIDPressure - - lastHeartbeatTime: "2023-05-31T04:40:17Z" - lastTransitionTime: "2023-05-31T04:40:08Z" - message: kubelet is posting ready status - reason: KubeletReady - status: "True" - type: Ready - daemonEndpoints: - kubeletEndpoint: - Port: 10250 - images: - - names: - - registry.k8s.io/etcd:3.5.6-0 - sizeBytes: 102542580 - - names: - - docker.io/library/import-2023-03-30@sha256:ba097b515c8c40689733c0f19de377e9bf8995964b7d7150c2045f3dfd166657 - - registry.k8s.io/kube-apiserver:v1.26.3 - sizeBytes: 80392681 - - names: - - docker.io/library/import-2023-03-30@sha256:8dbb345de79d1c44f59a7895da702a5f71997ae72aea056609445c397b0c10dc - - registry.k8s.io/kube-controller-manager:v1.26.3 - sizeBytes: 68538487 - - names: - - docker.io/library/import-2023-03-30@sha256:44db4d50a5f9c8efbac0d37ea974d1c0419a5928f90748d3d491a041a00c20b5 - - registry.k8s.io/kube-proxy:v1.26.3 - sizeBytes: 67217404 - - names: - - docker.io/library/import-2023-03-30@sha256:3dd2337f70af979c7362b5e52bbdfcb3a5fd39c78d94d02145150cd2db86ba39 - - registry.k8s.io/kube-scheduler:v1.26.3 - sizeBytes: 57761399 - - names: - - docker.io/kindest/kindnetd:v20230330-48f316cd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af - - docker.io/kindest/kindnetd@sha256:c19d6362a6a928139820761475a38c24c0cf84d507b9ddf414a078cf627497af - sizeBytes: 27726335 - - names: - - docker.io/kindest/local-path-provisioner:v0.0.23-kind.0@sha256:f2d0a02831ff3a03cf51343226670d5060623b43a4cfc4808bd0875b2c4b9501 - sizeBytes: 18664669 - - names: - - registry.k8s.io/coredns/coredns:v1.9.3 - sizeBytes: 14837849 - - names: - - docker.io/kindest/local-path-helper:v20230330-48f316cd@sha256:135203f2441f916fb13dad1561d27f60a6f11f50ec288b01a7d2ee9947c36270 - sizeBytes: 3052037 - - names: - - registry.k8s.io/pause:3.7 - sizeBytes: 311278 - nodeInfo: - architecture: amd64 - bootID: 2d71b318-5d07-4de2-9e61-2da28cf5bbf0 - containerRuntimeVersion: containerd://1.6.19-46-g941215f49 - kernelVersion: 5.15.0-72-generic - kubeProxyVersion: v1.26.3 - kubeletVersion: v1.26.3 - machineID: fa9f4cd3b3a743bc867b04e44941dcb2 - operatingSystem: linux - osImage: Ubuntu 22.04.2 LTS - systemUUID: f36c0f00-8ba5-4c8c-88bc-2981c8d377b9 - kind: List - metadata: - resourceVersion: "" - - -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/deployment.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/deployment.yaml deleted file mode 100644 index cb4982b3..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/deployment.yaml +++ /dev/null @@ -1,380 +0,0 @@ -{{- if or ( or .Values.autoDiscovery.clusterName .Values.autoDiscovery.namespace .Values.autoDiscovery.labels ) .Values.autoscalingGroups }} -{{/* one of the above is required */}} -apiVersion: {{ template "deployment.apiVersion" . }} -kind: Deployment -metadata: - annotations: -{{ toYaml .Values.deployment.annotations | indent 4 }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.fullname" . }} - namespace: {{ .Release.Namespace }} -spec: - replicas: {{ .Values.replicaCount }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} - selector: - matchLabels: -{{- if .Values.deployment.selector }} -{{ toYaml .Values.deployment.selector | indent 6 }} -{{- else }} -{{ include "cluster-autoscaler.instance-name" . | indent 6 }} - {{- if .Values.podLabels }} -{{ toYaml .Values.podLabels | indent 6 }} - {{- end }} -{{- end }} -{{- if .Values.updateStrategy }} - strategy: - {{ toYaml .Values.updateStrategy | nindent 4 | trim }} -{{- end }} - template: - metadata: - {{- if .Values.podAnnotations }} - annotations: -{{ toYaml .Values.podAnnotations | indent 8 }} - {{- end }} - labels: -{{ include "cluster-autoscaler.instance-name" . | indent 8 }} - {{- if .Values.additionalLabels }} -{{ toYaml .Values.additionalLabels | indent 8 }} - {{- end }} - {{- if .Values.podLabels }} -{{ toYaml .Values.podLabels | indent 8 }} - {{- end }} - spec: - {{- if .Values.priorityClassName }} - priorityClassName: "{{ .Values.priorityClassName }}" - {{- end }} - {{- with .Values.dnsConfig }} - dnsConfig: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- if .Values.dnsPolicy }} - dnsPolicy: "{{ .Values.dnsPolicy }}" - {{- end }} - {{- if .Values.hostNetwork }} - hostNetwork: {{ .Values.hostNetwork }} - {{- end }} - {{- with .Values.initContainers }} - initContainers: - {{- toYaml . | nindent 8 }} - {{- end }} - containers: - - name: {{ template "cluster-autoscaler.name" . }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: "{{ .Values.image.pullPolicy }}" - command: - - ./cluster-autoscaler - - --cloud-provider={{ .Values.cloudProvider }} - {{- if and (eq .Values.cloudProvider "clusterapi") (eq .Values.clusterAPIMode "kubeconfig-incluster") }} - - --namespace={{ .Values.clusterAPIConfigMapsNamespace | default "kube-system" }} - {{- else }} - - --namespace={{ .Release.Namespace }} - {{- end }} - {{- if .Values.autoscalingGroups }} - {{- range .Values.autoscalingGroups }} - {{- if eq $.Values.cloudProvider "hetzner" }} - - --nodes={{ .minSize }}:{{ .maxSize }}:{{ .instanceType }}:{{ .region }}:{{ .name }} - {{- else }} - - --nodes={{ .minSize }}:{{ .maxSize }}:{{ .name }} - {{- end }} - {{- end }} - {{- end }} - {{- if eq .Values.cloudProvider "rancher" }} - {{- if .Values.cloudConfigPath }} - - --cloud-config={{ .Values.cloudConfigPath }} - {{- end }} - {{- end }} - {{- if eq .Values.cloudProvider "aws" }} - {{- if .Values.autoDiscovery.clusterName }} - - --node-group-auto-discovery=asg:tag={{ tpl (join "," .Values.autoDiscovery.tags) . }} - {{- end }} - {{- if .Values.cloudConfigPath }} - - --cloud-config={{ .Values.cloudConfigPath }} - {{- end }} - {{- else if eq .Values.cloudProvider "gce" }} - {{- if .Values.autoscalingGroupsnamePrefix }} - {{- range .Values.autoscalingGroupsnamePrefix }} - - --node-group-auto-discovery=mig:namePrefix={{ tpl .name $ }},min={{ .minSize }},max={{ .maxSize }} - {{- end }} - {{- end }} - {{- if eq .Values.cloudProvider "oci" }} - {{- if .Values.cloudConfigPath }} - - --nodes={{ .minSize }}:{{ .maxSize }}:{{ .name }} - - --balance-similar-node-groups - {{- end }} - {{- end }} - {{- else if eq .Values.cloudProvider "magnum" }} - {{- if .Values.autoDiscovery.clusterName }} - - --cluster-name={{ tpl (.Values.autoDiscovery.clusterName) . }} - - --node-group-auto-discovery=magnum:role={{ tpl (join "," .Values.autoDiscovery.roles) . }} - {{- else }} - - --cluster-name={{ tpl (.Values.magnumClusterName) . }} - {{- end }} - {{- else if eq .Values.cloudProvider "clusterapi" }} - {{- if or .Values.autoDiscovery.clusterName .Values.autoDiscovery.labels .Values.autoDiscovery.namespace }} - - --node-group-auto-discovery=clusterapi:{{ template "cluster-autoscaler.capiAutodiscoveryConfig" . }} - {{- end }} - {{- if eq .Values.clusterAPIMode "incluster-kubeconfig"}} - - --cloud-config={{ .Values.clusterAPICloudConfigPath }} - {{- else if eq .Values.clusterAPIMode "kubeconfig-incluster"}} - - --kubeconfig={{ .Values.clusterAPIWorkloadKubeconfigPath }} - - --clusterapi-cloud-config-authoritative - {{- else if eq .Values.clusterAPIMode "kubeconfig-kubeconfig"}} - - --kubeconfig={{ .Values.clusterAPIWorkloadKubeconfigPath }} - - --cloud-config={{ .Values.clusterAPICloudConfigPath }} - {{- else if eq .Values.clusterAPIMode "single-kubeconfig"}} - - --kubeconfig={{ .Values.clusterAPIWorkloadKubeconfigPath }} - {{- end }} - {{- else if eq .Values.cloudProvider "azure" }} - {{- if .Values.autoDiscovery.clusterName }} - - --node-group-auto-discovery=label:cluster-autoscaler-enabled=true,cluster-autoscaler-name={{ tpl (.Values.autoDiscovery.clusterName) . }} - {{- end }} - {{- end }} - {{- if eq .Values.cloudProvider "magnum" }} - - --cloud-config={{ .Values.cloudConfigPath }} - {{- end }} - {{- range $key, $value := .Values.extraArgs }} - {{- if not (kindIs "invalid" $value) }} - - --{{ $key | mustRegexFind "^[^_]+" }}={{ $value }} - {{- else }} - - --{{ $key | mustRegexFind "^[^_]+" }} - {{- end }} - {{- end }} - {{- range .Values.customArgs }} - - {{ . }} - {{- end }} - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - {{- if and (eq .Values.cloudProvider "aws") (ne (tpl .Values.awsRegion $) "") }} - - name: AWS_REGION - value: "{{ tpl .Values.awsRegion $ }}" - {{- if .Values.awsAccessKeyID }} - - name: AWS_ACCESS_KEY_ID - valueFrom: - secretKeyRef: - key: AwsAccessKeyId - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - {{- end }} - {{- if .Values.awsSecretAccessKey }} - - name: AWS_SECRET_ACCESS_KEY - valueFrom: - secretKeyRef: - key: AwsSecretAccessKey - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - {{- end }} - {{- else if eq .Values.cloudProvider "azure" }} - - name: ARM_SUBSCRIPTION_ID - valueFrom: - secretKeyRef: - key: SubscriptionID - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: ARM_RESOURCE_GROUP - valueFrom: - secretKeyRef: - key: ResourceGroup - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: ARM_VM_TYPE - valueFrom: - secretKeyRef: - key: VMType - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: AZURE_ENABLE_FORCE_DELETE - value: "{{ .Values.azureEnableForceDelete }}" - {{- if .Values.azureUseWorkloadIdentityExtension }} - - name: ARM_USE_WORKLOAD_IDENTITY_EXTENSION - value: "true" - {{- else if .Values.azureUseManagedIdentityExtension }} - - name: ARM_USE_MANAGED_IDENTITY_EXTENSION - value: "true" - - name: ARM_USER_ASSIGNED_IDENTITY_ID - valueFrom: - secretKeyRef: - key: UserAssignedIdentityID - name: {{ template "cluster-autoscaler.fullname" . }} - {{- else }} - - name: ARM_TENANT_ID - valueFrom: - secretKeyRef: - key: TenantID - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: ARM_CLIENT_ID - valueFrom: - secretKeyRef: - key: ClientID - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: ARM_CLIENT_SECRET - valueFrom: - secretKeyRef: - key: ClientSecret - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - {{- end }} - {{- else if eq .Values.cloudProvider "exoscale" }} - - name: EXOSCALE_API_KEY - valueFrom: - secretKeyRef: - key: api-key - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: EXOSCALE_API_SECRET - valueFrom: - secretKeyRef: - key: api-secret - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: EXOSCALE_ZONE - valueFrom: - secretKeyRef: - key: api-zone - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - {{- else if eq .Values.cloudProvider "kwok" }} - - name: KWOK_PROVIDER_CONFIGMAP - value: "{{.Values.kwokConfigMapName | default "kwok-provider-config"}}" - {{- else if eq .Values.cloudProvider "civo" }} - - name: CIVO_API_URL - valueFrom: - secretKeyRef: - key: api-url - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: CIVO_API_KEY - valueFrom: - secretKeyRef: - key: api-key - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: CIVO_CLUSTER_ID - valueFrom: - secretKeyRef: - key: cluster-id - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - - name: CIVO_REGION - valueFrom: - secretKeyRef: - key: region - name: {{ default (include "cluster-autoscaler.fullname" .) .Values.secretKeyRefNameOverride }} - {{- end }} - {{- range $key, $value := .Values.extraEnv }} - - name: {{ $key }} - value: "{{ $value }}" - {{- end }} - {{- range $key, $value := .Values.extraEnvConfigMaps }} - - name: {{ $key }} - valueFrom: - configMapKeyRef: - name: {{ default (include "cluster-autoscaler.fullname" $) $value.name }} - key: {{ required "Must specify key!" $value.key }} - {{- end }} - {{- range $key, $value := .Values.extraEnvSecrets }} - - name: {{ $key }} - valueFrom: - secretKeyRef: - name: {{ default (include "cluster-autoscaler.fullname" $) $value.name }} - key: {{ required "Must specify key!" $value.key }} - {{- end }} - {{- if or .Values.envFromSecret .Values.envFromConfigMap }} - envFrom: - {{- if .Values.envFromSecret }} - - secretRef: - name: {{ .Values.envFromSecret }} - {{- end }} - {{- if .Values.envFromConfigMap }} - - configMapRef: - name: {{ .Values.envFromConfigMap }} - {{- end }} - {{- end }} - livenessProbe: - httpGet: - path: /health-check - port: 8085 - ports: - - containerPort: 8085 - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- if .Values.containerSecurityContext }} - securityContext: - {{ toYaml .Values.containerSecurityContext | nindent 12 | trim }} - {{- end }} - {{- if or (eq .Values.cloudProvider "magnum") .Values.extraVolumeSecrets .Values.extraVolumeMounts .Values.clusterAPIKubeconfigSecret }} - volumeMounts: - {{- if eq .Values.cloudProvider "magnum" }} - - name: cloudconfig - mountPath: {{ .Values.cloudConfigPath }} - readOnly: true - {{- end }} - {{- if and (eq .Values.cloudProvider "magnum") (.Values.magnumCABundlePath) }} - - name: ca-bundle - mountPath: {{ .Values.magnumCABundlePath }} - readOnly: true - {{- end }} - {{- range $key, $value := .Values.extraVolumeSecrets }} - - name: {{ $key }} - mountPath: {{ required "Must specify mountPath!" $value.mountPath }} - readOnly: true - {{- end }} - {{- if .Values.clusterAPIKubeconfigSecret }} - - name: cluster-api-kubeconfig - mountPath: {{ .Values.clusterAPIWorkloadKubeconfigPath | trimSuffix "/value" }} - {{- end }} - {{- if .Values.extraVolumeMounts }} - {{- toYaml .Values.extraVolumeMounts | nindent 12 }} - {{- end }} - {{- end }} - {{- if .Values.affinity }} - affinity: -{{ toYaml .Values.affinity | indent 8 }} - {{- end }} - {{- if .Values.nodeSelector }} - nodeSelector: -{{ toYaml .Values.nodeSelector | indent 8 }} - {{- end }} - serviceAccountName: {{ template "cluster-autoscaler.serviceAccountName" . }} - tolerations: -{{ toYaml .Values.tolerations | indent 8 }} - {{- if .Values.topologySpreadConstraints }} - topologySpreadConstraints: -{{ toYaml .Values.topologySpreadConstraints | indent 8 }} - {{- end }} - {{- if .Values.securityContext }} - securityContext: - {{ toYaml .Values.securityContext | nindent 8 | trim }} - {{- end }} - {{- if or (eq .Values.cloudProvider "magnum") .Values.extraVolumeSecrets .Values.extraVolumes .Values.clusterAPIKubeconfigSecret }} - volumes: - {{- if eq .Values.cloudProvider "magnum" }} - - name: cloudconfig - hostPath: - path: {{ .Values.cloudConfigPath }} - {{- end }} - {{- if and (eq .Values.cloudProvider "magnum") (.Values.magnumCABundlePath) }} - - name: ca-bundle - hostPath: - path: {{ .Values.magnumCABundlePath }} - {{- end }} - {{- range $key, $value := .Values.extraVolumeSecrets }} - - name: {{ $key }} - secret: - secretName: {{ default (include "cluster-autoscaler.fullname" $) $value.name }} - {{- if $value.items }} - items: - {{- toYaml $value.items | nindent 14 }} - {{- end }} - {{- end }} - {{- if .Values.extraVolumes }} - {{- toYaml .Values.extraVolumes | nindent 8 }} - {{- end }} - {{- if .Values.clusterAPIKubeconfigSecret }} - - name: cluster-api-kubeconfig - secret: - secretName: {{ .Values.clusterAPIKubeconfigSecret }} - {{- end }} - {{- end }} - {{- if .Values.image.pullSecrets }} - imagePullSecrets: - {{- range .Values.image.pullSecrets }} - - name: {{ . }} - {{- end }} - {{- end }} -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/extra-manifests.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/extra-manifests.yaml deleted file mode 100644 index a9bb3b6b..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/extra-manifests.yaml +++ /dev/null @@ -1,4 +0,0 @@ -{{ range .Values.extraObjects }} ---- -{{ tpl (toYaml .) $ }} -{{ end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/pdb.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/pdb.yaml deleted file mode 100644 index 0f8a69ec..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/pdb.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if .Values.podDisruptionBudget -}} -{{- if and .Values.podDisruptionBudget.minAvailable .Values.podDisruptionBudget.maxUnavailable }} - {{- fail "Only one of podDisruptionBudget.minAvailable or podDisruptionBudget.maxUnavailable should be set." }} -{{- end }}apiVersion: {{ template "podDisruptionBudget.apiVersion" . }} -kind: PodDisruptionBudget -metadata: -{{- if .Values.podDisruptionBudget.annotations }} - annotations: -{{ toYaml .Values.podDisruptionBudget.annotations | indent 4 }} -{{- end }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.fullname" . }} - namespace: {{ .Release.Namespace }} -spec: - selector: - matchLabels: -{{- if .Values.podDisruptionBudget.selector }} -{{ toYaml .Values.podDisruptionBudget.selector | indent 6 }} -{{- else }} -{{ include "cluster-autoscaler.instance-name" . | indent 6 }} - {{- if and .Values.podDisruptionBudget.minAvailable (not .Values.podDisruptionBudget.maxUnavailable) }} - minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} - {{- end }} - {{- if and .Values.podDisruptionBudget.maxUnavailable (not .Values.podDisruptionBudget.minAvailable) }} - maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} - {{- end }} -{{- end -}} -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/podsecuritypolicy.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/podsecuritypolicy.yaml deleted file mode 100644 index e3ce5997..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/podsecuritypolicy.yaml +++ /dev/null @@ -1,42 +0,0 @@ -{{- if .Values.rbac.pspEnabled }} -apiVersion: {{ template "podsecuritypolicy.apiVersion" . }} -kind: PodSecurityPolicy -metadata: - name: {{ template "cluster-autoscaler.fullname" . }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} -spec: - # Prevents running in privileged mode - privileged: false - # Required to prevent escalations to root. - allowPrivilegeEscalation: false - requiredDropCapabilities: - - ALL - volumes: - - 'configMap' - - 'secret' - - 'hostPath' - - 'emptyDir' - - 'projected' - - 'downwardAPI' - hostNetwork: {{ .Values.hostNetwork }} - hostIPC: false - hostPID: false - runAsUser: - rule: RunAsAny - seLinux: - rule: RunAsAny - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/priority-expander-configmap.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/priority-expander-configmap.yaml deleted file mode 100644 index 8259f14f..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/priority-expander-configmap.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if hasKey .Values.extraArgs "expander" }} -{{- if and (.Values.expanderPriorities) (include "cluster-autoscaler.priorityExpanderEnabled" .) -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: cluster-autoscaler-priority-expander - namespace: {{ .Release.Namespace }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - {{- if .Values.priorityConfigMapAnnotations }} - annotations: -{{ toYaml .Values.priorityConfigMapAnnotations | indent 4 }} - {{- end }} -data: - priorities: |- -{{- if kindIs "string" .Values.expanderPriorities }} -{{ .Values.expanderPriorities | indent 4 }} -{{- else }} -{{- range $k,$v := .Values.expanderPriorities }} - {{ $k | int }}: - {{- toYaml $v | nindent 6 }} -{{- end -}} -{{- end -}} -{{- end -}} -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/prometheusrule.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/prometheusrule.yaml deleted file mode 100644 index 097c969e..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/prometheusrule.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.prometheusRule.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ include "cluster-autoscaler.fullname" . }} - {{- if .Values.prometheusRule.namespace }} - namespace: {{ .Values.prometheusRule.namespace }} - {{- end }} - labels: {{- toYaml .Values.prometheusRule.additionalLabels | nindent 4 }} -spec: - groups: - - name: {{ include "cluster-autoscaler.fullname" . }} - interval: {{ .Values.prometheusRule.interval }} - rules: {{- tpl (toYaml .Values.prometheusRule.rules) . | nindent 8 }} -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/role.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/role.yaml deleted file mode 100644 index 80cf30a1..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/role.yaml +++ /dev/null @@ -1,96 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: -{{- with .Values.rbac.annotations }} - annotations: - {{- range $k, $v := . }} - {{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }} - {{- end }} -{{- end }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.fullname" . }} - namespace: {{ .Release.Namespace }} -rules: - - apiGroups: - - "" - resources: - - configmaps - verbs: - - create -{{- if (include "cluster-autoscaler.priorityExpanderEnabled" .) }} - - list - - watch -{{- end }} - - apiGroups: - - "" - resources: - - configmaps - resourceNames: - - cluster-autoscaler-status -{{- if (include "cluster-autoscaler.priorityExpanderEnabled" .) }} - - cluster-autoscaler-priority-expander -{{- end }} - verbs: - - delete - - get - - update -{{- if (include "cluster-autoscaler.priorityExpanderEnabled" .) }} - - watch -{{- end }} -{{- if eq (default "" (index .Values.extraArgs "leader-elect-resource-lock")) "configmaps" }} - - apiGroups: - - "" - resources: - - configmaps - resourceNames: - - cluster-autoscaler - verbs: - - get - - update -{{- end }} -{{- if and ( and ( eq .Values.cloudProvider "clusterapi" ) ( not .Values.rbac.clusterScoped ) ( or ( eq .Values.clusterAPIMode "incluster-incluster" ) ( eq .Values.clusterAPIMode "kubeconfig-incluster" ) ))}} - - apiGroups: - - cluster.x-k8s.io - resources: - - machinedeployments - - machinepools - - machines - - machinesets - verbs: - - get - - list - - update - - watch - - apiGroups: - - cluster.x-k8s.io - resources: - - machinedeployments/scale - - machinepools/scale - verbs: - - get - - patch - - update -{{- end }} -{{- if ( not .Values.rbac.clusterScoped ) }} - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - apiGroups: - - coordination.k8s.io - resourceNames: - - cluster-autoscaler - resources: - - leases - verbs: - - get - - update -{{- end }} -{{- if .Values.rbac.additionalRules }} -{{ toYaml .Values.rbac.additionalRules | indent 2}} -{{- end }} -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/rolebinding.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/rolebinding.yaml deleted file mode 100644 index 9436aabe..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/rolebinding.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if .Values.rbac.create -}} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: -{{- with .Values.rbac.annotations }} - annotations: - {{- range $k, $v := . }} - {{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }} - {{- end }} -{{- end }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.fullname" . }} - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ template "cluster-autoscaler.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "cluster-autoscaler.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/secret.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/secret.yaml deleted file mode 100644 index 760cc3c5..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/secret.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if not .Values.secretKeyRefNameOverride }} -{{- $isAzure := eq .Values.cloudProvider "azure" }} -{{- $isAws := eq .Values.cloudProvider "aws" }} -{{- $awsCredentialsProvided := and .Values.awsAccessKeyID .Values.awsSecretAccessKey }} -{{- $isCivo := eq .Values.cloudProvider "civo" }} - -{{- if or $isAzure (and $isAws $awsCredentialsProvided) $isCivo }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "cluster-autoscaler.fullname" . }} - namespace: {{ .Release.Namespace }} -data: -{{- if $isAzure }} - ClientID: "{{ .Values.azureClientID | b64enc }}" - ClientSecret: "{{ .Values.azureClientSecret | b64enc }}" - ResourceGroup: "{{ .Values.azureResourceGroup | b64enc }}" - SubscriptionID: "{{ .Values.azureSubscriptionID | b64enc }}" - TenantID: "{{ .Values.azureTenantID | b64enc }}" - VMType: "{{ .Values.azureVMType | b64enc }}" - UserAssignedIdentityID: "{{ .Values.azureUserAssignedIdentityID | b64enc }}" -{{- else if $isAws }} - AwsAccessKeyId: "{{ .Values.awsAccessKeyID | b64enc }}" - AwsSecretAccessKey: "{{ .Values.awsSecretAccessKey | b64enc }}" -{{- else if $isCivo }} - api-url: "{{ .Values.civoApiUrl | b64enc }}" - api-key: "{{ .Values.civoApiKey | b64enc }}" - cluster-id: "{{ .Values.civoClusterID | b64enc }}" - region: "{{ .Values.civoRegion | b64enc }}" -{{- end }} -{{- end }} -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/service.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/service.yaml deleted file mode 100644 index c8bd4079..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/service.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.service.create }} -apiVersion: v1 -kind: Service -metadata: -{{- if .Values.service.annotations }} - annotations: -{{ toYaml .Values.service.annotations | indent 4 }} -{{- end }} - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} -{{- if .Values.service.labels }} -{{ toYaml .Values.service.labels | indent 4 }} -{{- end }} - name: {{ template "cluster-autoscaler.fullname" . }} - namespace: {{ .Release.Namespace }} -spec: -{{- if .Values.service.clusterIP }} - clusterIP: "{{ .Values.service.clusterIP }}" -{{- end }} -{{- if .Values.service.externalIPs }} - externalIPs: -{{ toYaml .Values.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.service.loadBalancerIP }} - loadBalancerIP: "{{ .Values.service.loadBalancerIP }}" -{{- end }} -{{- if .Values.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: -{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} -{{- end }} - ports: - - port: {{ .Values.service.servicePort }} - protocol: TCP - targetPort: 8085 - name: {{ .Values.service.portName }} - selector: -{{- if .Values.service.selector }} -{{ toYaml .Values.service.selector | indent 4 }} -{{- else }} -{{ include "cluster-autoscaler.instance-name" . | indent 4 }} -{{- end }} - type: "{{ .Values.service.type }}" -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/serviceaccount.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/serviceaccount.yaml deleted file mode 100644 index 465b5aad..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/serviceaccount.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and .Values.rbac.create .Values.rbac.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.serviceAccountName" . }} - namespace: {{ .Release.Namespace }} - -{{- with .Values.rbac.serviceAccount.annotations }} - annotations: - {{- range $k, $v := . }} - {{- printf "%s: %s" (tpl $k $) (tpl $v $) | nindent 4 }} - {{- end }} -{{- end }} -automountServiceAccountToken: {{ .Values.rbac.serviceAccount.automountServiceAccountToken }} -{{- end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/servicemonitor.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/servicemonitor.yaml deleted file mode 100644 index 9ce83a2e..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/servicemonitor.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{ if .Values.serviceMonitor.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "cluster-autoscaler.fullname" . }} - {{- if .Values.serviceMonitor.namespace }} - namespace: {{ .Values.serviceMonitor.namespace }} - {{- end }} - {{- if .Values.serviceMonitor.annotations }} - annotations: -{{ toYaml .Values.serviceMonitor.annotations | indent 4 }} - {{- end }} - labels: - {{- range $key, $value := .Values.serviceMonitor.selector }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - selector: - matchLabels: -{{ include "cluster-autoscaler.instance-name" . | indent 6 }} - endpoints: - - port: {{ .Values.service.portName }} - interval: {{ .Values.serviceMonitor.interval }} - path: {{ .Values.serviceMonitor.path }} - {{- if .Values.serviceMonitor.relabelings }} - relabelings: -{{ tpl (toYaml .Values.serviceMonitor.relabelings | indent 6) . }} - {{- end }} - {{- if .Values.serviceMonitor.metricRelabelings }} - metricRelabelings: -{{ tpl (toYaml .Values.serviceMonitor.metricRelabelings | indent 6) . }} - {{- end }} - namespaceSelector: - matchNames: - - {{.Release.Namespace}} -{{ end }} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/vpa.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/vpa.yaml deleted file mode 100644 index 560dab00..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/templates/vpa.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.vpa.enabled -}} -apiVersion: autoscaling.k8s.io/v1 -kind: VerticalPodAutoscaler -metadata: - labels: -{{ include "cluster-autoscaler.labels" . | indent 4 }} - name: {{ template "cluster-autoscaler.fullname" . }} - namespace: {{ .Release.Namespace }} -spec: - targetRef: - apiVersion: {{ template "deployment.apiVersion" . }} - kind: Deployment - name: {{ template "cluster-autoscaler.fullname" . }} - updatePolicy: - updateMode: {{ .Values.vpa.updateMode | quote }} - recommenders: - - name: {{ .Values.vpa.recommender | quote }} - resourcePolicy: - containerPolicies: - - containerName: {{ template "cluster-autoscaler.name" . }} - {{- .Values.vpa.containerPolicy | toYaml | nindent 6 }} -{{- end -}} diff --git a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/values.yaml b/packages/system/cluster-autoscaler/charts/cluster-autoscaler/values.yaml deleted file mode 100644 index 9e41d35b..00000000 --- a/packages/system/cluster-autoscaler/charts/cluster-autoscaler/values.yaml +++ /dev/null @@ -1,507 +0,0 @@ -## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -# affinity -- Affinity for pod assignment -affinity: {} - -# additionalLabels -- Labels to add to each object of the chart. -additionalLabels: {} - -autoDiscovery: - # cloudProviders `aws`, `gce`, `azure`, `magnum`, `clusterapi` and `oci` are supported by auto-discovery at this time - # AWS: Set tags as described in https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup - - # autoDiscovery.clusterName -- Enable autodiscovery for `cloudProvider=aws`, for groups matching `autoDiscovery.tags`. - # autoDiscovery.clusterName -- Enable autodiscovery for `cloudProvider=azure`, using tags defined in https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/azure/README.md#auto-discovery-setup. - # Enable autodiscovery for `cloudProvider=clusterapi`, for groups matching `autoDiscovery.labels`. - # Enable autodiscovery for `cloudProvider=gce`, but no MIG tagging required. - # Enable autodiscovery for `cloudProvider=magnum`, for groups matching `autoDiscovery.roles`. - clusterName: # cluster.local - - # autoDiscovery.namespace -- Enable autodiscovery via cluster namespace for for `cloudProvider=clusterapi` - namespace: # default - - # autoDiscovery.tags -- ASG tags to match, run through `tpl`. - tags: - - k8s.io/cluster-autoscaler/enabled - - k8s.io/cluster-autoscaler/{{ .Values.autoDiscovery.clusterName }} - # - kubernetes.io/cluster/{{ .Values.autoDiscovery.clusterName }} - - # autoDiscovery.roles -- Magnum node group roles to match. - roles: - - worker - - # autoDiscovery.labels -- Cluster-API labels to match https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#configuring-node-group-auto-discovery - labels: [] - # - color: green - # - shape: circle -# autoscalingGroups -- For AWS, Azure AKS, Exoscale or Magnum. At least one element is required if not using `autoDiscovery`. For example: -#
-# - name: asg1
-# maxSize: 2
-# minSize: 1 -#
-# For Hetzner Cloud, the `instanceType` and `region` keys are also required. -#
-# - name: mypool
-# maxSize: 2
-# minSize: 1
-# instanceType: CPX21
-# region: FSN1 -#
-autoscalingGroups: [] -# - name: asg1 -# maxSize: 2 -# minSize: 1 -# - name: asg2 -# maxSize: 2 -# minSize: 1 - -# autoscalingGroupsnamePrefix -- For GCE. At least one element is required if not using `autoDiscovery`. For example: -#
-# - name: ig01
-# maxSize: 10
-# minSize: 0 -#
-autoscalingGroupsnamePrefix: [] -# - name: ig01 -# maxSize: 10 -# minSize: 0 -# - name: ig02 -# maxSize: 10 -# minSize: 0 - -# awsAccessKeyID -- AWS access key ID ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) -awsAccessKeyID: "" - -# awsRegion -- AWS region (required if `cloudProvider=aws`) -awsRegion: "" - -# awsSecretAccessKey -- AWS access secret key ([if AWS user keys used](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#using-aws-credentials)) -awsSecretAccessKey: "" - -# azureClientID -- Service Principal ClientID with contributor permission to Cluster and Node ResourceGroup. -# Required if `cloudProvider=azure` -azureClientID: "" - -# azureClientSecret -- Service Principal ClientSecret with contributor permission to Cluster and Node ResourceGroup. -# Required if `cloudProvider=azure` -azureClientSecret: "" - -# azureResourceGroup -- Azure resource group that the cluster is located. -# Required if `cloudProvider=azure` -azureResourceGroup: "" - -# azureSubscriptionID -- Azure subscription where the resources are located. -# Required if `cloudProvider=azure` -azureSubscriptionID: "" - -# azureTenantID -- Azure tenant where the resources are located. -# Required if `cloudProvider=azure` -azureTenantID: "" - -# azureUseManagedIdentityExtension -- Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID, resource group, and azure AKS cluster name are set. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. -azureUseManagedIdentityExtension: false - -# azureUserAssignedIdentityID -- When vmss has multiple user assigned identity assigned, azureUserAssignedIdentityID specifies which identity to be used -azureUserAssignedIdentityID: "" - -# azureUseWorkloadIdentityExtension -- Whether to use Azure's workload identity extension for credentials. See the project here: https://github.com/Azure/azure-workload-identity for more details. You can only use one authentication method at a time, either azureUseWorkloadIdentityExtension or azureUseManagedIdentityExtension should be set. -azureUseWorkloadIdentityExtension: false - -# azureVMType -- Azure VM type. -azureVMType: "vmss" - -# azureEnableForceDelete -- Whether to force delete VMs or VMSS instances when scaling down. -azureEnableForceDelete: false - -# civoApiUrl -- URL for the Civo API. -# Required if `cloudProvider=civo` -civoApiUrl: "https://api.civo.com" - -# civoApiKey -- API key for the Civo API. -# Required if `cloudProvider=civo` -civoApiKey: "" - -# civoClusterID -- Cluster ID for the Civo cluster. -# Required if `cloudProvider=civo` -civoClusterID: "" - -# civoRegion -- Region for the Civo cluster. -# Required if `cloudProvider=civo` -civoRegion: "" - -# cloudConfigPath -- Configuration file for cloud provider. -cloudConfigPath: "" - -# cloudProvider -- The cloud provider where the autoscaler runs. -# Currently only `gce`, `aws`, `azure`, `magnum`, `clusterapi`, `civo` and `coreweave` are supported. -# `aws` supported for AWS. `gce` for GCE. `azure` for Azure AKS. -# `magnum` for OpenStack Magnum, `clusterapi` for Cluster API. -# `civo` for Civo Cloud. -# `coreweave` for CoreWeave. -cloudProvider: aws - -# clusterAPICloudConfigPath -- Path to kubeconfig for connecting to Cluster API Management Cluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or incluster-kubeconfig` -clusterAPICloudConfigPath: /etc/kubernetes/mgmt-kubeconfig - -# clusterAPIConfigMapsNamespace -- Namespace on the workload cluster to store Leader election and status configmaps -clusterAPIConfigMapsNamespace: "" - -# clusterAPIKubeconfigSecret -- Secret containing kubeconfig for connecting to Cluster API managed workloadcluster -# Required if `cloudProvider=clusterapi` and `clusterAPIMode=kubeconfig-kubeconfig,kubeconfig-incluster or incluster-kubeconfig` -clusterAPIKubeconfigSecret: "" - -# clusterAPIMode -- Cluster API mode, see https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md#connecting-cluster-autoscaler-to-cluster-api-management-and-workload-clusters -# Syntax: workloadClusterMode-ManagementClusterMode -# for `kubeconfig-kubeconfig`, `incluster-kubeconfig` and `single-kubeconfig` you always must mount the external kubeconfig using either `extraVolumeSecrets` or `extraMounts` and `extraVolumes` -# if you dont set `clusterAPIKubeconfigSecret`and thus use an in-cluster config or want to use a non capi generated kubeconfig you must do so for the workload kubeconfig as well -clusterAPIMode: incluster-incluster # incluster-incluster, incluster-kubeconfig, kubeconfig-incluster, kubeconfig-kubeconfig, single-kubeconfig - -# clusterAPIWorkloadKubeconfigPath -- Path to kubeconfig for connecting to Cluster API managed workloadcluster, only used if `clusterAPIMode=kubeconfig-kubeconfig or kubeconfig-incluster` -clusterAPIWorkloadKubeconfigPath: /etc/kubernetes/value - -# containerSecurityContext -- [Security context for container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) -containerSecurityContext: {} - # allowPrivilegeEscalation: false - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - -deployment: - # deployment.annotations -- Annotations to add to the Deployment object. - annotations: {} - # deployment.selector -- Labels for Deployment `spec.selector.matchLabels`. - selector: {} - -# dnsConfig -- [Pod's DNS Config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config) -dnsConfig: {} - # nameservers: - # - 1.2.3.4 - # searches: - # - ns1.svc.cluster-domain.example - # - my.dns.search.suffix - # options: - # - name: ndots - # value: "2" - # - name: edns0 - -# dnsPolicy -- Defaults to `ClusterFirst`. Valid values are: -# `ClusterFirstWithHostNet`, `ClusterFirst`, `Default` or `None`. -# If autoscaler does not depend on cluster DNS, recommended to set this to `Default`. -dnsPolicy: ClusterFirst - -# envFromConfigMap -- ConfigMap name to use as envFrom. -envFromConfigMap: "" - -# envFromSecret -- Secret name to use as envFrom. -envFromSecret: "" - -## Priorities Expander -# expanderPriorities -- The expanderPriorities is used if `extraArgs.expander` contains `priority` and expanderPriorities is also set with the priorities. -# If `extraArgs.expander` contains `priority`, then expanderPriorities is used to define cluster-autoscaler-priority-expander priorities. -# See: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/expander/priority/readme.md -expanderPriorities: {} - -# extraArgs -- Additional container arguments. -# Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler -# parameters and their default values. -# Everything after the first _ will be ignored allowing the use of multi-string arguments. -extraArgs: - logtostderr: true - stderrthreshold: info - v: 4 - # write-status-configmap: true - # status-config-map-name: cluster-autoscaler-status - # leader-elect: true - # leader-elect-resource-lock: endpoints - # skip-nodes-with-local-storage: true - # expander: random - # scale-down-enabled: true - # balance-similar-node-groups: true - # min-replica-count: 0 - # scale-down-utilization-threshold: 0.5 - # scale-down-non-empty-candidates-count: 30 - # max-node-provision-time: 15m0s - # scan-interval: 10s - # scale-down-delay-after-add: 10m - # scale-down-delay-after-delete: 0s - # scale-down-delay-after-failure: 3m - # scale-down-unneeded-time: 10m - # node-deletion-delay-timeout: 2m - # node-deletion-batcher-interval: 0s - # skip-nodes-with-system-pods: true - # balancing-ignore-label_1: first-label-to-ignore - # balancing-ignore-label_2: second-label-to-ignore - -# customArgs -- Additional custom container arguments. -# Refer to https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca for the full list of cluster autoscaler -# parameters and their default values. -# List of arguments as strings. -customArgs: [] - -# extraEnv -- Additional container environment variables. -extraEnv: {} - -# extraEnvConfigMaps -- Additional container environment variables from ConfigMaps. -extraEnvConfigMaps: {} - -# extraEnvSecrets -- Additional container environment variables from Secrets. -extraEnvSecrets: {} - -# extraObjects -- Extra K8s manifests to deploy -extraObjects: [] -# - apiVersion: v1 -# kind: ConfigMap -# metadata: -# name: my-configmap -# data: -# key: "value" -# - apiVersion: scheduling.k8s.io/v1 -# kind: PriorityClass -# metadata: -# name: high-priority -# value: 1000000 -# globalDefault: false -# description: "This priority class should be used for XYZ service pods only." - -# extraVolumeMounts -- Additional volumes to mount. -extraVolumeMounts: [] - # - name: ssl-certs - # mountPath: /etc/ssl/certs/ca-certificates.crt - # readOnly: true - -# extraVolumes -- Additional volumes. -extraVolumes: [] - # - name: ssl-certs - # hostPath: - # path: /etc/ssl/certs/ca-bundle.crt - -# extraVolumeSecrets -- Additional volumes to mount from Secrets. -extraVolumeSecrets: {} - # autoscaler-vol: - # mountPath: /data/autoscaler/ - # custom-vol: - # name: custom-secret - # mountPath: /data/custom/ - # items: - # - key: subkey - # path: mypath - -# initContainers -- Any additional init containers. -initContainers: [] - -# fullnameOverride -- String to fully override `cluster-autoscaler.fullname` template. -fullnameOverride: "" - -# hostNetwork -- Whether to expose network interfaces of the host machine to pods. -hostNetwork: false - -image: - # image.repository -- Image repository - repository: registry.k8s.io/autoscaling/cluster-autoscaler - # image.tag -- Image tag - tag: v1.34.2 - # image.pullPolicy -- Image pull policy - pullPolicy: IfNotPresent - ## Optionally specify an array of imagePullSecrets. - ## Secrets must be manually created in the namespace. - ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - ## - # image.pullSecrets -- Image pull secrets - pullSecrets: [] - # - myRegistrKeySecretName - -# kubeTargetVersionOverride -- Allow overriding the `.Capabilities.KubeVersion.GitVersion` check. Useful for `helm template` commands. -kubeTargetVersionOverride: "" - -# kwokConfigMapName -- configmap for configuring kwok provider -kwokConfigMapName: "kwok-provider-config" - -# magnumCABundlePath -- Path to the host's CA bundle, from `ca-file` in the cloud-config file. -magnumCABundlePath: "/etc/kubernetes/ca-bundle.crt" - -# magnumClusterName -- Cluster name or ID in Magnum. -# Required if `cloudProvider=magnum` and not setting `autoDiscovery.clusterName`. -magnumClusterName: "" - -# nameOverride -- String to partially override `cluster-autoscaler.fullname` template (will maintain the release name) -nameOverride: "" - -# nodeSelector -- Node labels for pod assignment. Ref: https://kubernetes.io/docs/user-guide/node-selection/. -nodeSelector: {} - -# podAnnotations -- Annotations to add to each pod. -podAnnotations: {} - -# podDisruptionBudget -- Pod disruption budget. -podDisruptionBudget: - # podDisruptionBudget.annotations -- Annotations to add to the PodDisruptionBudget. - annotations: {} - # podDisruptionBudget.selector -- Override labels for PodDisruptionBudget `spec.selector.matchLabels`. - selector: {} - maxUnavailable: 1 - # minAvailable: 2 - -# podLabels -- Labels to add to each pod. -podLabels: {} - -# priorityClassName -- priorityClassName -priorityClassName: "system-cluster-critical" - -# priorityConfigMapAnnotations -- Annotations to add to `cluster-autoscaler-priority-expander` ConfigMap. -priorityConfigMapAnnotations: {} - # key1: "value1" - # key2: "value2" - -## Custom PrometheusRule to be defined -## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart -## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions -prometheusRule: - # prometheusRule.enabled -- If true, creates a Prometheus Operator PrometheusRule. - enabled: false - # prometheusRule.additionalLabels -- Additional labels to be set in metadata. - additionalLabels: {} - # prometheusRule.namespace -- Namespace which Prometheus is running in. - namespace: monitoring - # prometheusRule.interval -- How often rules in the group are evaluated (falls back to `global.evaluation_interval` if not set). - interval: null - # prometheusRule.rules -- Rules spec template (see https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#rule). - rules: [] - -rbac: - # rbac.create -- If `true`, create and use RBAC resources. - create: true - # rbac.pspEnabled -- If `true`, creates and uses RBAC resources required in the cluster with [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) enabled. - # Must be used with `rbac.create` set to `true`. - pspEnabled: false - # rbac.clusterScoped -- if set to false will only provision RBAC to alter resources in the current namespace. Most useful for Cluster-API - clusterScoped: true - # rbac.annotations -- Additional annotations to add to RBAC resources (Role/RoleBinding/ClusterRole/ClusterRoleBinding). - annotations: {} - serviceAccount: - # rbac.serviceAccount.annotations -- Additional Service Account annotations. - annotations: {} - # rbac.serviceAccount.create -- If `true` and `rbac.create` is also true, a Service Account will be created. - create: true - # rbac.serviceAccount.name -- The name of the ServiceAccount to use. If not set and create is `true`, a name is generated using the fullname template. - name: "" - # rbac.serviceAccount.automountServiceAccountToken -- Automount API credentials for a Service Account. - automountServiceAccountToken: true - # rbac.additionalRules -- Additional rules for role/clusterrole - additionalRules: [] - # - apiGroups: - # - infrastructure.cluster.x-k8s.io - # resources: - # - kubemarkmachinetemplates - # verbs: - # - get - # - list - # - watch - - -# replicaCount -- Desired number of pods -replicaCount: 1 - -# resources -- Pod resource requests and limits. -resources: {} - # limits: - # cpu: 100m - # memory: 300Mi - # requests: - # cpu: 100m - # memory: 300Mi - -# revisionHistoryLimit -- The number of revisions to keep. -revisionHistoryLimit: 10 - -# securityContext -- [Security context for pod](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) -securityContext: {} - # runAsNonRoot: true - # runAsUser: 65534 - # runAsGroup: 65534 - # seccompProfile: - # type: RuntimeDefault - -service: - # service.create -- If `true`, a Service will be created. - create: true - # service.annotations -- Annotations to add to service - annotations: {} - # service.labels -- Labels to add to service - labels: {} - # service.externalIPs -- List of IP addresses at which the service is available. Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips. - externalIPs: [] - - # service.selector -- Override labels for Service `spec.selector`. - selector: {} - - # service.clusterIP -- IP address to assign to service - clusterIP: "" - - # service.loadBalancerIP -- IP address to assign to load balancer (if supported). - loadBalancerIP: "" - # service.loadBalancerSourceRanges -- List of IP CIDRs allowed access to load balancer (if supported). - loadBalancerSourceRanges: [] - # service.servicePort -- Service port to expose. - servicePort: 8085 - # service.portName -- Name for service port. - portName: http - # service.type -- Type of service to create. - type: ClusterIP - -## Are you using Prometheus Operator? -serviceMonitor: - # serviceMonitor.enabled -- If true, creates a Prometheus Operator ServiceMonitor. - enabled: false - # serviceMonitor.interval -- Interval that Prometheus scrapes Cluster Autoscaler metrics. - interval: 10s - # serviceMonitor.namespace -- Namespace which Prometheus is running in. - namespace: monitoring - ## [Prometheus Selector Label](https://github.com/helm/charts/tree/master/stable/prometheus-operator#prometheus-operator-1) - ## [Kube Prometheus Selector Label](https://github.com/helm/charts/tree/master/stable/prometheus-operator#exporters) - # serviceMonitor.selector -- Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install. - selector: - release: prometheus-operator - # serviceMonitor.path -- The path to scrape for metrics; autoscaler exposes `/metrics` (this is standard) - path: /metrics - # serviceMonitor.annotations -- Annotations to add to service monitor - annotations: {} - ## [RelabelConfig](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.RelabelConfig) - # serviceMonitor.relabelings -- RelabelConfigs to apply to metrics before scraping. - relabelings: {} - ## [RelabelConfig](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.RelabelConfig) - # serviceMonitor.metricRelabelings -- MetricRelabelConfigs to apply to samples before ingestion. - metricRelabelings: {} - -# tolerations -- List of node taints to tolerate (requires Kubernetes >= 1.6). -tolerations: [] - -# topologySpreadConstraints -- You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19). -topologySpreadConstraints: [] - # - maxSkew: 1 - # topologyKey: topology.kubernetes.io/zone - # whenUnsatisfiable: DoNotSchedule - # labelSelector: - # matchLabels: - # app.kubernetes.io/instance: cluster-autoscaler - -# updateStrategy -- [Deployment update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) -updateStrategy: {} - # rollingUpdate: - # maxSurge: 1 - # maxUnavailable: 0 - # type: RollingUpdate - -# vpa -- Configure a VerticalPodAutoscaler for the cluster-autoscaler Deployment. -vpa: - # vpa.enabled -- If true, creates a VerticalPodAutoscaler. - enabled: false - # vpa.updateMode -- [UpdateMode](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L124) - updateMode: "Auto" - # vpa.containerPolicy -- [ContainerResourcePolicy](https://github.com/kubernetes/autoscaler/blob/vertical-pod-autoscaler/v0.13.0/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L159). The containerName is always set to the deployment's container name. This value is required if VPA is enabled. - containerPolicy: {} - # vpa.recommender -- Name of the VPA recommender that will provide recommendations for vertical scaling. - recommender: default - -# secretKeyRefNameOverride -- Overrides the name of the Secret to use when loading the secretKeyRef for AWS, Azure and Civo env variables -secretKeyRefNameOverride: "" diff --git a/packages/system/cluster-autoscaler/values-azure.yaml b/packages/system/cluster-autoscaler/values-azure.yaml deleted file mode 100644 index 7720481a..00000000 --- a/packages/system/cluster-autoscaler/values-azure.yaml +++ /dev/null @@ -1,12 +0,0 @@ -cluster-autoscaler: - cloudProvider: azure - rbac: - additionalRules: - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - get - - update diff --git a/packages/system/cluster-autoscaler/values-hetzner.yaml b/packages/system/cluster-autoscaler/values-hetzner.yaml deleted file mode 100644 index 8e19fc53..00000000 --- a/packages/system/cluster-autoscaler/values-hetzner.yaml +++ /dev/null @@ -1,12 +0,0 @@ -cluster-autoscaler: - cloudProvider: hetzner - rbac: - additionalRules: - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - get - - update diff --git a/packages/system/cluster-autoscaler/values.yaml b/packages/system/cluster-autoscaler/values.yaml deleted file mode 100644 index eaef53d9..00000000 --- a/packages/system/cluster-autoscaler/values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -cluster-autoscaler: - extraArgs: - enforce-node-group-min-size: true diff --git a/packages/system/clustersecret-operator/.helmignore b/packages/system/clustersecret-operator/.helmignore deleted file mode 100644 index d5c178e8..00000000 --- a/packages/system/clustersecret-operator/.helmignore +++ /dev/null @@ -1,3 +0,0 @@ -images -hack -.gitkeep diff --git a/packages/system/clustersecret-operator/Chart.yaml b/packages/system/clustersecret-operator/Chart.yaml deleted file mode 100644 index bc9ef8e7..00000000 --- a/packages/system/clustersecret-operator/Chart.yaml +++ /dev/null @@ -1,3 +0,0 @@ -apiVersion: v2 -name: cozy-clustersecret-operator -version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/clustersecret-operator/Makefile b/packages/system/clustersecret-operator/Makefile deleted file mode 100644 index 34fa1464..00000000 --- a/packages/system/clustersecret-operator/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -export NAME=clustersecret-operator -export NAMESPACE=cozy-clustersecret-operator - -export REPO_NAME=clustersecret-operator -export REPO_URL=https://sap.github.io/clustersecret-operator-helm -export CHART_NAME=clustersecret-operator -export CHART_VERSION=^0.3 - -include ../../../hack/package.mk - -update: clean clustersecret-operator-update diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/.helmignore b/packages/system/clustersecret-operator/charts/clustersecret-operator/.helmignore deleted file mode 100644 index 0e8a0eb3..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/.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/packages/system/clustersecret-operator/charts/clustersecret-operator/Chart.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/Chart.yaml deleted file mode 100644 index 447e8530..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -appVersion: v0.3.68 -description: A Helm chart for https://github.com/sap/clustersecret-operator -name: clustersecret-operator -type: application -version: 0.3.68 diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/README.md b/packages/system/clustersecret-operator/charts/clustersecret-operator/README.md deleted file mode 100644 index 11b21f84..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# clustersecret-operator - -![Version: 0.3.68](https://img.shields.io/badge/Version-0.3.68-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.3.68](https://img.shields.io/badge/AppVersion-v0.3.68-informational?style=flat-square) - -A Helm chart for https://github.com/sap/clustersecret-operator - -## Values - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| fullnameOverride | string | `""` | Override full name | -| nameOverride | string | `""` | Override name | -| global.image.tag | string | `""` | Image tag (defauls to .Chart.AppVersion) | -| global.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | -| global.imagePullSecrets | list | `[]` | Image pull secrets | -| global.affinity | object | `{}` | Affinity settings | -| global.nodeSelector | object | `{}` | Node selector | -| global.topologySpreadConstraints | list | `[]` | Topology spread constraints (if unspecified, default constraints for hostname and zone will be generated) | -| global.defaultHostNameSpreadPolicy | string | `"ScheduleAnyway"` | Default topology spread policy for hostname | -| global.defaultZoneSpreadPolicy | string | `"ScheduleAnyway"` | Default topology spread policy for zone | -| global.tolerations | list | `[]` | Tolerations | -| global.priorityClassName | string | `""` | Priority class | -| global.podSecurityContext | object | `{}` | Pod security context | -| global.podAnnotations | object | `{}` | Additional pod annotations | -| global.podLabels | object | `{}` | Additional pod labels | -| global.securityContext | object | `{}` | Container security context | -| global.logLevel | int | `0` | Log level | -| controller.replicaCount | int | `1` | Replica count | -| controller.image.repository | string | `"ghcr.io/sap/clustersecret-operator/controller"` | Image repository | -| controller.image.tag | string | `""` | Image tag (defauls to .Chart.AppVersion) | -| controller.image.pullPolicy | string | `""` | Image pull policy | -| controller.imagePullSecrets | list | `[]` | Image pull secrets | -| controller.affinity | object | `{}` | Affinity settings | -| controller.nodeSelector | object | `{}` | Node selector | -| controller.topologySpreadConstraints | list | `[]` | Topology spread constraints (if unspecified, default constraints for hostname and zone will be generated) | -| controller.defaultHostNameSpreadPolicy | string | `""` | Default topology spread policy for hostname | -| controller.defaultZoneSpreadPolicy | string | `""` | Default topology spread policy for zone | -| controller.tolerations | list | `[]` | Tolerations | -| controller.priorityClassName | string | `""` | Priority class | -| controller.podSecurityContext | object | `{}` | Pod security context | -| controller.podAnnotations | object | `{}` | Additional pod annotations | -| controller.podLabels | object | `{}` | Additional pod labels | -| controller.securityContext | object | `{}` | Container security context | -| controller.resources.limits.memory | string | `"200Mi"` | Memory limit | -| controller.resources.limits.cpu | float | `0.1` | CPU limit | -| controller.resources.requests.memory | string | `"20Mi"` | Memory request | -| controller.resources.requests.cpu | float | `0.01` | CPU request | -| controller.logLevel | int | `0` | Log level | -| webhook.replicaCount | int | `1` | Replica count | -| webhook.image.repository | string | `"ghcr.io/sap/clustersecret-operator/webhook"` | Image repository | -| webhook.image.tag | string | `""` | Image tag (defauls to .Chart.AppVersion) | -| webhook.image.pullPolicy | string | `""` | Image pull policy | -| webhook.imagePullSecrets | list | `[]` | Image pull secrets | -| webhook.affinity | object | `{}` | Affinity settings | -| webhook.nodeSelector | object | `{}` | Node selector | -| webhook.topologySpreadConstraints | list | `[]` | Topology spread constraints (if unspecified, default constraints for hostname and zone will be generated) | -| webhook.defaultHostNameSpreadPolicy | string | `""` | Default topology spread policy for hostname | -| webhook.defaultZoneSpreadPolicy | string | `""` | Default topology spread policy for zone | -| webhook.tolerations | list | `[]` | Tolerations | -| webhook.priorityClassName | string | `""` | Priority class | -| webhook.podSecurityContext | object | `{}` | Pod security context | -| webhook.podAnnotations | object | `{}` | Additional pod annotations | -| webhook.podLabels | object | `{}` | Additional pod labels | -| webhook.securityContext | object | `{}` | Container security context | -| webhook.resources.limits.memory | string | `"100Mi"` | Memory limit | -| webhook.resources.limits.cpu | float | `0.1` | CPU limit | -| webhook.resources.requests.memory | string | `"20Mi"` | Memory request | -| webhook.resources.requests.cpu | float | `0.01` | CPU request | -| webhook.service.type | string | `"ClusterIP"` | Service type | -| webhook.service.port | int | `443` | Service port | -| webhook.logLevel | int | `0` | Log level | - ----------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/crds/clustersecrets.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/crds/clustersecrets.yaml deleted file mode 100644 index e28a99b3..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/crds/clustersecrets.yaml +++ /dev/null @@ -1,106 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: clustersecrets.core.cs.sap.com -spec: - scope: Cluster - names: - plural: clustersecrets - singular: clustersecret - kind: ClusterSecret - group: core.cs.sap.com - versions: - - name: v1alpha1 - served: true - storage: true - additionalPrinterColumns: - - name: Age - type: date - jsonPath: .metadata.creationTimestamp - - name: State - type: string - jsonPath: .status.state - subresources: - status: {} - schema: - openAPIV3Schema: - type: object - required: ["spec"] - properties: - spec: - type: object - required: ["template"] - properties: - namespaceSelector: - type: object - anyOf: - - required: ["matchLabels"] - - required: ["matchExpressions"] - properties: - matchLabels: - type: object - additionalProperties: - type: string - nullable: true - matchExpressions: - type: array - items: - type: object - properties: - key: - type: string - operator: - type: string - enum: ["In","NotIn","Exists","DoesNotExist"] - values: - type: array - items: - type: string - template: - type: object - required: ["type"] - properties: - type: - type: string - minLength: 1 - data: - type: object - additionalProperties: - type: string - nullable: true - stringData: - type: object - additionalProperties: - type: string - nullable: true - status: - type: object - properties: - observedGeneration: - type: integer - state: - type: string - enum: ["Ready","Processing","Deleting","Error"] - conditions: - type: array - items: - type: object - required: ["type","status"] - properties: - type: - type: string - enum: ["Ready"] - status: - type: string - enum: ["True","False","Unknown"] - lastUpdateTime: - type: string - format: datetime - lastTransitionTime: - type: string - format: datetime - reason: - type: string - minLength: 1 - message: - type: string diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers-controller.tpl b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers-controller.tpl deleted file mode 100644 index 4f012e93..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers-controller.tpl +++ /dev/null @@ -1,13 +0,0 @@ -{{- define "clustersecret-operator.controller.fullname" -}} -{{ include "clustersecret-operator.fullname" . }}-controller -{{- end }} - -{{- define "clustersecret-operator.controller.labels" -}} -{{ include "clustersecret-operator.labels" . }} -app.kubernetes.io/component: controller -{{- end }} - -{{- define "clustersecret-operator.controller.selectorLabels" -}} -{{ include "clustersecret-operator.selectorLabels" . }} -app.kubernetes.io/component: controller -{{- end }} \ No newline at end of file diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers-webhook.tpl b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers-webhook.tpl deleted file mode 100644 index 77a8a372..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers-webhook.tpl +++ /dev/null @@ -1,13 +0,0 @@ -{{- define "clustersecret-operator.webhook.fullname" -}} -{{ include "clustersecret-operator.fullname" . }}-webhook -{{- end }} - -{{- define "clustersecret-operator.webhook.labels" -}} -{{ include "clustersecret-operator.labels" . }} -app.kubernetes.io/component: webhook -{{- end }} - -{{- define "clustersecret-operator.webhook.selectorLabels" -}} -{{ include "clustersecret-operator.selectorLabels" . }} -app.kubernetes.io/component: webhook -{{- end }} \ No newline at end of file diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers.tpl b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers.tpl deleted file mode 100644 index 48b65844..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/_helpers.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "clustersecret-operator.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 "clustersecret-operator.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 "clustersecret-operator.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "clustersecret-operator.labels" -}} -helm.sh/chart: {{ include "clustersecret-operator.chart" . }} -{{ include "clustersecret-operator.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "clustersecret-operator.selectorLabels" -}} -app.kubernetes.io/name: {{ include "clustersecret-operator.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-deployment.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-deployment.yaml deleted file mode 100644 index e42a33a3..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-deployment.yaml +++ /dev/null @@ -1,96 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "clustersecret-operator.controller.fullname" . }} - labels: - {{- include "clustersecret-operator.controller.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.controller.replicaCount }} - selector: - matchLabels: - {{- include "clustersecret-operator.controller.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.controller.podAnnotations | default .Values.global.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "clustersecret-operator.controller.selectorLabels" . | nindent 8 }} - {{- with .Values.controller.podLabels | default .Values.global.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.controller.imagePullSecrets | default .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.controller.podSecurityContext | default .Values.global.podSecurityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.controller.nodeSelector | default .Values.global.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.controller.affinity | default .Values.global.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.controller.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} - topologySpreadConstraints: - {{- range . }} - - {{ toYaml . | nindent 8 | trim }} - {{- if not .labelSelector }} - labelSelector: - matchLabels: - {{- include "clustersecret-operator.controller.selectorLabels" $ | nindent 12 }} - {{- end }} - {{- end }} - {{- else }} - topologySpreadConstraints: - - maxSkew: 1 - topologyKey: kubernetes.io/hostname - nodeTaintsPolicy: Honor - whenUnsatisfiable: {{ .Values.controller.defaultHostNameSpreadPolicy | default .Values.global.defaultHostNameSpreadPolicy }} - labelSelector: - matchLabels: - {{- include "clustersecret-operator.controller.selectorLabels" . | nindent 12 }} - - maxSkew: 1 - topologyKey: topology.kubernetes.io/zone - nodeTaintsPolicy: Honor - whenUnsatisfiable: {{ .Values.controller.defaultZoneSpreadPolicy | default .Values.global.defaultZoneSpreadPolicy }} - labelSelector: - matchLabels: - {{- include "clustersecret-operator.controller.selectorLabels" . | nindent 12 }} - {{- end }} - {{- with .Values.controller.tolerations | default .Values.global.tolerations }} - tolerations: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.controller.priorityClassName | default .Values.global.priorityClassName }} - priorityClassName: {{ . }} - {{- end }} - serviceAccountName: {{ include "clustersecret-operator.controller.fullname" . }} - automountServiceAccountToken: true - containers: - - name: controller - image: {{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag | default .Values.global.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.controller.image.pullPolicy | default .Values.global.image.pullPolicy }} - {{- with .Values.controller.securityContext | default .Values.global.securityContext }} - securityContext: - {{- toYaml . | nindent 12 }} - {{- end }} - resources: - {{- toYaml .Values.controller.resources | nindent 12 }} - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - args: - - "--lease_namespace={{ .Release.Namespace }}" - - "--lease_name={{ include "clustersecret-operator.controller.fullname" . }}" - - "--lease_id=$(POD_NAME)" - - "--v={{ .Values.controller.logLevel | default .Values.global.logLevel | default 0 }}" diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-pdb.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-pdb.yaml deleted file mode 100644 index 6f1985d5..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-pdb.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if ge (int .Values.controller.replicaCount) 2 }} -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: {{ include "clustersecret-operator.controller.fullname" . }} - labels: - {{- include "clustersecret-operator.controller.labels" . | nindent 4 }} -spec: - minAvailable: 1 - selector: - matchLabels: - {{- include "clustersecret-operator.controller.selectorLabels" . | nindent 6 }} -{{- end }} \ No newline at end of file diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-rbac.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-rbac.yaml deleted file mode 100644 index 040a5559..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/controller-rbac.yaml +++ /dev/null @@ -1,74 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "clustersecret-operator.controller.fullname" . }} - labels: - {{- include "clustersecret-operator.controller.labels" . | nindent 4 }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - namespace: {{ .Release.Namespace }} - name: {{ include "clustersecret-operator.controller.fullname" . }} - labels: - {{- include "clustersecret-operator.controller.labels" . | nindent 4 }} -rules: -- apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["create"] -- apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - resourceNames: ["{{ include "clustersecret-operator.controller.fullname" . }}"] - verbs: ["get","list","watch","update","patch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - namespace: {{ .Release.Namespace }} - name: {{ include "clustersecret-operator.controller.fullname" . }} - labels: - {{- include "clustersecret-operator.controller.labels" . | nindent 4 }} -subjects: -- kind: ServiceAccount - namespace: {{ .Release.Namespace }} - name: {{ include "clustersecret-operator.controller.fullname" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: {{ include "clustersecret-operator.controller.fullname" . }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "clustersecret-operator.controller.fullname" . }} - labels: - {{- include "clustersecret-operator.controller.labels" . | nindent 4 }} -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get","list","watch","create","update","patch","delete"] -- apiGroups: [""] - resources: ["namespaces"] - verbs: ["get","list","watch"] -- apiGroups: ["core.cs.sap.com"] - resources: ["clustersecrets","clustersecrets/status"] - verbs: ["get","list","watch","update"] -- apiGroups: ["","events.k8s.io"] - resources: ["events"] - verbs: ["*"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "clustersecret-operator.controller.fullname" . }} - labels: - {{- include "clustersecret-operator.controller.labels" . | nindent 4 }} -subjects: -- kind: ServiceAccount - namespace: {{ .Release.Namespace }} - name: {{ include "clustersecret-operator.controller.fullname" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "clustersecret-operator.controller.fullname" . }} diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/tests/rbac.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/tests/rbac.yaml deleted file mode 100644 index 83205ec0..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/tests/rbac.yaml +++ /dev/null @@ -1,58 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "clustersecret-operator.fullname" . }}-test - labels: - {{- include "clustersecret-operator.labels" . | nindent 4 }} - annotations: - helm.sh/hook: test - helm.sh/hook-weight: "-1" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "clustersecret-operator.fullname" . }}-test - labels: - {{- include "clustersecret-operator.labels" . | nindent 4 }} - annotations: - helm.sh/hook: test - helm.sh/hook-weight: "-1" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded -rules: -- apiGroups: - - core.cs.sap.com - resources: - - clustersecrets - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "clustersecret-operator.fullname" . }}-test - labels: - {{- include "clustersecret-operator.labels" . | nindent 4 }} - annotations: - helm.sh/hook: test - helm.sh/hook-weight: "-1" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded -subjects: -- kind: ServiceAccount - namespace: {{ .Release.Namespace }} - name: {{ include "clustersecret-operator.fullname" . }}-test -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "clustersecret-operator.fullname" . }}-test diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/tests/test-1.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/tests/test-1.yaml deleted file mode 100644 index 2c163a78..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/tests/test-1.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- $clusterSecretName := printf "%s-test-1-%s" (include "clustersecret-operator.fullname" .) (randAlphaNum 10 | lower) }} ---- -apiVersion: core.cs.sap.com/v1alpha1 -kind: ClusterSecret -metadata: - name: {{ $clusterSecretName }} - labels: - {{- include "clustersecret-operator.labels" . | nindent 4 }} - annotations: - helm.sh/hook: test - helm.sh/hook-weight: "0" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded -spec: - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: default - template: - type: Opaque - data: - mykey: bXl2YWx1ZQ== ---- -apiVersion: v1 -kind: Pod -metadata: - name: {{ include "clustersecret-operator.fullname" . }}-test-1 - labels: - {{- include "clustersecret-operator.labels" . | nindent 4 }} - annotations: - helm.sh/hook: test - helm.sh/hook-weight: "1" - helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded -spec: - containers: - - name: kubectl - image: ghcr.io/sap/kubectl-container:{{ .Capabilities.KubeVersion.Version }} - command: - - bash - - -ec - - | - kubectl wait clustersecrets.core.cs.sap.com/{{ $clusterSecretName }} --for condition=Ready --timeout 30s - kubectl -n default get secret {{ $clusterSecretName }} - serviceAccountName: {{ include "clustersecret-operator.fullname" . }}-test - terminationGracePeriodSeconds: 3 - restartPolicy: Never diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-admission.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-admission.yaml deleted file mode 100644 index 5e49e23c..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-admission.yaml +++ /dev/null @@ -1,107 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ include "clustersecret-operator.webhook.fullname" . }} - labels: - {{- include "clustersecret-operator.webhook.labels" . | nindent 4 }} -spec: - type: {{ .Values.webhook.service.type }} - ports: - - port: {{ .Values.webhook.service.port }} - targetPort: 1443 - protocol: TCP - name: https - selector: - {{- include "clustersecret-operator.webhook.selectorLabels" . | nindent 4 }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "clustersecret-operator.webhook.fullname" . }}-tls - labels: - {{- include "clustersecret-operator.webhook.labels" . | nindent 4 }} -type: Opaque -data: - {{- $data := (lookup "v1" "Secret" .Release.Namespace (printf "%s-tls" (include "clustersecret-operator.webhook.fullname" .))).data }} - {{- $caCert := "" }} - {{- if $data }} - {{ $data | toYaml | nindent 2 }} - {{- $caCert = index $data "ca.crt" }} - {{- else }} - {{- $cn := printf "%s.%s.svc" (include "clustersecret-operator.webhook.fullname" .) .Release.Namespace }} - {{- $ca := genCA (printf "%s-ca" (include "clustersecret-operator.webhook.fullname" .)) 36500 }} - {{- $cert := genSignedCert $cn (list "127.0.0.1") (list $cn "localhost") 36500 $ca }} - ca.crt: {{ $ca.Cert | b64enc }} - tls.crt: {{ $cert.Cert | b64enc }} - tls.key: {{ $cert.Key | b64enc }} - {{- $caCert = $ca.Cert | b64enc }} - {{- end }} ---- -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: clustersecret-operator - labels: - {{- include "clustersecret-operator.webhook.labels" . | nindent 4 }} -webhooks: -- name: clustersecret-operator.cs.sap.com - admissionReviewVersions: - - v1 - clientConfig: - caBundle: {{ $caCert }} - service: - name: {{ include "clustersecret-operator.webhook.fullname" . }} - namespace: {{ .Release.Namespace }} - path: /validation - port: {{ .Values.webhook.service.port }} - rules: - - apiGroups: - - core.cs.sap.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - - DELETE - resources: - - clustersecrets - scope: Cluster - matchPolicy: Exact - sideEffects: None - timeoutSeconds: 10 - failurePolicy: Fail ---- -apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - name: clustersecret-operator - labels: - {{- include "clustersecret-operator.webhook.labels" . | nindent 4 }} -webhooks: -- name: clustersecret-operator.cs.sap.com - admissionReviewVersions: - - v1 - clientConfig: - caBundle: {{ $caCert }} - service: - name: {{ include "clustersecret-operator.webhook.fullname" . }} - namespace: {{ .Release.Namespace }} - path: /mutation - port: {{ .Values.webhook.service.port }} - rules: - - apiGroups: - - core.cs.sap.com - apiVersions: - - v1alpha1 - operations: - - CREATE - - UPDATE - - DELETE - resources: - - clustersecrets - scope: Cluster - matchPolicy: Exact - sideEffects: None - timeoutSeconds: 10 - failurePolicy: Fail \ No newline at end of file diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-deployment.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-deployment.yaml deleted file mode 100644 index df766a52..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-deployment.yaml +++ /dev/null @@ -1,109 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "clustersecret-operator.webhook.fullname" . }} - labels: - {{- include "clustersecret-operator.webhook.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.webhook.replicaCount }} - selector: - matchLabels: - {{- include "clustersecret-operator.webhook.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.webhook.podAnnotations | default .Values.global.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "clustersecret-operator.webhook.selectorLabels" . | nindent 8 }} - {{- with .Values.webhook.podLabels | default .Values.global.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.webhook.imagePullSecrets | default .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.webhook.podSecurityContext | default .Values.global.podSecurityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.webhook.nodeSelector | default .Values.global.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.webhook.affinity | default .Values.global.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.webhook.topologySpreadConstraints | default .Values.global.topologySpreadConstraints }} - topologySpreadConstraints: - {{- range . }} - - {{ toYaml . | nindent 8 | trim }} - {{- if not .labelSelector }} - labelSelector: - matchLabels: - {{- include "clustersecret-operator.webhook.selectorLabels" $ | nindent 12 }} - {{- end }} - {{- end }} - {{- else }} - topologySpreadConstraints: - - maxSkew: 1 - topologyKey: kubernetes.io/hostname - nodeTaintsPolicy: Honor - whenUnsatisfiable: {{ .Values.webhook.defaultHostNameSpreadPolicy | default .Values.global.defaultHostNameSpreadPolicy }} - labelSelector: - matchLabels: - {{- include "clustersecret-operator.webhook.selectorLabels" . | nindent 12 }} - - maxSkew: 1 - topologyKey: topology.kubernetes.io/zone - nodeTaintsPolicy: Honor - whenUnsatisfiable: {{ .Values.webhook.defaultZoneSpreadPolicy | default .Values.global.defaultZoneSpreadPolicy }} - labelSelector: - matchLabels: - {{- include "clustersecret-operator.webhook.selectorLabels" . | nindent 12 }} - {{- end }} - {{- with .Values.webhook.tolerations | default .Values.global.tolerations }} - tolerations: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.webhook.priorityClassName | default .Values.global.priorityClassName }} - priorityClassName: {{ . }} - {{- end }} - serviceAccountName: {{ include "clustersecret-operator.webhook.fullname" . }} - automountServiceAccountToken: true - containers: - - name: webhook - image: {{ .Values.webhook.image.repository }}:{{ .Values.webhook.image.tag | default .Values.global.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.webhook.image.pullPolicy | default .Values.global.image.pullPolicy }} - {{- with .Values.webhook.securityContext | default .Values.global.securityContext }} - securityContext: - {{- toYaml . | nindent 12 }} - {{- end }} - resources: - {{- toYaml .Values.webhook.resources | nindent 12 }} - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - args: - - "--bind_address=:1443" - - "--tls_enabled=true" - - "--tls_key_file=/app/etc/ssl/tls.key" - - "--tls_cert_file=/app/etc/ssl/tls.crt" - - "--v={{ .Values.webhook.logLevel | default .Values.global.logLevel | default 0 }}" - volumeMounts: - - name: ssl - mountPath: /app/etc/ssl - volumes: - - name: ssl - secret: - secretName: {{ include "clustersecret-operator.webhook.fullname" . }}-tls - items: - - key: tls.key - path: tls.key - - key: tls.crt - path: tls.crt diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-pdb.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-pdb.yaml deleted file mode 100644 index bdfc1bc1..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-pdb.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if ge (int .Values.webhook.replicaCount) 2 }} -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: {{ include "clustersecret-operator.webhook.fullname" . }} - labels: - {{- include "clustersecret-operator.webhook.labels" . | nindent 4 }} -spec: - minAvailable: 1 - selector: - matchLabels: - {{- include "clustersecret-operator.webhook.selectorLabels" . | nindent 6 }} -{{- end }} \ No newline at end of file diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-rbac.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-rbac.yaml deleted file mode 100644 index c149e28a..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/templates/webhook-rbac.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "clustersecret-operator.webhook.fullname" . }} - labels: - {{- include "clustersecret-operator.webhook.labels" . | nindent 4 }} diff --git a/packages/system/clustersecret-operator/charts/clustersecret-operator/values.yaml b/packages/system/clustersecret-operator/charts/clustersecret-operator/values.yaml deleted file mode 100644 index 3eb14836..00000000 --- a/packages/system/clustersecret-operator/charts/clustersecret-operator/values.yaml +++ /dev/null @@ -1,138 +0,0 @@ -# -- Override full name -fullnameOverride: "" -# -- Override name -nameOverride: "" - -global: - image: - # -- Image tag (defauls to .Chart.AppVersion) - tag: "" - # -- Image pull policy - pullPolicy: IfNotPresent - # -- Image pull secrets - imagePullSecrets: [] - # -- Affinity settings - affinity: {} - # -- Node selector - nodeSelector: {} - # -- Topology spread constraints (if unspecified, default constraints for hostname and zone will be generated) - topologySpreadConstraints: [] - # -- Default topology spread policy for hostname - defaultHostNameSpreadPolicy: ScheduleAnyway - # -- Default topology spread policy for zone - defaultZoneSpreadPolicy: ScheduleAnyway - # -- Tolerations - tolerations: [] - # -- Priority class - priorityClassName: "" - # -- Pod security context - podSecurityContext: {} - # -- Additional pod annotations - podAnnotations: {} - # -- Additional pod labels - podLabels: {} - # -- Container security context - securityContext: {} - # -- Log level - logLevel: 0 - -controller: - # -- Replica count - replicaCount: 1 - image: - # -- Image repository - repository: ghcr.io/sap/clustersecret-operator/controller - # -- Image tag (defauls to .Chart.AppVersion) - tag: "" - # -- Image pull policy - pullPolicy: "" - # -- Image pull secrets - imagePullSecrets: [] - # -- Affinity settings - affinity: {} - # -- Node selector - nodeSelector: {} - # -- Topology spread constraints (if unspecified, default constraints for hostname and zone will be generated) - topologySpreadConstraints: [] - # -- Default topology spread policy for hostname - defaultHostNameSpreadPolicy: "" - # -- Default topology spread policy for zone - defaultZoneSpreadPolicy: "" - # -- Tolerations - tolerations: [] - # -- Priority class - priorityClassName: "" - # -- Pod security context - podSecurityContext: {} - # -- Additional pod annotations - podAnnotations: {} - # -- Additional pod labels - podLabels: {} - # -- Container security context - securityContext: {} - resources: - limits: - # -- Memory limit - memory: 200Mi - # -- CPU limit - cpu: 0.1 - requests: - # -- Memory request - memory: 20Mi - # -- CPU request - cpu: 0.01 - # -- Log level - logLevel: 0 - -webhook: - # -- Replica count - replicaCount: 1 - image: - # -- Image repository - repository: ghcr.io/sap/clustersecret-operator/webhook - # -- Image tag (defauls to .Chart.AppVersion) - tag: "" - # -- Image pull policy - pullPolicy: "" - # -- Image pull secrets - imagePullSecrets: [] - # -- Affinity settings - affinity: {} - # -- Node selector - nodeSelector: {} - # -- Topology spread constraints (if unspecified, default constraints for hostname and zone will be generated) - topologySpreadConstraints: [] - # -- Default topology spread policy for hostname - defaultHostNameSpreadPolicy: "" - # -- Default topology spread policy for zone - defaultZoneSpreadPolicy: "" - # -- Tolerations - tolerations: [] - # -- Priority class - priorityClassName: "" - # -- Pod security context - podSecurityContext: {} - # -- Additional pod annotations - podAnnotations: {} - # -- Additional pod labels - podLabels: {} - # -- Container security context - securityContext: {} - resources: - limits: - # -- Memory limit - memory: 100Mi - # -- CPU limit - cpu: 0.1 - requests: - # -- Memory request - memory: 20Mi - # -- CPU request - cpu: 0.01 - service: - # -- Service type - type: ClusterIP - # -- Service port - port: 443 - # -- Log level - logLevel: 0 diff --git a/packages/system/clustersecret-operator/values.yaml b/packages/system/clustersecret-operator/values.yaml deleted file mode 100644 index ff7b161a..00000000 --- a/packages/system/clustersecret-operator/values.yaml +++ /dev/null @@ -1 +0,0 @@ -clustersecret-operator: {} diff --git a/packages/system/coredns/values.yaml b/packages/system/coredns/values.yaml index 7f6403b8..a1061a1e 100644 --- a/packages/system/coredns/values.yaml +++ b/packages/system/coredns/values.yaml @@ -6,6 +6,3 @@ coredns: k8sAppLabelOverride: kube-dns service: name: kube-dns - serviceAccount: - create: true - name: kube-dns diff --git a/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml b/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml index 58f166f6..13352680 100644 --- a/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml +++ b/packages/system/cozy-proxy/charts/cozy-proxy/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: cozy-proxy description: A simple kube-proxy addon for 1:1 NAT services in Kubernetes using an NFT backend type: application -version: 0.3.0 -appVersion: 0.3.0 +version: 0.2.0 +appVersion: 0.2.0 diff --git a/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml b/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml index e143e926..8cde5bed 100644 --- a/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml +++ b/packages/system/cozy-proxy/charts/cozy-proxy/values.yaml @@ -1,6 +1,6 @@ image: repository: ghcr.io/cozystack/cozystack/cozy-proxy - tag: v0.3.0 + tag: v0.2.0 pullPolicy: IfNotPresent daemonset: diff --git a/packages/system/cozystack-api/templates/certmanager.yaml b/packages/system/cozystack-api/templates/certmanager.yaml index 4f73768a..def27bd1 100644 --- a/packages/system/cozystack-api/templates/certmanager.yaml +++ b/packages/system/cozystack-api/templates/certmanager.yaml @@ -18,8 +18,6 @@ spec: issuerRef: name: cozystack-api-selfsigned isCA: true - privateKey: - rotationPolicy: Never --- apiVersion: cert-manager.io/v1 kind: Issuer diff --git a/packages/system/cozystack-api/templates/deployment.yaml b/packages/system/cozystack-api/templates/deployment.yaml index 9febfe1e..aa877266 100644 --- a/packages/system/cozystack-api/templates/deployment.yaml +++ b/packages/system/cozystack-api/templates/deployment.yaml @@ -1,12 +1,18 @@ apiVersion: apps/v1 +{{- if .Values.cozystackAPI.localK8sAPIEndpoint.enabled }} +kind: DaemonSet +{{- else }} kind: Deployment +{{- end }} metadata: name: cozystack-api namespace: cozy-system labels: app: cozystack-api spec: + {{- if not .Values.cozystackAPI.localK8sAPIEndpoint.enabled }} replicas: {{ .Values.cozystackAPI.replicas }} + {{- end }} selector: matchLabels: app: cozystack-api @@ -18,19 +24,27 @@ spec: tolerations: - operator: Exists serviceAccountName: cozystack-api - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - preference: - matchExpressions: - - key: node-role.kubernetes.io/control-plane - operator: Exists + {{- if .Values.cozystackAPI.localK8sAPIEndpoint.enabled }} + {{- with .Values.cozystackAPI.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} containers: - name: cozystack-api args: - --tls-cert-file=/tmp/cozystack-api-certs/tls.crt - --tls-private-key-file=/tmp/cozystack-api-certs/tls.key + {{- if .Values.cozystackAPI.localK8sAPIEndpoint.enabled }} + env: + - name: KUBERNETES_SERVICE_HOST + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: KUBERNETES_SERVICE_PORT + value: "6443" + {{- end }} image: "{{ .Values.cozystackAPI.image }}" ports: - containerPort: 443 diff --git a/packages/system/cozystack-api/templates/hook.yaml b/packages/system/cozystack-api/templates/hook.yaml index 852b2db0..3c6b3080 100644 --- a/packages/system/cozystack-api/templates/hook.yaml +++ b/packages/system/cozystack-api/templates/hook.yaml @@ -1,5 +1,16 @@ -{{- $previous := lookup "apps/v1" "DaemonSet" .Release.Namespace "cozystack-api" }} +{{- $shouldRunUpdateHook := false }} +{{- $previousKind := "Deployment" }} +{{- $previousKindPlural := "deployments" }} +{{- if not .Values.cozystackAPI.localK8sAPIEndpoint.enabled }} + {{- $previousKind = "DaemonSet" }} + {{- $previousKindPlural = "daemonsets" }} +{{- end }} +{{- $previous := lookup "apps/v1" $previousKind .Release.Namespace "cozystack-api" }} {{- if $previous }} + {{- $shouldRunUpdateHook = true }} +{{- end }} + +{{- if $shouldRunUpdateHook }} --- apiVersion: batch/v1 kind: Job @@ -25,7 +36,7 @@ spec: - -exc - |- kubectl --namespace={{ .Release.Namespace }} delete --ignore-not-found \ - daemonsets.apps cozystack-api + {{ $previousKindPlural }}.apps cozystack-api restartPolicy: Never --- apiVersion: rbac.authorization.k8s.io/v1 @@ -40,7 +51,7 @@ rules: - apiGroups: - "apps" resources: - - "daemonsets" + - "{{ $previousKindPlural }}" verbs: - get - delete diff --git a/packages/system/cozystack-api/templates/service.yaml b/packages/system/cozystack-api/templates/service.yaml index 64ba149d..abe67abc 100644 --- a/packages/system/cozystack-api/templates/service.yaml +++ b/packages/system/cozystack-api/templates/service.yaml @@ -4,7 +4,9 @@ metadata: name: cozystack-api namespace: cozy-system spec: - trafficDistribution: PreferClose + {{- if .Values.cozystackAPI.localK8sAPIEndpoint.enabled }} + internalTrafficPolicy: Local + {{- end }} ports: - port: 443 protocol: TCP diff --git a/packages/system/cozystack-api/values.yaml b/packages/system/cozystack-api/values.yaml index dddabf54..b5abfaec 100644 --- a/packages/system/cozystack-api/values.yaml +++ b/packages/system/cozystack-api/values.yaml @@ -1,3 +1,10 @@ cozystackAPI: - image: ghcr.io/cozystack/cozystack/cozystack-api:v1.3.0@sha256:5fa8648821cf1e9e08cf7c2899c4b1c4226bb74c6773327141456c7d3f2b9b7e + image: ghcr.io/cozystack/cozystack/cozystack-api:v1.0.0-beta.2@sha256:2815ee65d13e3bde376ca3975a1106e1e32b8b911f2004d85a824a9fc30eebbd + localK8sAPIEndpoint: + enabled: true replicas: 2 + # nodeSelector for DaemonSet mode (localK8sAPIEndpoint.enabled: true) + # Talos uses empty value: "node-role.kubernetes.io/control-plane": "" + # Generic k8s (k3s, kubeadm) uses: "node-role.kubernetes.io/control-plane": "true" + nodeSelector: + node-role.kubernetes.io/control-plane: "" diff --git a/packages/system/cozystack-basics/templates/clusterroles.yaml b/packages/system/cozystack-basics/templates/clusterroles.yaml deleted file mode 100644 index f270f4e1..00000000 --- a/packages/system/cozystack-basics/templates/clusterroles.yaml +++ /dev/null @@ -1,264 +0,0 @@ ---- -# == default cluster role == -# Used by tenant ServiceAccounts -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.cozystack.io/aggregate-to-tenant: "true" -rules: [] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:base - labels: - rbac.cozystack.io/aggregate-to-tenant: "true" -rules: -- apiGroups: [""] - resources: ["pods", "services", "persistentvolumes", "endpoints", "events", "resourcequotas"] - verbs: ["get", "list", "watch"] -- apiGroups: ["discovery.k8s.io"] - resources: ["endpointslices"] - verbs: ["get", "list", "watch"] -- apiGroups: ["networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get", "list", "watch"] -- apiGroups: ["rbac.authorization.k8s.io"] - resources: ["roles"] - verbs: ["get"] -- apiGroups: ["apps.cozystack.io"] - resources: ['*'] - verbs: ['*'] -- apiGroups: - - cozystack.io - resources: - - workloadmonitors - - workloads - verbs: ["get", "list", "watch"] -- apiGroups: - - core.cozystack.io - resources: - - tenantmodules - - tenantsecrets - verbs: ["get", "list", "watch"] ---- -# == view cluster role == -# Aggregates all roles labeled for view access -# Also aggregated into use, admin, and super-admin -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:view - labels: - rbac.cozystack.io/aggregate-to-tenant-use: "true" - rbac.cozystack.io/aggregate-to-tenant-admin: "true" - rbac.cozystack.io/aggregate-to-tenant-super-admin: "true" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.cozystack.io/aggregate-to-tenant-view: "true" -rules: [] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:view:base - labels: - rbac.cozystack.io/aggregate-to-tenant-view: "true" -rules: -- apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - verbs: - - get -- apiGroups: - - apps.cozystack.io - resources: - - "*" - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - pods - - services - - persistentvolumes - - endpoints - - events - - resourcequotas - verbs: - - get - - list - - watch -- apiGroups: - - discovery.k8s.io - resources: - - endpointslices - verbs: - - get - - list - - watch -- apiGroups: - - networking.k8s.io - resources: - - ingresses - verbs: - - get - - list - - watch -- apiGroups: - - cozystack.io - resources: - - workloadmonitors - - workloads - verbs: ["get", "list", "watch"] ---- -# == use cluster role == -# Aggregates view + all roles labeled for use access -# Also aggregated into admin and super-admin -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:use - labels: - rbac.cozystack.io/aggregate-to-tenant-admin: "true" - rbac.cozystack.io/aggregate-to-tenant-super-admin: "true" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.cozystack.io/aggregate-to-tenant-use: "true" -rules: [] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:use:base - labels: - rbac.cozystack.io/aggregate-to-tenant-use: "true" -rules: -- apiGroups: ["subresources.kubevirt.io"] - resources: - - virtualmachineinstances/console - - virtualmachineinstances/vnc - verbs: - - get - - list -- apiGroups: ["subresources.kubevirt.io"] - resources: - - virtualmachineinstances/portforward - verbs: - - get - - update -- apiGroups: - - core.cozystack.io - resources: - - tenantmodules - - tenantsecrets - verbs: ["get", "list", "watch"] ---- -# == admin cluster role == -# Aggregates use + all roles labeled for admin access -# Also aggregated into super-admin -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:admin - labels: - rbac.cozystack.io/aggregate-to-tenant-super-admin: "true" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.cozystack.io/aggregate-to-tenant-admin: "true" -rules: [] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:admin:base - labels: - rbac.cozystack.io/aggregate-to-tenant-admin: "true" -rules: -- apiGroups: [""] - resources: - - pods - - services - - persistentvolumes - - endpoints - - events - verbs: - - delete -- apiGroups: ["kubevirt.io"] - resources: - - virtualmachines - verbs: - - get - - list -- apiGroups: ["apps.cozystack.io"] - resources: - - buckets - - clickhouses - - foos - - foundationdbs - - harbors - - httpcaches - - kafkas - - kuberneteses - - mariadbs - - mongodbs - - natses - - openbaos - - opensearches - - postgreses - - qdrants - - rabbitmqs - - redises - - seaweedfses - - tcpbalancers - - virtualmachines - - vmdisks - - vminstances - - vpns - - infos - - virtualprivateclouds - verbs: - - create - - update - - patch - - delete ---- -# == super admin cluster role == -# Aggregates admin + all roles labeled for super-admin access -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:super-admin -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.cozystack.io/aggregate-to-tenant-super-admin: "true" -rules: [] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:tenant:super-admin:base - labels: - rbac.cozystack.io/aggregate-to-tenant-super-admin: "true" -rules: -- apiGroups: ["kubevirt.io"] - resources: - - virtualmachines - verbs: - - '*' -- apiGroups: ["apps.cozystack.io"] - resources: - - '*' - verbs: - - '*' diff --git a/packages/system/cozystack-basics/templates/cozystack-values-secret.yaml b/packages/system/cozystack-basics/templates/cozystack-values-secret.yaml index 8c0d1c7a..b625435f 100644 --- a/packages/system/cozystack-basics/templates/cozystack-values-secret.yaml +++ b/packages/system/cozystack-basics/templates/cozystack-values-secret.yaml @@ -6,7 +6,6 @@ metadata: namespace: tenant-root labels: reconcile.fluxcd.io/watch: Enabled - internal.cozystack.io/managed-by-cozystack: "" type: Opaque stringData: values.yaml: | diff --git a/packages/system/cozystack-basics/templates/dashboard-role.yaml b/packages/system/cozystack-basics/templates/dashboard-role.yaml deleted file mode 100644 index f7656319..00000000 --- a/packages/system/cozystack-basics/templates/dashboard-role.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -# == dashboard role == -# Single namespaced role for tenant dashboard access to helm resources -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: cozy:tenant:dashboard - namespace: cozy-public -rules: -- apiGroups: ["source.toolkit.fluxcd.io"] - resources: ["helmrepositories"] - verbs: ["get", "list"] -- apiGroups: ["source.toolkit.fluxcd.io"] - resources: ["helmcharts"] - verbs: ["get", "list"] diff --git a/packages/system/cozystack-basics/templates/monitoring-external-services.yaml b/packages/system/cozystack-basics/templates/monitoring-external-services.yaml deleted file mode 100644 index e36540c4..00000000 --- a/packages/system/cozystack-basics/templates/monitoring-external-services.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: vlinsert-generic - namespace: cozy-monitoring -spec: - type: ExternalName - externalName: vlinsert-generic.tenant-root.svc.cluster.local ---- -apiVersion: v1 -kind: Service -metadata: - name: vminsert-shortterm - namespace: cozy-monitoring -spec: - type: ExternalName - externalName: vminsert-shortterm.tenant-root.svc.cluster.local ---- -apiVersion: v1 -kind: Service -metadata: - name: vminsert-longterm - namespace: cozy-monitoring -spec: - type: ExternalName - externalName: vminsert-longterm.tenant-root.svc.cluster.local diff --git a/packages/system/cozystack-basics/templates/tenant-root.yaml b/packages/system/cozystack-basics/templates/tenant-root.yaml index 93f5129e..95af9d7f 100644 --- a/packages/system/cozystack-basics/templates/tenant-root.yaml +++ b/packages/system/cozystack-basics/templates/tenant-root.yaml @@ -23,6 +23,7 @@ spec: namespace: cozy-system interval: 1m0s timeout: 5m0s - valuesFrom: - - kind: Secret - name: cozystack-values + values: + _cluster: + oidc-enabled: {{ .Values.oidcEnabled | quote }} + root-host: {{ .Values.rootHost | quote }} diff --git a/packages/system/cozystack-controller/definitions/dashboard.cozystack.io_cfomappings.yaml b/packages/system/cozystack-controller/definitions/dashboard.cozystack.io_cfomappings.yaml deleted file mode 100644 index a46f6a23..00000000 --- a/packages/system/cozystack-controller/definitions/dashboard.cozystack.io_cfomappings.yaml +++ /dev/null @@ -1,118 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.4 - name: cfomappings.dashboard.cozystack.io -spec: - group: dashboard.cozystack.io - names: - kind: CFOMapping - listKind: CFOMappingList - plural: cfomappings - singular: cfomapping - scope: Cluster - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - 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: |- - ArbitrarySpec holds schemaless user data and preserves unknown fields. - We map the entire .spec to a single JSON payload to mirror the CRDs you provided. - NOTE: Using apiextensionsv1.JSON avoids losing arbitrary structure during round-trips. - type: object - x-kubernetes-preserve-unknown-fields: true - status: - description: CommonStatus is a generic Status block with Kubernetes conditions. - properties: - conditions: - description: Conditions represent the latest available observations - of an object's state. - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration reflects the most recent generation - observed by the controller. - format: int64 - type: integer - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} diff --git a/packages/system/cozystack-controller/templates/deployment.yaml b/packages/system/cozystack-controller/templates/deployment.yaml index aab7bbe1..201aeb72 100644 --- a/packages/system/cozystack-controller/templates/deployment.yaml +++ b/packages/system/cozystack-controller/templates/deployment.yaml @@ -27,3 +27,6 @@ spec: {{- if .Values.cozystackController.disableTelemetry }} - --disable-telemetry {{- end }} + {{- if eq .Values.cozystackController.cozystackAPIKind "Deployment" }} + - --reconcile-deployment + {{- end }} diff --git a/packages/system/cozystack-controller/values.yaml b/packages/system/cozystack-controller/values.yaml index 4d0d0fde..7adbea35 100644 --- a/packages/system/cozystack-controller/values.yaml +++ b/packages/system/cozystack-controller/values.yaml @@ -1,4 +1,5 @@ cozystackController: - image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.3.0@sha256:d03d19b78c4c98f970ac549a68b01ef6bd1ad755f5e0dcb9e08503511cdf2fdc + image: ghcr.io/cozystack/cozystack/cozystack-controller:v1.0.0-beta.2@sha256:3149c8341de741bce35de27591f72be82f22634ebc5dba8889b2bbae7892579a debug: false disableTelemetry: false + cozystackAPIKind: "DaemonSet" diff --git a/packages/system/cozystack-scheduler/Chart.yaml b/packages/system/cozystack-scheduler/Chart.yaml deleted file mode 100644 index f2dd13ee..00000000 --- a/packages/system/cozystack-scheduler/Chart.yaml +++ /dev/null @@ -1,3 +0,0 @@ -apiVersion: v2 -name: cozy-cozystack-scheduler -version: 0.3.0 diff --git a/packages/system/cozystack-scheduler/Makefile b/packages/system/cozystack-scheduler/Makefile deleted file mode 100644 index d075ec63..00000000 --- a/packages/system/cozystack-scheduler/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -export NAME=cozystack-scheduler -export NAMESPACE=kube-system - -include ../../../hack/package.mk - -test: - helm unittest . - -update: - rm -rf charts - tag=$$(git ls-remote --tags --sort="v:refname" https://github.com/cozystack/cozystack-scheduler | awk -F'[/^]' 'END{print $$3}') && \ - mkdir -p charts/cozystack-scheduler && \ - curl -sSL https://github.com/cozystack/cozystack-scheduler/archive/refs/tags/$${tag}.tar.gz | \ - tar xzvf - --strip 2 -C charts/cozystack-scheduler cozystack-scheduler-$${tag#*v}/chart diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/Chart.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/Chart.yaml deleted file mode 100644 index f2dd13ee..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/Chart.yaml +++ /dev/null @@ -1,3 +0,0 @@ -apiVersion: v2 -name: cozy-cozystack-scheduler -version: 0.3.0 diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/crds/cozystack.io_schedulingclasses.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/crds/cozystack.io_schedulingclasses.yaml deleted file mode 100644 index d6b60d8b..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/crds/cozystack.io_schedulingclasses.yaml +++ /dev/null @@ -1,1123 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.19.0 - name: schedulingclasses.cozystack.io -spec: - group: cozystack.io - names: - kind: SchedulingClass - listKind: SchedulingClassList - plural: schedulingclasses - singular: schedulingclass - scope: Cluster - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - 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: - properties: - nodeAffinity: - description: Node affinity is a group of node affinity scheduling - rules. - 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 - nodeSelector: - additionalProperties: - type: string - type: object - podAffinity: - description: Pod affinity is a group of inter pod affinity scheduling - rules. - 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: Pod anti affinity is a group of inter pod anti affinity - scheduling rules. - 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 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 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 - topologySpreadConstraints: - items: - description: TopologySpreadConstraint specifies how to spread matching - pods among the given topology. - properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - 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 the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: - description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: - description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. - type: string - nodeTaintsPolicy: - description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. - type: string - topologyKey: - description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: - description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - type: object - served: true - storage: true diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/clusterrole.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/clusterrole.yaml deleted file mode 100644 index 22f196a5..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/clusterrole.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozystack-scheduler -rules: - - apiGroups: ["cozystack.io"] - resources: - - schedulingclasses - verbs: ["get", "list", "watch"] diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/clusterrolebinding.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/clusterrolebinding.yaml deleted file mode 100644 index 00fcd968..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cozystack-scheduler:kube-scheduler -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:kube-scheduler -subjects: - - kind: ServiceAccount - name: cozystack-scheduler - namespace: {{ .Release.Namespace }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cozystack-scheduler:volume-scheduler -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: system:volume-scheduler -subjects: - - kind: ServiceAccount - name: cozystack-scheduler - namespace: {{ .Release.Namespace }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: cozystack-scheduler -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cozystack-scheduler -subjects: - - kind: ServiceAccount - name: cozystack-scheduler - namespace: {{ .Release.Namespace }} diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/configmap.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/configmap.yaml deleted file mode 100644 index 24e0bc6f..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/configmap.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: cozystack-scheduler-config - namespace: {{ .Release.Namespace }} -data: - scheduler-config.yaml: | - apiVersion: kubescheduler.config.k8s.io/v1 - kind: KubeSchedulerConfiguration - leaderElection: - leaderElect: true - resourceNamespace: {{ .Release.Namespace }} - resourceName: cozystack-scheduler - profiles: - - schedulerName: cozystack-scheduler - plugins: - preFilter: - disabled: - - name: InterPodAffinity - - name: NodeAffinity - - name: PodTopologySpread - enabled: - - name: CozystackInterPodAffinity - - name: CozystackNodeAffinity - - name: CozystackPodTopologySpread - - name: CozystackSchedulingClass - filter: - disabled: - - name: InterPodAffinity - - name: NodeAffinity - - name: PodTopologySpread - enabled: - - name: CozystackInterPodAffinity - - name: CozystackNodeAffinity - - name: CozystackPodTopologySpread - - name: CozystackSchedulingClass - preScore: - disabled: - - name: InterPodAffinity - - name: NodeAffinity - - name: PodTopologySpread - enabled: - - name: CozystackInterPodAffinity - - name: CozystackNodeAffinity - - name: CozystackPodTopologySpread - score: - disabled: - - name: InterPodAffinity - - name: NodeAffinity - - name: PodTopologySpread - enabled: - - name: CozystackInterPodAffinity - - name: CozystackNodeAffinity - - name: CozystackPodTopologySpread - {{- with .Values.extenders }} - extenders: - {{- toYaml . | nindent 6 }} - {{- end }} diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/deployment.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/deployment.yaml deleted file mode 100644 index 0365f0de..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/deployment.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cozystack-scheduler - namespace: {{ .Release.Namespace }} -spec: - replicas: {{ .Values.replicas }} - selector: - matchLabels: - app: cozystack-scheduler - template: - metadata: - labels: - app: cozystack-scheduler - spec: - serviceAccountName: cozystack-scheduler - containers: - - name: cozystack-scheduler - image: {{ .Values.image }} - command: - - /cozystack-scheduler - - --config=/etc/kubernetes/scheduler-config.yaml - {{- with .Values.defaultLabelSelectorKeys }} - - --default-label-selector-keys={{ join "," . }} - {{- end }} - livenessProbe: - httpGet: - path: /healthz - port: 10259 - scheme: HTTPS - initialDelaySeconds: 15 - volumeMounts: - - name: config - mountPath: /etc/kubernetes/scheduler-config.yaml - subPath: scheduler-config.yaml - readOnly: true - volumes: - - name: config - configMap: - name: cozystack-scheduler-config diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/rolebinding.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/rolebinding.yaml deleted file mode 100644 index 796bf55c..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/rolebinding.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cozystack-scheduler:extension-apiserver-authentication-reader - namespace: kube-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: extension-apiserver-authentication-reader -subjects: - - kind: ServiceAccount - name: cozystack-scheduler - namespace: {{ .Release.Namespace }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: cozystack-scheduler:leader-election - namespace: {{ .Release.Namespace }} -rules: - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] - verbs: ["create", "get", "list", "update", "watch"] - - apiGroups: ["coordination.k8s.io"] - resources: ["leasecandidates"] - verbs: ["create", "get", "list", "update", "watch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: cozystack-scheduler:leader-election - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: cozystack-scheduler:leader-election -subjects: - - kind: ServiceAccount - name: cozystack-scheduler - namespace: {{ .Release.Namespace }} diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/serviceaccount.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/serviceaccount.yaml deleted file mode 100644 index 876e5f01..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/templates/serviceaccount.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: cozystack-scheduler - namespace: {{ .Release.Namespace }} diff --git a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/values.yaml b/packages/system/cozystack-scheduler/charts/cozystack-scheduler/values.yaml deleted file mode 100644 index 55b6faff..00000000 --- a/packages/system/cozystack-scheduler/charts/cozystack-scheduler/values.yaml +++ /dev/null @@ -1,23 +0,0 @@ -image: ghcr.io/cozystack/cozystack/cozystack-scheduler:v0.3.0@sha256:89c285c5c5fe3ed8d7d597acf32fc9f045394e0f8efafd1878d6080cf112f6c2 -replicas: 1 -# defaultLabelSelectorKeys overrides the pod label keys used to auto-populate -# nil LabelSelectors in SchedulingClass affinity and topology spread terms. -# When empty or unset, the binary defaults are used: -# - apps.cozystack.io/application.group -# - apps.cozystack.io/application.kind -# - apps.cozystack.io/application.name -# defaultLabelSelectorKeys: [] - -# extenders is a list of scheduler extenders to call during the scheduling cycle. -# Each entry is passed directly into KubeSchedulerConfiguration.extenders[]. -# Example: -# extenders: -# - urlPrefix: http://linstor-scheduler-extender.cozy-linstor.svc:8099 -# filterVerb: filter -# prioritizeVerb: prioritize -# weight: 5 -# enableHTTPS: false -# httpTimeout: 10s -# nodeCacheCapable: false -# ignorable: true -extenders: [] diff --git a/packages/system/cozystack-scheduler/templates/tenant-clusterroles.yaml b/packages/system/cozystack-scheduler/templates/tenant-clusterroles.yaml deleted file mode 100644 index a7b8fd21..00000000 --- a/packages/system/cozystack-scheduler/templates/tenant-clusterroles.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -# == schedulingclass view cluster role == -# Aggregated into cozy-tenant-view (and consequently use, admin, super-admin) -# Provides read-only access to SchedulingClass resources -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: cozy:schedulingclass:view - labels: - rbac.cozystack.io/aggregate-to-tenant-view: "true" -rules: -- apiGroups: ["cozystack.io"] - resources: - - schedulingclasses - verbs: - - get - - list - - watch diff --git a/packages/system/cozystack-scheduler/tests/configmap_test.yaml b/packages/system/cozystack-scheduler/tests/configmap_test.yaml deleted file mode 100644 index ce8f372d..00000000 --- a/packages/system/cozystack-scheduler/tests/configmap_test.yaml +++ /dev/null @@ -1,26 +0,0 @@ -suite: scheduler configmap tests - -templates: - - charts/cozy-cozystack-scheduler/templates/configmap.yaml - -tests: - - it: renders extenders when configured - values: - - ../values-linstor.yaml - asserts: - - isKind: - of: ConfigMap - - matchRegex: - path: data["scheduler-config.yaml"] - pattern: "urlPrefix: http://linstor-scheduler-extender" - - matchRegex: - path: data["scheduler-config.yaml"] - pattern: "ignorable: true" - - - it: omits extenders by default - asserts: - - isKind: - of: ConfigMap - - notMatchRegex: - path: data["scheduler-config.yaml"] - pattern: "extenders:" diff --git a/packages/system/cozystack-scheduler/values-linstor.yaml b/packages/system/cozystack-scheduler/values-linstor.yaml deleted file mode 100644 index ab16ca57..00000000 --- a/packages/system/cozystack-scheduler/values-linstor.yaml +++ /dev/null @@ -1,10 +0,0 @@ -cozy-cozystack-scheduler: - extenders: - - urlPrefix: http://linstor-scheduler-extender.cozy-linstor.svc:8099 - filterVerb: filter - prioritizeVerb: prioritize - weight: 5 - enableHTTPS: false - httpTimeout: 10s - nodeCacheCapable: false - ignorable: true diff --git a/packages/system/dashboard/images/openapi-ui-k8s-bff/Dockerfile b/packages/system/dashboard/images/openapi-ui-k8s-bff/Dockerfile index ea0c900d..ef698698 100644 --- a/packages/system/dashboard/images/openapi-ui-k8s-bff/Dockerfile +++ b/packages/system/dashboard/images/openapi-ui-k8s-bff/Dockerfile @@ -1,10 +1,9 @@ -# imported from https://github.com/PRO-Robotech/openapi-ui-k8s-bff +# imported from https://github.com/cozystack/openapi-ui-k8s-bff ARG NODE_VERSION=20.18.1 FROM node:${NODE_VERSION}-alpine AS builder WORKDIR /src -# release/1.4.0 -ARG COMMIT_REF=92e4b618eb9ad17b19827b5a2b7ceab33e8cf534 +ARG COMMIT_REF=183dc9dcbb0f8a1833dad642c35faa385c71e58d RUN wget -O- https://github.com/PRO-Robotech/openapi-ui-k8s-bff/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=1 ENV PATH=/src/node_modules/.bin:$PATH diff --git a/packages/system/dashboard/images/openapi-ui/Dockerfile b/packages/system/dashboard/images/openapi-ui/Dockerfile index 82cc6db0..f430f8e6 100644 --- a/packages/system/dashboard/images/openapi-ui/Dockerfile +++ b/packages/system/dashboard/images/openapi-ui/Dockerfile @@ -1,13 +1,12 @@ ARG NODE_VERSION=20.18.1 # openapi-k8s-toolkit -# imported from https://github.com/PRO-Robotech/openapi-k8s-toolkit +# imported from https://github.com/cozystack/openapi-k8s-toolkit FROM node:${NODE_VERSION}-alpine AS openapi-k8s-toolkit-builder RUN apk add git WORKDIR /src -# release/1.4.0 -ARG COMMIT=d6b9e4ad0d1eb9d3730f7f0c664792c8dda3214d -RUN wget -O- https://github.com/PRO-Robotech/openapi-k8s-toolkit/archive/${COMMIT}.tar.gz | tar -xzvf- --strip-components=1 +ARG COMMIT=cb2f122caafaa2fd5455750213d9e633017ec555 +RUN wget -O- https://github.com/cozystack/openapi-k8s-toolkit/archive/${COMMIT}.tar.gz | tar -xzvf- --strip-components=1 COPY openapi-k8s-toolkit/patches /patches RUN git apply /patches/*.diff @@ -18,13 +17,12 @@ RUN npm run build # openapi-ui -# imported from https://github.com/PRO-Robotech/openapi-ui +# imported from https://github.com/cozystack/openapi-ui FROM node:${NODE_VERSION}-alpine AS builder #RUN apk add git WORKDIR /src -# release/1.4.0 -ARG COMMIT_REF=6addca6939264ef2e39801baa88c1460cc1aa53e +ARG COMMIT_REF=3cfbbf2156b6a5e4a1f283a032019530c0c2d37d RUN wget -O- https://github.com/PRO-Robotech/openapi-ui/archive/${COMMIT_REF}.tar.gz | tar xzf - --strip-components=1 #COPY openapi-ui/patches /patches @@ -58,12 +56,5 @@ COPY --from=builder2 /src/node_modules /app/node_modules COPY --from=builder2 /src/build /app/build EXPOSE 8080 RUN sed -i -e 's|OpenAPI UI|Cozystack|g' build/index.html -# Fix Factory component: return null while loading instead of showing "Factory Not Found" 404 -RUN APP_JS=$(find build -name "App-react.js" -type f | head -1) && \ - if [ -n "$APP_JS" ]; then \ - sed -i 's|const { data: factoryData } = useK8sSmartResource({|const { data: factoryData, isLoading: factoryIsLoading } = useK8sSmartResource({|' "$APP_JS" && \ - sed -i '/Factory Not Found/s/return /return factoryIsLoading ? null : /' "$APP_JS" && \ - echo "Factory loading patch applied to $APP_JS"; \ - fi USER 1001 CMD ["node", "/app/build/index.js"] diff --git a/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff new file mode 100644 index 00000000..03212014 --- /dev/null +++ b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff @@ -0,0 +1,90 @@ +diff --git a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts +index 87a0f12..fb2e1cc 100644 +--- a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts ++++ b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts +@@ -134,22 +134,6 @@ export const prepare = ({ + // impossible in k8s + return {} + }) +- if (customFields.length > 0) { +- dataSource = dataSource.map((el: TJSON) => { +- const newFieldsForComplexJsonPath: Record = {} +- customFields.forEach(({ dataIndex, jsonPath }) => { +- const jpQueryResult = jp.query(el, `$${jsonPath}`) +- newFieldsForComplexJsonPath[dataIndex] = +- Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult +- }) +- if (typeof el === 'object') { +- return { ...el, ...newFieldsForComplexJsonPath } +- } +- // impossible in k8s +- return { ...newFieldsForComplexJsonPath } +- }) +- } +- + // Handle flatMap: expand rows for map objects + // Process all flatMap columns sequentially + if (flatMapColumns.length > 0 && dataSource) { +@@ -204,6 +188,62 @@ export const prepare = ({ + currentDataSource = expandedDataSource + }) + dataSource = currentDataSource ++ } ++ ++ if (customFields.length > 0) { ++ dataSource = dataSource.map((el: TJSON) => { ++ const newFieldsForComplexJsonPath: Record = {} ++ customFields.forEach(({ dataIndex, jsonPath }) => { ++ let fieldValue: TJSON = null ++ let handled = false ++ ++ const flatMapMatch = jsonPath.match(/^(.*)\[(_flatMap[^\]]+_Key)\](.*)$/) ++ if (flatMapMatch && el && typeof el === 'object' && !Array.isArray(el)) { ++ const basePath = flatMapMatch[1] ++ const keyField = flatMapMatch[2] ++ const tailPath = flatMapMatch[3] ++ const keyValue = (el as Record)[keyField] ++ if (keyValue !== null && keyValue !== undefined) { ++ const baseResult = jp.query(el, `$${basePath}`)[0] ++ if (baseResult && typeof baseResult === 'object' && !Array.isArray(baseResult)) { ++ const baseValue = (baseResult as Record)[String(keyValue)] ++ if (tailPath) { ++ const normalizedTailPath = ++ tailPath.startsWith('.') || tailPath.startsWith('[') ? tailPath : `.${tailPath}` ++ const tailResult = jp.query(baseValue, `$${normalizedTailPath}`) ++ fieldValue = Array.isArray(tailResult) && tailResult.length === 1 ? tailResult[0] : tailResult ++ } else { ++ fieldValue = baseValue as TJSON ++ } ++ handled = true ++ } ++ } ++ } ++ ++ if (!handled) { ++ let resolvedJsonPath = jsonPath ++ if (el && typeof el === 'object' && !Array.isArray(el)) { ++ resolvedJsonPath = jsonPath.replace(/\[(_flatMap[^\]]+_Key)\]/g, (match, keyField) => { ++ const keyValue = (el as Record)[keyField] ++ if (keyValue === null || keyValue === undefined) { ++ return match ++ } ++ const escaped = String(keyValue).replace(/'/g, "\\'") ++ return `['${escaped}']` ++ }) ++ } ++ const jpQueryResult = jp.query(el, `$${resolvedJsonPath}`) ++ fieldValue = Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult ++ } ++ ++ newFieldsForComplexJsonPath[dataIndex] = fieldValue ++ }) ++ if (typeof el === 'object') { ++ return { ...el, ...newFieldsForComplexJsonPath } ++ } ++ // impossible in k8s ++ return { ...newFieldsForComplexJsonPath } ++ }) + } + } else { + dataSource = dataItems.map((el: TJSON) => { diff --git a/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-unresolved-placeholder.diff b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-unresolved-placeholder.diff deleted file mode 100644 index e98861a3..00000000 --- a/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-unresolved-placeholder.diff +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts ---- a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts -+++ b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts -@@ -185,6 +185,11 @@ - return `['${escaped}']` - }) - } -- const jpQueryResult = jp.query(el, `$${resolvedJsonPath}`) -- fieldValue = Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult -+ if (/_flatMap[^\]]+_Key/.test(resolvedJsonPath)) { -+ // Placeholder was not resolved (row not yet expanded or key missing) — skip query -+ fieldValue = null -+ } else { -+ const jpQueryResult = jp.query(el, `$${resolvedJsonPath}`) -+ fieldValue = Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult -+ } - } diff --git a/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/formlistinput-allow-empty.diff b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/formlistinput-allow-empty.diff deleted file mode 100644 index 1c83df7c..00000000 --- a/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/formlistinput-allow-empty.diff +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/src/localTypes/formExtensions.ts b/src/localTypes/formExtensions.ts ---- a/src/localTypes/formExtensions.ts -+++ b/src/localTypes/formExtensions.ts -@@ -59,2 +59,4 @@ - relatedValuePath?: string -+ allowEmpty?: boolean -+ persistType?: 'str' | 'number' | 'arr' | 'obj' - } -diff --git a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx ---- a/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx -+++ b/src/components/molecules/BlackholeForm/molecules/FormListInput/FormListInput.tsx -@@ -149,3 +149,10 @@ - }, [relatedPath, form, arrName, fixedName, relatedFieldValue, onValuesChangeCallBack, isTouchedPeristed]) - -+ // When allowEmpty is set, auto-persist the field so the BFF preserves empty values -+ useEffect(() => { -+ if (customProps.allowEmpty) { -+ persistedControls.onPersistMark(persistName || name, customProps.persistType ?? 'str') -+ } -+ }, [customProps.allowEmpty, customProps.persistType, persistedControls, persistName, name]) -+ - const uri = prepareTemplate({ -@@ -267,5 +274,14 @@ - validateTrigger="onBlur" - hasFeedback={designNewLayout ? { icons: feedbackIcons } : true} - style={{ flex: 1 }} -+ normalize={(value: unknown) => { -+ if (customProps.allowEmpty && (value === undefined || value === null)) { -+ if (customProps.persistType === 'number') return 0 -+ if (customProps.persistType === 'arr') return [] -+ if (customProps.persistType === 'obj') return {} -+ return '' -+ } -+ return value -+ }} - > -