Compare commits
67 commits
main
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2eb484d8d4 | ||
|
|
5de17e5191 | ||
|
|
72efe285c9 | ||
|
|
3f3470a120 | ||
|
|
ddd452dcea | ||
|
|
208a9337ee | ||
|
|
50977618f5 | ||
|
|
718eb81b4b | ||
|
|
7d9e9107eb | ||
|
|
53a8ce6fd0 | ||
|
|
601b605f97 | ||
|
|
8364c25787 | ||
|
|
fe26737ede | ||
|
|
a81a3679d2 | ||
|
|
7880d55587 | ||
|
|
ae72c69c1c | ||
|
|
576e9ac5d7 | ||
|
|
82a833267e | ||
|
|
9910188c5a | ||
|
|
7fc6207fbc | ||
|
|
8c24435ee7 | ||
|
|
9fb1f79d7c | ||
|
|
890bb00e4b | ||
|
|
f961438c9d | ||
|
|
53d603f50c | ||
|
|
f7161c2af8 | ||
|
|
a33c143c2d | ||
|
|
002d3eb44c | ||
|
|
e77ee47e15 | ||
|
|
7780f50714 | ||
|
|
ec7cef8c69 | ||
|
|
bcdf308226 | ||
|
|
d5d4d86556 | ||
|
|
efc640103d | ||
|
|
d799731923 | ||
|
|
7fed9d4a42 | ||
|
|
01ef9f1223 | ||
|
|
e4fadb50dc | ||
|
|
736790852e | ||
|
|
6017dabaee | ||
|
|
ea641f7ec7 | ||
|
|
2c23f1fab6 | ||
|
|
2de20be50b | ||
|
|
1c87fe2004 | ||
|
|
a18047fc16 | ||
|
|
803d6b15ba | ||
|
|
c94768c64b | ||
|
|
093329cdce | ||
|
|
0e3c7fabff | ||
|
|
0ba129b4b7 | ||
|
|
095d3ab150 | ||
|
|
b06e2cecd5 | ||
|
|
b255214da0 | ||
|
|
4c9c68b7f5 | ||
|
|
002bd20f19 | ||
|
|
22c46d7271 | ||
|
|
dce757c884 | ||
|
|
109b4a333e | ||
|
|
4dada99a92 | ||
|
|
fd18a699b9 | ||
|
|
532669ad61 | ||
|
|
116e1baf63 | ||
|
|
52b4a0a7c6 | ||
|
|
0b4f3c7d30 | ||
|
|
ccb37d3fac | ||
|
|
89d90cac2d | ||
|
|
4f9a035c5b |
803 changed files with 52823 additions and 80338 deletions
|
|
@ -1,5 +0,0 @@
|
|||
reviews:
|
||||
auto_review:
|
||||
enabled: true
|
||||
auto_incremental_review: true
|
||||
drafts: false
|
||||
|
|
@ -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
|
||||
|
|
@ -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/<name>/patches/` applied by the Makefile.
|
||||
- For source-code changes in images: suggest a patch in `packages/<name>/images/<name>/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 `<package-name>` 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/`.
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
|
@ -1 +1 @@
|
|||
* @kvaps @lllamnyp @lexfrei @androndo @IvanHunters @sircthulhu @myasnikovdaniil
|
||||
* @kvaps @lllamnyp @lexfrei @androndo @IvanHunters @sircthulhu
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
labels: 'kind/bug'
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
|
|
|||
20
.github/PULL_REQUEST_TEMPLATE.md
vendored
20
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -1,11 +1,8 @@
|
|||
<!-- Thank you for making a contribution! Here are some tips for you:
|
||||
- Use Conventional Commits for the PR title: `type(scope): description`
|
||||
- Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore
|
||||
- Scopes are not an exhaustive list — pick the most specific scope for the change and extend the list when a genuinely new area appears. Examples:
|
||||
- System components: dashboard, platform, operator, cilium, kube-ovn, linstor, fluxcd, cluster-api
|
||||
- Managed apps: postgres, mariadb, redis, kafka, clickhouse, virtual-machine, kubernetes
|
||||
- Development and maintenance: api, hack, tests, ci, docs, maintenance
|
||||
- Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer
|
||||
- Start the PR title with the [label] of Cozystack component:
|
||||
- For system components: [platform], [system], [linstor], [cilium], [kube-ovn], [dashboard], [cluster-api], etc.
|
||||
- For managed apps: [apps], [tenant], [kubernetes], [postgres], [virtual-machine] etc.
|
||||
- For development and maintenance: [tests], [ci], [docs], [maintenance].
|
||||
- If it's a work in progress, consider creating this PR as a draft.
|
||||
- Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft.
|
||||
- Add the label `backport` if it's a bugfix that needs to be backported to a previous version.
|
||||
|
|
@ -14,19 +11,14 @@
|
|||
## What this PR does
|
||||
|
||||
|
||||
### Screenshots
|
||||
|
||||
<!-- REQUIRED for UI changes: attach screenshots or screen recordings demonstrating
|
||||
the visual impact of your changes. PRs with UI changes without screenshots will not be merged. -->
|
||||
|
||||
### Release note
|
||||
|
||||
<!-- Write a release note:
|
||||
- Explain what has changed internally and for users.
|
||||
- Start with the same `type(scope):` prefix as in the PR title
|
||||
- Start with the same [label] as in the PR title
|
||||
- Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
|
||||
-->
|
||||
|
||||
```release-note
|
||||
|
||||
[]
|
||||
```
|
||||
371
.github/labels.yml
vendored
371
.github/labels.yml
vendored
|
|
@ -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
|
||||
61
.github/workflows/codegen-drift.yml
vendored
61
.github/workflows/codegen-drift.yml
vendored
|
|
@ -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
|
||||
84
.github/workflows/labels.yaml
vendored
84
.github/workflows/labels.yaml
vendored
|
|
@ -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
|
||||
206
.github/workflows/pr-labeler.yaml
vendored
206
.github/workflows/pr-labeler.yaml
vendored
|
|
@ -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(', ')}`);
|
||||
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
|
|
@ -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: |
|
||||
|
|
|
|||
23
.github/workflows/pull-requests.yaml
vendored
23
.github/workflows/pull-requests.yaml
vendored
|
|
@ -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
|
||||
|
|
@ -159,7 +145,6 @@ jobs:
|
|||
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-32cpu-128gb-x86-64]
|
||||
timeout-minutes: 120
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
|
|
|||
142
.github/workflows/tags.yaml
vendored
142
.github/workflows/tags.yaml
vendored
|
|
@ -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
|
||||
|
|
@ -131,6 +129,7 @@ jobs:
|
|||
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"
|
||||
git push origin HEAD || true
|
||||
|
||||
# Tag the api/apps/v1alpha1 submodule for pkg.go.dev
|
||||
- name: Tag API submodule
|
||||
|
|
@ -223,7 +222,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
|
||||
});
|
||||
|
|
@ -255,21 +254,6 @@ jobs:
|
|||
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
|
||||
|
|
@ -318,59 +302,50 @@ jobs:
|
|||
|
||||
- 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 }}
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
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." \
|
||||
copilot --prompt "prepare changelog file for tagged release v${{ steps.tag.outputs.version }}, use @docs/agents/changelog.md for it. Create the changelog file at docs/changelogs/v${{ steps.tag.outputs.version }}.md" \
|
||||
--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"
|
||||
git remote set-url origin https://x-access-token:${APP_TOKEN}@github.com/${GITHUB_REPOSITORY}
|
||||
|
||||
CHANGELOG_FILE="docs/changelogs/v${{ steps.tag.outputs.version }}.md"
|
||||
CHANGELOG_BRANCH="changelog-v${{ steps.tag.outputs.version }}"
|
||||
|
||||
if [ -f "$CHANGELOG_FILE" ]; then
|
||||
# Fetch latest main branch
|
||||
git fetch origin main
|
||||
|
||||
# Delete local branch if it exists
|
||||
git branch -D "$CHANGELOG_BRANCH" 2>/dev/null || true
|
||||
|
||||
# Create and checkout new branch from main
|
||||
git checkout -b "$CHANGELOG_BRANCH" origin/main
|
||||
|
||||
# Add and commit changelog
|
||||
git add "$CHANGELOG_FILE"
|
||||
if git diff --staged --quiet; then
|
||||
echo "⚠️ No changes to commit (file may already be committed)"
|
||||
else
|
||||
git commit -m "docs: add changelog for v${{ steps.tag.outputs.version }}" -s
|
||||
echo "✅ Changelog committed to branch $CHANGELOG_BRANCH"
|
||||
fi
|
||||
|
||||
# Push the branch (force push to update if it exists)
|
||||
git push -f origin "$CHANGELOG_BRANCH"
|
||||
else
|
||||
echo "⚠️ Changelog file was not generated"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create PR for changelog
|
||||
if: steps.check_changelog.outputs.exists == 'false'
|
||||
|
|
@ -411,7 +386,7 @@ jobs:
|
|||
repo: context.repo.repo,
|
||||
head: changelogBranch,
|
||||
base: baseBranch,
|
||||
title: `docs(release): add changelog for v${version}`,
|
||||
title: `docs: 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
|
||||
});
|
||||
|
|
@ -421,7 +396,7 @@ jobs:
|
|||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.data.number,
|
||||
labels: ['kind/documentation', 'automated']
|
||||
labels: ['documentation', 'automated']
|
||||
});
|
||||
|
||||
console.log(`Created PR #${pr.data.number} for changelog`);
|
||||
|
|
@ -465,58 +440,17 @@ jobs:
|
|||
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"
|
||||
run: make update-all BRANCH=release-${{ steps.tag.outputs.version }} RELEASE_TAG=${{ steps.tag.outputs.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
|
||||
git add content
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
|
|
|
|||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -80,7 +80,3 @@ fabric.properties
|
|||
**/.DS_Store
|
||||
|
||||
tmp/
|
||||
|
||||
# build revision marker (generated by make image-packages)
|
||||
packages/core/platform/.build-revision
|
||||
.claude/
|
||||
|
|
|
|||
|
|
@ -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: |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
47
Makefile
47
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
|
||||
|
||||
|
|
@ -22,13 +22,11 @@ build: build-deps
|
|||
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/bucket image
|
||||
make -C packages/system/objectstorage-controller image
|
||||
make -C packages/system/grafana-operator image
|
||||
|
|
@ -60,11 +58,7 @@ manifests:
|
|||
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 +77,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
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@
|
|||
[](https://cozystack.io/support/)
|
||||
[](https://github.com/cozystack/cozystack)
|
||||
[](https://github.com/cozystack/cozystack/releases/latest)
|
||||
[](https://github.com/cozystack/cozystack/graphs/contributors)
|
||||
[](https://www.bestpractices.dev/projects/10177)
|
||||
[](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/).
|
||||
|
||||
|
|
|
|||
102
SECURITY.md
102
SECURITY.md
|
|
@ -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:
|
||||
|
||||
<https://github.com/cozystack/cozystack/releases>
|
||||
|
||||
## 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: <https://github.com/cozystack/cozystack/releases>
|
||||
- project changelogs in this repository
|
||||
- the Cozystack website and documentation: <https://cozystack.io>
|
||||
|
||||
## 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.
|
||||
|
|
@ -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"`
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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:="<password>"
|
||||
ResticPassword string `json:"resticPassword"`
|
||||
// Access key for S3 authentication.
|
||||
// +kubebuilder:default:="<your-access-key>"
|
||||
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:="<your-secret-key>"
|
||||
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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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=
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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 <ip:port>.
|
||||
// +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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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 `<cluster-name>.<tenant-host>` 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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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:="<password>"
|
||||
ResticPassword string `json:"resticPassword"`
|
||||
// Access key for S3 authentication.
|
||||
// +kubebuilder:default:="<your-access-key>"
|
||||
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:="<your-secret-key>"
|
||||
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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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:="<your-access-key>"
|
||||
S3AccessKey string `json:"s3AccessKey,omitempty"`
|
||||
// Secret key for S3 authentication.
|
||||
// +kubebuilder:default:="<your-secret-key>"
|
||||
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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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"`
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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 {
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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"`
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -176,15 +176,6 @@ func main() {
|
|||
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")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// +kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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": {}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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": {}
|
||||
}
|
||||
|
|
@ -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": {}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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<version>.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<version>.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 <PR_NUMBER> --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 <PR_NUMBER> --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<version>.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<version>.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 <PR_NUMBER> --repo cozystack/<repo> --json author --jq .author.login` to get PR author (not commit author)
|
||||
|
|
@ -655,7 +637,7 @@ Save the changelog to file `docs/changelogs/v<version>.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
|
||||
|
|
|
|||
|
|
@ -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)/<name>/README.md` — regenerated by `cozyvalues-gen` (parameter table, formatting).
|
||||
- `packages/(apps|extra)/<name>/values.schema.json` — `cozyvalues-gen` rewrites ordering and derived fields.
|
||||
- `packages/system/<name>-rd/cozyrds/<name>.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/<apps-or-extra>/<name> generate
|
||||
git add packages/<apps-or-extra>/<name>/ packages/system/<name>-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]`, `[mariadb]`, `[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 <noreply@anthropic.com>
|
||||
Assisted-By: GPT-5 <noreply@openai.com>
|
||||
Assisted-By: Gemini <noreply@google.com>
|
||||
```
|
||||
|
||||
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 <your-commit-hash>
|
||||
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 <branch-name>
|
||||
```
|
||||
|
||||
Create the PR with `gh pr create --title "type(scope): brief description" --body-file <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 <PR-number> --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=<PR_NUMBER> -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=<PR_NUMBER> -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 <number> --body "new description"`
|
||||
|
|
|
|||
|
|
@ -78,18 +78,11 @@ packages/<category>/<package-name>/
|
|||
- 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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.0.4
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.0.5
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.0.6
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.0.7
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.1.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=<type>` 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
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.1.1
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.1.2
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[bucket] Fix S3 Manager endpoint mismatch with COSI credentials**: The S3 Manager UI previously constructed an `s3.<tenant>.<cluster-domain>` 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
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.1.3
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.1.4
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.1.5
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.1.6
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.2.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
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.2.1
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.2.2
|
||||
-->
|
||||
|
||||
## 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
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.2.3
|
||||
-->
|
||||
|
||||
# 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
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.3.0-rc.1
|
||||
-->
|
||||
|
||||
# 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
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.3.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
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v1.3.1
|
||||
-->
|
||||
|
||||
# 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+<git-hash>` (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
|
||||
|
|
@ -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
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue