mirror of
https://github.com/cozystack/cozystack.git
synced 2026-03-03 13:38:56 +00:00
Compare commits
178 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80ad9965e5 | ||
|
|
523510469c | ||
|
|
cf5b2f2bbb | ||
|
|
4e5343e36c | ||
|
|
d8237b4321 | ||
|
|
83c3b0ca12 | ||
|
|
e1590aad1b | ||
|
|
304338d697 | ||
|
|
b65d639ecb | ||
|
|
339e71331f | ||
|
|
08be385665 | ||
|
|
2f0657f8ba | ||
|
|
a64ba184ce | ||
|
|
00328c8a31 | ||
|
|
7009c8da37 | ||
|
|
63db8ca009 | ||
|
|
369384f5ec | ||
|
|
4278692763 | ||
|
|
edc942b6c1 | ||
|
|
4c71e7fe57 | ||
|
|
627022972d | ||
|
|
1e8a9ee980 | ||
|
|
b45f4a6545 | ||
|
|
5b96190be8 | ||
|
|
8849570f74 | ||
|
|
b6958320b2 | ||
|
|
0a210bf5d3 | ||
|
|
90d50fef48 | ||
|
|
19ed058897 | ||
|
|
6438ce98b1 | ||
|
|
523d8ea638 | ||
|
|
e89896fdba | ||
|
|
ab5101a713 | ||
|
|
af460f1c41 | ||
|
|
634649f9ec | ||
|
|
df782fec9c | ||
|
|
172774b6cd | ||
|
|
62119eb761 | ||
|
|
48c6e23ca0 | ||
|
|
9064a72c92 | ||
|
|
dc06b16d11 | ||
|
|
739a74dc28 | ||
|
|
723eefea66 | ||
|
|
1d10907168 | ||
|
|
c19cddf08e | ||
|
|
4c08caafe1 | ||
|
|
be58047aba | ||
|
|
f60e2555c9 | ||
|
|
6443a1264e | ||
|
|
52a23eacfc | ||
|
|
2634b01465 | ||
|
|
15a3636d5f | ||
|
|
ef43ef6753 | ||
|
|
ba804b7c52 | ||
|
|
9c5abf49ca | ||
|
|
10e79651ef | ||
|
|
965818efd4 | ||
|
|
b1ebc9cc85 | ||
|
|
667c778f27 | ||
|
|
77d95e3b91 | ||
|
|
a8d3cbce82 | ||
|
|
eea685065a | ||
|
|
480f8027d7 | ||
|
|
19b56414a6 | ||
|
|
0f9806e9b0 | ||
|
|
177073596c | ||
|
|
93a9241899 | ||
|
|
5401ae9734 | ||
|
|
b78d97f374 | ||
|
|
8b95db06ee | ||
|
|
5a2d4d7e66 | ||
|
|
42e6f0e3f2 | ||
|
|
e2eb1e267b | ||
|
|
2ac533f2f6 | ||
|
|
ae9f9c57b1 | ||
|
|
18f253f77a | ||
|
|
bd9dcb52a3 | ||
|
|
be473a12be | ||
|
|
8f5adcccf5 | ||
|
|
08bd918a10 | ||
|
|
023276ebab | ||
|
|
19c4674ebb | ||
|
|
202da193c0 | ||
|
|
cc9687707c | ||
|
|
ac10e35272 | ||
|
|
fc7d5ee71f | ||
|
|
9d90503fb7 | ||
|
|
4be1c257d6 | ||
|
|
f3ba8eca8e | ||
|
|
0f286ee7ba | ||
|
|
5acf62824a | ||
|
|
93e33a0921 | ||
|
|
c4fa795491 | ||
|
|
f93042499b | ||
|
|
7cbe564ff1 | ||
|
|
62ff0c0b39 | ||
|
|
198b30887a | ||
|
|
9632772337 | ||
|
|
992c7d54fe | ||
|
|
4e3c8eafa1 | ||
|
|
05cd1a1c82 | ||
|
|
ee1c83ec85 | ||
|
|
1f784db3f7 | ||
|
|
f4e0145c1c | ||
|
|
efd96877ab | ||
|
|
5a20693d67 | ||
|
|
448fc61570 | ||
|
|
dc0eebd81e | ||
|
|
a545ff3781 | ||
|
|
82cebe3ad7 | ||
|
|
184441d82f | ||
|
|
ebbc76582c | ||
|
|
8e57ac487e | ||
|
|
766f6e9a9e | ||
|
|
ea74d7d59a | ||
|
|
74262977f6 | ||
|
|
d1fa0e6586 | ||
|
|
3e41504b2d | ||
|
|
06f68d28d9 | ||
|
|
21de4f7584 | ||
|
|
840c264e86 | ||
|
|
bbb92ba497 | ||
|
|
b163a5913f | ||
|
|
ba8a9cc1f7 | ||
|
|
b858745cdd | ||
|
|
d9d6fa1a5a | ||
|
|
9e635fcc3f | ||
|
|
2791e3e96a | ||
|
|
1a977bd4b4 | ||
|
|
10516c38ec | ||
|
|
1e36722ab8 | ||
|
|
d57f9acc7a | ||
|
|
466f0fed52 | ||
|
|
c1edc5d711 | ||
|
|
354507a4ea | ||
|
|
a9c2bfb33b | ||
|
|
85c9da58de | ||
|
|
b1d5de1006 | ||
|
|
af96e3da94 | ||
|
|
bf1ece5f7c | ||
|
|
c3f70abc99 | ||
|
|
ea85856b1a | ||
|
|
e9bdbcf60d | ||
|
|
43ec8f0877 | ||
|
|
1f0edc5f79 | ||
|
|
fe8ec75ac7 | ||
|
|
671e13df70 | ||
|
|
36df9bda05 | ||
|
|
2a82273902 | ||
|
|
bb8f2047bf | ||
|
|
2a508c4f29 | ||
|
|
a4cbc7341d | ||
|
|
fdc2b8f3ec | ||
|
|
e6070210f6 | ||
|
|
e1e9eef63b | ||
|
|
f2a8e2d45d | ||
|
|
1a49cbef2d | ||
|
|
346dce83d4 | ||
|
|
4d8dca8049 | ||
|
|
7a19215f0a | ||
|
|
2d9dc9fe01 | ||
|
|
d86742eb36 | ||
|
|
857416d1d2 | ||
|
|
6bd7d3add5 | ||
|
|
2fcf975e6a | ||
|
|
b7bebecb64 | ||
|
|
edc12e3f7e | ||
|
|
27b06f4fbd | ||
|
|
3f6888a470 | ||
|
|
1a4e979e63 | ||
|
|
a3be02132d | ||
|
|
c6ec3168f7 | ||
|
|
5b58ec5cdd | ||
|
|
7e622181ed | ||
|
|
bf38316163 | ||
|
|
1475196437 | ||
|
|
076d69a10b | ||
|
|
5654ac4e3d |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -1 +1 @@
|
||||
* @kvaps @lllamnyp @klinch0
|
||||
* @kvaps @lllamnyp @nbykov0
|
||||
|
||||
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/v0.9.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.5/cozyvalues-gen-linux-amd64.tar.gz | tar -xzvf- -C /usr/local/bin/ cozyvalues-gen
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
run: |
|
||||
|
||||
3
.github/workflows/pull-requests.yaml
vendored
3
.github/workflows/pull-requests.yaml
vendored
@@ -1,7 +1,8 @@
|
||||
name: Pull Request
|
||||
|
||||
env:
|
||||
REGISTRY: ${{ vars.OCIR_REPO }}
|
||||
# TODO: unhardcode this
|
||||
REGISTRY: iad.ocir.io/idyksih5sir9/cozystack
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
@@ -31,4 +31,5 @@ This list is sorted in chronological order, based on the submission date.
|
||||
| [gohost](https://gohost.kz/) | @karabass_off | 2024-02-01 | Our company has been working in the market of Kazakhstan for more than 15 years, providing clients with a standard set of services: VPS/VDC, IaaS, shared hosting, etc. Now we are expanding the lineup by introducing Bare Metal Kubenetes cluster under Cozystack management. |
|
||||
| [Urmanac](https://urmanac.com) | @kingdonb | 2024-12-04 | Urmanac is the future home of a hosting platform for the knowledge base of a community of personal server enthusiasts. We use Cozystack to provide support services for web sites hosted using both conventional deployments and on SpinKube, with WASM. |
|
||||
| [Hidora](https://hikube.cloud) | @matthieu-robin | 2025-09-17 | Hidora is a Swiss cloud provider delivering managed services and infrastructure solutions through datacenters located in Switzerland, ensuring data sovereignty and reliability. Its sovereign cloud platform, Hikube, is designed to run workloads with high availability across multiple datacenters, providing enterprises with a secure and scalable foundation for their applications based on Cozystack. |
|
||||
|
|
||||
| [QOSI](https://qosi.kz) | @tabu-a | 2025-10-04 | QOSI is a non-profit organization driving open-source adoption and digital sovereignty across Kazakhstan and Central Asia. We use Cozystack as a platform for deploying sovereign, GPU-enabled clouds and educational environments under the National AI Program. Our goal is to accelerate the region’s transition toward open, self-hosted cloud-native technologies |
|
||||
|
|
||||
1
Makefile
1
Makefile
@@ -15,6 +15,7 @@ build: build-deps
|
||||
make -C packages/extra/monitoring image
|
||||
make -C packages/system/cozystack-api image
|
||||
make -C packages/system/cozystack-controller image
|
||||
make -C packages/system/lineage-controller-webhook image
|
||||
make -C packages/system/cilium image
|
||||
make -C packages/system/kubeovn image
|
||||
make -C packages/system/kubeovn-webhook image
|
||||
|
||||
@@ -39,7 +39,6 @@ import (
|
||||
cozystackiov1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
"github.com/cozystack/cozystack/internal/controller"
|
||||
"github.com/cozystack/cozystack/internal/controller/dashboard"
|
||||
lcw "github.com/cozystack/cozystack/internal/lineagecontrollerwebhook"
|
||||
"github.com/cozystack/cozystack/internal/telemetry"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2"
|
||||
@@ -70,6 +69,7 @@ func main() {
|
||||
var telemetryEndpoint string
|
||||
var telemetryInterval string
|
||||
var cozystackVersion string
|
||||
var reconcileDeployment bool
|
||||
var tlsOpts []func(*tls.Config)
|
||||
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
|
||||
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
|
||||
@@ -89,6 +89,8 @@ func main() {
|
||||
"Interval between telemetry data collection (e.g. 15m, 1h)")
|
||||
flag.StringVar(&cozystackVersion, "cozystack-version", "unknown",
|
||||
"Version of Cozystack")
|
||||
flag.BoolVar(&reconcileDeployment, "reconcile-deployment", false,
|
||||
"If set, the Cozystack API server is assumed to run as a Deployment, else as a DaemonSet.")
|
||||
opts := zap.Options{
|
||||
Development: false,
|
||||
}
|
||||
@@ -214,25 +216,25 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cozyAPIKind := "DaemonSet"
|
||||
if reconcileDeployment {
|
||||
cozyAPIKind = "Deployment"
|
||||
}
|
||||
if err = (&controller.CozystackResourceDefinitionReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
CozystackAPIKind: cozyAPIKind,
|
||||
}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "CozystackResourceDefinitionReconciler")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// special one that's both a webhook and a reconciler
|
||||
lineageControllerWebhook := &lcw.LineageControllerWebhook{
|
||||
dashboardManager := &dashboard.Manager{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsController(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup controller", "controller", "LineageController")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsWebhook(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup webhook", "webhook", "LineageWebhook")
|
||||
if err = dashboardManager.SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "DashboardReconciler")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -261,7 +263,9 @@ func main() {
|
||||
}
|
||||
|
||||
setupLog.Info("starting manager")
|
||||
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||
ctx := ctrl.SetupSignalHandler()
|
||||
dashboardManager.InitializeStaticResources(ctx)
|
||||
if err := mgr.Start(ctx); err != nil {
|
||||
setupLog.Error(err, "problem running manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
179
cmd/lineage-controller-webhook/main.go
Normal file
179
cmd/lineage-controller-webhook/main.go
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
Copyright 2025.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
||||
// to ensure that exec-entrypoint and run can make use of them.
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
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/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
|
||||
cozystackiov1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
lcw "github.com/cozystack/cozystack/internal/lineagecontrollerwebhook"
|
||||
// +kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
var (
|
||||
scheme = runtime.NewScheme()
|
||||
setupLog = ctrl.Log.WithName("setup")
|
||||
)
|
||||
|
||||
func init() {
|
||||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
|
||||
utilruntime.Must(cozystackiov1alpha1.AddToScheme(scheme))
|
||||
// +kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
func main() {
|
||||
var metricsAddr string
|
||||
var enableLeaderElection bool
|
||||
var probeAddr string
|
||||
var secureMetrics bool
|
||||
var enableHTTP2 bool
|
||||
var tlsOpts []func(*tls.Config)
|
||||
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
|
||||
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
|
||||
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
|
||||
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
|
||||
"Enable leader election for controller manager. "+
|
||||
"Enabling this will ensure there is only one active controller manager.")
|
||||
flag.BoolVar(&secureMetrics, "metrics-secure", true,
|
||||
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
|
||||
flag.BoolVar(&enableHTTP2, "enable-http2", false,
|
||||
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
|
||||
opts := zap.Options{
|
||||
Development: false,
|
||||
}
|
||||
opts.BindFlags(flag.CommandLine)
|
||||
flag.Parse()
|
||||
|
||||
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
|
||||
|
||||
// if the enable-http2 flag is false (the default), http/2 should be disabled
|
||||
// due to its vulnerabilities. More specifically, disabling http/2 will
|
||||
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
|
||||
// Rapid Reset CVEs. For more information see:
|
||||
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
|
||||
// - https://github.com/advisories/GHSA-4374-p667-p6c8
|
||||
disableHTTP2 := func(c *tls.Config) {
|
||||
setupLog.Info("disabling http/2")
|
||||
c.NextProtos = []string{"http/1.1"}
|
||||
}
|
||||
|
||||
if !enableHTTP2 {
|
||||
tlsOpts = append(tlsOpts, disableHTTP2)
|
||||
}
|
||||
|
||||
webhookServer := webhook.NewServer(webhook.Options{
|
||||
TLSOpts: tlsOpts,
|
||||
})
|
||||
|
||||
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
|
||||
// More info:
|
||||
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/server
|
||||
// - https://book.kubebuilder.io/reference/metrics.html
|
||||
metricsServerOptions := metricsserver.Options{
|
||||
BindAddress: metricsAddr,
|
||||
SecureServing: secureMetrics,
|
||||
TLSOpts: tlsOpts,
|
||||
}
|
||||
|
||||
if secureMetrics {
|
||||
// FilterProvider is used to protect the metrics endpoint with authn/authz.
|
||||
// These configurations ensure that only authorized users and service accounts
|
||||
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
|
||||
// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/filters#WithAuthenticationAndAuthorization
|
||||
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
|
||||
|
||||
// TODO(user): If CertDir, CertName, and KeyName are not specified, controller-runtime will automatically
|
||||
// generate self-signed certificates for the metrics server. While convenient for development and testing,
|
||||
// this setup is not recommended for production.
|
||||
}
|
||||
|
||||
// Configure rate limiting for the Kubernetes client
|
||||
config := ctrl.GetConfigOrDie()
|
||||
config.QPS = 50.0 // Increased from default 5.0
|
||||
config.Burst = 100 // Increased from default 10
|
||||
|
||||
mgr, err := ctrl.NewManager(config, ctrl.Options{
|
||||
Scheme: scheme,
|
||||
Metrics: metricsServerOptions,
|
||||
WebhookServer: webhookServer,
|
||||
HealthProbeBindAddress: probeAddr,
|
||||
LeaderElection: enableLeaderElection,
|
||||
LeaderElectionID: "8796f12d.cozystack.io",
|
||||
// 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
|
||||
// speeds up voluntary leader transitions as the new leader don't have to wait
|
||||
// LeaseDuration time first.
|
||||
//
|
||||
// In the default scaffold provided, the program ends immediately after
|
||||
// the manager stops, so would be fine to enable this option. However,
|
||||
// if you are doing or is intended to do any operation such as perform cleanups
|
||||
// after the manager stops then its usage might be unsafe.
|
||||
// LeaderElectionReleaseOnCancel: true,
|
||||
})
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to start manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lineageControllerWebhook := &lcw.LineageControllerWebhook{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsController(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup controller", "controller", "LineageController")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := lineageControllerWebhook.SetupWithManagerAsWebhook(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup webhook", "webhook", "LineageWebhook")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// +kubebuilder:scaffold:builder
|
||||
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up health check")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up ready check")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
setupLog.Info("starting manager")
|
||||
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||
setupLog.Error(err, "problem running manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
18
docs/changelogs/patch-template.md
Normal file
18
docs/changelogs/patch-template.md
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0..
|
||||
-->
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
## Security
|
||||
|
||||
## Fixes
|
||||
|
||||
## Dependencies
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.36.0...main
|
||||
@@ -17,4 +17,4 @@ https://github.com/cozystack/cozystack/releases/tag/v0..
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: **Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.34.0...v0.35.0
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.34.0...v0.35.0
|
||||
|
||||
3
docs/changelogs/unreleased.md
Normal file
3
docs/changelogs/unreleased.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Changes after v0.37.0
|
||||
|
||||
* [lineage] Break webhook out into a separate daemonset. Reduce unnecessary webhook calls by marking handled resources and excluding them from consideration by the webhook's object selector (@lllamnyp in #1515).
|
||||
10
docs/changelogs/v0.35.3.md
Normal file
10
docs/changelogs/v0.35.3.md
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.35.3
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* [seaweedfs] Add a liveness check for the SeaweedFS S3 endpoint to improve health monitoring and enable automatic recovery. (@IvanHunters in https://github.com/cozystack/cozystack/pull/1368)
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.35.2...v0.35.3
|
||||
14
docs/changelogs/v0.35.4.md
Normal file
14
docs/changelogs/v0.35.4.md
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.35.4
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* [virtual-machine] Fix the regression in VM update hook introduced in https://github.com/cozystack/cozystack/pull/1169 by targeting the correct API resource and avoiding conflicts with KubeVirt resources. (@kvaps in https://github.com/cozystack/cozystack/pull/1376, backported in https://github.com/cozystack/cozystack/pull/1377)
|
||||
* [cozy-lib] Add the missing template `cozy-lib.resources.flatten`. (@kvaps in https://github.com/cozystack/cozystack/pull/1372, backported in https://github.com/cozystack/cozystack/pull/1375)
|
||||
* [platform] Fix a boolean override bug in Helm merge. ConfigMap values now correctly take precedence over bundle defaults. (@dyudin0821 in https://github.com/cozystack/cozystack/pull/1385, backported in https://github.com/cozystack/cozystack/pull/1388)
|
||||
* [seaweedfs] Resolve connectivity issues in SeaweedFS. Increase Nginx ingress timeouts for SeaweedFS S3 endpoint. (@kvaps in https://github.com/cozystack/cozystack/pull/1386, backported in https://github.com/cozystack/cozystack/pull/1390)
|
||||
* [dx] Remove the BUILDER and PLATFORM autodetect logic in Makefiles. (@kvaps in https://github.com/cozystack/cozystack/pull/1391, backported in https://github.com/cozystack/cozystack/pull/1392)
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.35.3...v0.35.4
|
||||
11
docs/changelogs/v0.35.5.md
Normal file
11
docs/changelogs/v0.35.5.md
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.35.5
|
||||
-->
|
||||
|
||||
## Fixes
|
||||
|
||||
* [etcd] Ensure that TopologySpreadConstraints consistently target etcd pods. (@kvaps in https://github.com/cozystack/cozystack/pull/1405, backported in https://github.com/cozystack/cozystack/pull/1406)
|
||||
* [tests] Add resource quota for testing namespaces. (@IvanHunters in https://github.com/cozystack/cozystack/commit/4982cdf5024c8bb9aa794b91d55545ea6b105d17)
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.35.4...v0.35.5
|
||||
117
docs/changelogs/v0.36.0.md
Normal file
117
docs/changelogs/v0.36.0.md
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.36.0
|
||||
-->
|
||||
|
||||
|
||||
## Feature Highlights
|
||||
|
||||
Release v0.36.0 focuses on the stability, observability, and flexible configuration of managed applications.
|
||||
|
||||
### Per-Namespace Resource Limits for Tenants
|
||||
|
||||
Resource management for Cozystack tenants has received a final patch and is now graduated to a stable feature.
|
||||
Platform administrators can define explicit CPU, memory, and storage limits for each tenant's namespace
|
||||
via the tenant specification.
|
||||
This prevents any single tenant from consuming more than their share of cluster resources,
|
||||
ensuring cluster stability and a guaranteed service level for each tenant.
|
||||
|
||||
### Kube-OVN Cluster Health Monitor
|
||||
|
||||
A new component called the Kube-OVN Plunger continuously monitors the health of the Kube-OVN network's central control cluster.
|
||||
This external agent gathers OVN cluster status and consensus information, exposing Prometheus metrics and live events stream via SSE.
|
||||
As a result, it provides much better visibility of the virtual network layer and helps maintain a reliable and observable network in Cozystack.
|
||||
This change opens the road to automated Kube-OVN database operations and recovery in specific corner cases.
|
||||
|
||||
### Configurable CoreDNS Addon for Kubernetes
|
||||
|
||||
Cozystack introduces a dedicated CoreDNS addon for managing cluster DNS with greater flexibility.
|
||||
CoreDNS is now deployed via a Helm chart and can be tuned through custom values in the cluster specification,
|
||||
including autoscaling, replica count, and adjusting service IP.
|
||||
CoreDNS can now be configured in the dashboard and using Cozystack API.
|
||||
|
||||
### Granular SeaweedFS Service Configuration
|
||||
|
||||
The SeaweedFS S3 storage service in Cozystack is now far more configurable at a component level.
|
||||
The Helm chart for SeaweedFS now includes independent configuration for each component and its resources.
|
||||
It includes the master nodes, volume servers with support for multiple zones, filers, the backing database, and the S3 gateway.
|
||||
Administrators can set per-component parameters such as the number of replicas, available CPU, memory, and storage size.
|
||||
|
||||
### Server-side Encryption for S3
|
||||
|
||||
Cozystack v0.36.0 includes SeaweedFS 3.97, bringing support for server-side encryption of S3 buckets (SSE-C, SSE-KMS, and SSE-S3).
|
||||
|
||||
**Breaking change:** upon updating Cozystack, SeaweedFS will be updated to a newer version, and the services specification
|
||||
will be converted to the new format.
|
||||
|
||||
### Custom Resource Profiles for Ingress Controller
|
||||
|
||||
NGINX controller is now configurable on a per-replica basis.
|
||||
Configurations include the ingress controller pods' CPU and memory requests/limits, either with direct values or using one of the available presets.
|
||||
|
||||
### Cozystack REST API Documentation
|
||||
|
||||
[Cozystack REST API reference](https://cozystack.io/docs/cozystack-api/rest/) is now published on the website.
|
||||
It includes endpoints and methods for listing, creating, updating, and removing each managed application, defined as Cozystack CRD.
|
||||
|
||||
|
||||
### Built-in LLDP-Based Neighbor Discovery in Talos
|
||||
|
||||
Cozystack now includes the LLDPD extension in its Talos OS image, enabling Link Layer Discovery Protocol (LLDP) out of the box.
|
||||
This means each node can automatically discover and advertise its network neighbors and topology without any manual setup.
|
||||
|
||||
### Use external IP for Egress Traffic in VMs
|
||||
|
||||
When a virtual machine has an external IP assigned to it, it will now always use it for egress traffic, independently of the external method used.
|
||||
|
||||
## Major Features and Improvements
|
||||
|
||||
* [talos] Add LLDPD (`ghcr.io/siderolabs/lldpd`) as a built-in system extension, enabling LLDP-based neighbor discovery out of the box. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1351 and https://github.com/cozystack/cozystack/pull/1360)
|
||||
* [kubernetes] Add a configurable CoreDNS addon with valuesOverride, packaged chart, and managed deployment (metrics, autoscaling, HPA, customizable Service). (@klinch0 in https://github.com/cozystack/cozystack/pull/1362)
|
||||
* [kube-ovn] Implement the Kube-OVN plunger, an external monitoring agent for the ovn-central cluster. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1380, patched in https://github.com/cozystack/cozystack/pull/1414 and https://github.com/cozystack/cozystack/pull/1418)
|
||||
* [tenant] Enable per-namespace resource quota settings in tenants, with explicit cpu, memory, and storage values. (@IvanHunters in https://github.com/cozystack/cozystack/pull/1389)
|
||||
* [seaweedfs] Add detailed resource configuration for each component of the SeaweedFS service. (@klinch0 and @kvaps in https://github.com/cozystack/cozystack/pull/1415)
|
||||
* [ingress] Enable per-replica resource configuration to the ingress controller. (@kvaps in https://github.com/cozystack/cozystack/pull/1416)
|
||||
* [virtual-machine] Use external IP for egress traffic with `PortList` method. (@kvaps in https://github.com/cozystack/cozystack/pull/1349)
|
||||
|
||||
|
||||
## Fixes
|
||||
|
||||
* [cozy-lib] Fix malformed retrieval of `cozyConfig` in the cozy-lib template. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1348)
|
||||
* [cozy-lib] Add the missing template `cozy-lib.resources.flatten`. (@kvaps in https://github.com/cozystack/cozystack/pull/1372)
|
||||
* [cozystack-api] Sanitize the OpenAPI v2 schema. (@kvaps in https://github.com/cozystack/cozystack/pull/1353)
|
||||
* [kube-ovn] Improve northd leader detection. Patch the northd leader check to test against all endpoints instead of just the first one marked as ready. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1363)
|
||||
* [seaweedfs] Add a liveness check for the SeaweedFS S3 endpoint to improve health monitoring and enable automatic recovery. (@IvanHunters in https://github.com/cozystack/cozystack/pull/1368)
|
||||
* [seaweedfs] Resolve race conditions in SeaweedFS. Increase deployment timeouts and set install/upgrade remediation to unlimited retries to improve deployment resilience. (@IvanHunters in https://github.com/cozystack/cozystack/pull/1371)
|
||||
* [seaweedfs] Resolve connectivity issues in SeaweedFS. Increase Nginx ingress timeouts for SeaweedFS S3 endpoint. (@kvaps in https://github.com/cozystack/cozystack/pull/1386)
|
||||
* [virtual-machine] Fix the reg ression in VM update hook introduced in https://github.com/cozystack/cozystack/pull/1169. Target the correct API resource and avoid conflicts with KubeVirt resources. (@kvaps in https://github.com/cozystack/cozystack/pull/1376)
|
||||
* [virtual-machine] Correct app version references in `virtual-machine` and `vm-instance`, ensuring accurate versioning during migrations. (@kvaps in https://github.com/cozystack/cozystack/pull/1378).
|
||||
* [cozyreport] Fix an error where cozyreport tried to parse non-existent objects and generated garbage output in CI debug logs. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1383)
|
||||
* [platform] Fix a boolean override bug in Helm merge. ConfigMap values now correctly take precedence over bundle defaults. (@dyudin0821 in https://github.com/cozystack/cozystack/pull/1385)
|
||||
* [kubernetes] CoreDNS release now installs and stores state in the `kube-system` namespace. (@kvaps in https://github.com/cozystack/cozystack/pull/1395)
|
||||
* [kubernetes] Expose configuration for CoreDNS, enabling setting the image repository and replica count via `values.yaml`. (@kvaps in https://github.com/cozystack/cozystack/pull/1410)
|
||||
* [etcd] Ensure that TopologySpreadConstraints consistently target etcd pods. (@kvaps in https://github.com/cozystack/cozystack/pull/1405)
|
||||
* [tenant] Use force-upgrade for ingress controller charts. (@klinch0 in https://github.com/cozystack/cozystack/pull/1404)
|
||||
* [cozystack-controller] Fix an RBAC error that prevented the workload labelling feature from working. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1419)
|
||||
* [seaweedfs] Remove VerticalPodAutoscaler for SeaweedFS. (@kvaps in https://github.com/cozystack/cozystack/pull/1421)
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
* Update LINSTOR to v1.31.3. (@kvaps in https://github.com/cozystack/cozystack/pull/1358)
|
||||
* Update SeaweedFS to v3.97. (@kvaps in https://github.com/cozystack/cozystack/pull/1361 and https://github.com/cozystack/cozystack/pull/1373)
|
||||
* Update Kube-OVN to 1.14.5. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1363)
|
||||
* Replace Bitnami images with alternatives in all charts. (@kvaps in https://github.com/cozystack/cozystack/pull/1374)
|
||||
|
||||
## Documentation
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
|
||||
* [dx] Remove the BUILDER and PLATFORM autodetect logic in Makefiles. (@kvaps in https://github.com/cozystack/cozystack/pull/1391)
|
||||
* [ci] Use the host buildx config in CI. (@kvaps in https://github.com/cozystack/cozystack/pull/1015)
|
||||
* [ci] Add `jq` and `git` to the installer image. (@kvaps in https://github.com/cozystack/cozystack/pull/1417)
|
||||
* [ci] Source the `REGISTRY` environment variable from actions' variables, not secrets, so external pull requests can work. (@lllamnyp in https://github.com/cozystack/cozystack/pull/1423)
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.35.0...v0.36.0
|
||||
22
docs/changelogs/v0.36.1.md
Normal file
22
docs/changelogs/v0.36.1.md
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.36.1
|
||||
-->
|
||||
|
||||
## Major Features and Improvements
|
||||
|
||||
* [cozystack-api] Implement recursive, Kubernetes-like defaulting for applications: missing fields in nested objects and arrays are auto-populated safely without mutating shared defaults. (@kvaps in https://github.com/cozystack/cozystack/pull/1432)
|
||||
|
||||
## Fixes
|
||||
|
||||
* [cozystack-api] Update defaulting API schemas. (@kvaps in https://github.com/cozystack/cozystack/pull/1433)
|
||||
* [dashboard] Fix Bitnami dependencies. (@kvaps in https://github.com/cozystack/cozystack/pull/1431)
|
||||
* [seaweedfs] Fix SeaweedFS migration. (@kvaps in https://github.com/cozystack/cozystack/pull/1430)
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
|
||||
* [adopters] Add [Hidora](https://hikube.cloud) to the Cozystack adopters list. (@matthieu-robin in https://github.com/cozystack/cozystack/pull/1429)
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: https://github.com/cozystack/cozystack/compare/v0.36.0...v0.36.1
|
||||
18
docs/changelogs/v0.36.2.md
Normal file
18
docs/changelogs/v0.36.2.md
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
<!--
|
||||
https://github.com/cozystack/cozystack/releases/tag/v0.36.2
|
||||
-->
|
||||
|
||||
## Features and Improvements
|
||||
|
||||
## Security
|
||||
|
||||
## Fixes
|
||||
|
||||
## Dependencies
|
||||
|
||||
## Development, Testing, and CI/CD
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: [v0.36.1...v0.36.2](https://github.com/cozystack/cozystack/compare/v0.36.1...v0.36.2)
|
||||
117
docs/changelogs/v0.37.0.md
Normal file
117
docs/changelogs/v0.37.0.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Cozystack v0.37 — “OpenAPI Dashboard & Lineage Everywhere”
|
||||
|
||||
We’ve shipped a big usability push this cycle: a brand-new **OpenAPI-driven dashboard**, lineage labeling across core resource types, and several reliability improvements to smooth upgrades from 0.36→ 0.37. Below are the highlights and the full categorized lists.
|
||||
|
||||
## Highlights
|
||||
|
||||
* **New OpenAPI-based Dashboard** replaces the old UI, adds module-aware navigation, dynamic branding, and richer Kubernetes resource views ([**@kvaps**](https://github.com/kvaps) in #1269, #1463, #1460).
|
||||
* **Lineage Webhook** tags Pods, PVCs, Services, Ingresses, and Secrets, adding labels referencing the managing Cozystack application ([**@lllamnyp**](https://github.com/lllamnyp) in #1448, #1452, #1477, #1486, #1497; [**@kvaps**](https://github.com/kvaps) in #1454).
|
||||
* **Smoother upgrades** with installer and migration hardening, decoupled CRDs vs. API server ([**@lllamnyp**](https://github.com/lllamnyp) in #1494, #1498; [**@kvaps**](https://github.com/kvaps) in #1506).
|
||||
* **Operations quality**: Kubernetes tests with smarter waits/readiness checks ([**@IvanHunters**](https://github.com/IvanHunters) in #1485).
|
||||
|
||||
---
|
||||
|
||||
## New features
|
||||
|
||||
### Dashboard
|
||||
|
||||
* Introduce the OpenAPI-based dashboard and controller; implement TenantNamespace, TenantModules, TenantSecret/SecretsTable resources ([**@kvaps**](https://github.com/kvaps) in #1269).
|
||||
* Module-aware navigation, richer detail views (Services/Secrets/Ingresses), improved sidebars; “Tenant Modules” grouping ([**@kvaps**](https://github.com/kvaps) in #1463).
|
||||
* Dynamic branding via cluster config (tenant name, footer/title, logo/icon SVGs) ([**@kvaps**](https://github.com/kvaps) in #1460).
|
||||
* Dashboard: fix namespace listing for unprivileged users and stabilize streamed requests; build-time patching ([**@kvaps**](https://github.com/kvaps) in #1456).
|
||||
* Dashboard UX set: marketplace hides module resources; consistent navigation/links; prefill “name” in forms; ingress factory; formatted TenantNamespaces tables ([**@kvaps**](https://github.com/kvaps) in #1463).
|
||||
* **Dashboard**: list modules reliably; remove Tenant from Marketplace; fix field override while typing ([**@kvaps**](https://github.com/kvaps) in #1501, #1503).
|
||||
* **Dashboard**: correct API group for applications; sidebars; disable auto-expand; fix `/docs` redirect ([**@kvaps**](https://github.com/kvaps) in #1463, #1465, #1462).
|
||||
* **Dashboard**: show Secrets with empty values correctly ([**@kvaps**](https://github.com/kvaps) in #1480).
|
||||
* Dashboard configuration refactor: generate static resources at startup; auto-cleanup stale objects; higher controller client throughput ([**@kvaps**](https://github.com/kvaps) in #1457).
|
||||
|
||||
### Migration to v0.37
|
||||
* **Installer/Migrations**: prevent unintended deletion of platform resource definitions; resilient timestamping; tolerant annotations; stronger migrate-then-reconcile flow ([**@kvaps**](https://github.com/kvaps) in #1475; Andrei Kvapil & [**@lllamnyp**](https://github.com/lllamnyp) in #1498).
|
||||
* Installer hardening for **migration #20**: packaged apply, ordered waits/readiness checks, RFC3339(nano) stamping; Helm in installer image (Andrei Kvapil & [**@lllamnyp**](https://github.com/lllamnyp) in #1498).
|
||||
* **Decoupled API & CozyRDs**: You can now upgrade the Cozystack API server independently of CRDs/CozyRD instances, easing 0.36 → 0.37 migrations ([**@lllamnyp**](https://github.com/lllamnyp) in #1494).
|
||||
* **Migration #20**: The installer runs migration from packaged Helm charts with ordered waits/readiness checks; annotations are tolerant; timestamps are environment-robust (Andrei Kvapil & [**@lllamnyp**](https://github.com/lllamnyp) in #1498; [**@kvaps**](https://github.com/kvaps) in #1475).
|
||||
|
||||
### Webhook / Lineage
|
||||
|
||||
* Add a lineage mutating webhook to auto-label Pods/Secrets/PVCs/Ingresses/WorkloadMonitors with owning app ([**@lllamnyp**](https://github.com/lllamnyp) in #1448, #1497, [**@kvaps**](https://github.com/kvaps) in #1454).
|
||||
* **Name-based** selectors for Secret visibility (templates supported) ([**@lllamnyp**](https://github.com/lllamnyp) in #1477).
|
||||
* Select **Services** and **Ingresses** in CRDs/API; treat them as user-facing when configured ([**@lllamnyp**](https://github.com/lllamnyp) in #1486).
|
||||
* **VictoriaMetrics integration**: Lineage labels are explicitly set on VM resources; `managedMetadata` is configured to avoid controller “fights” over labels ([**@lllamnyp**](https://github.com/lllamnyp) in #1452).
|
||||
* Webhook **excludes** `default` and `kube-system` to avoid unintended mutations (part of the installer/migration hardening by Andrei Kvapil & [**@lllamnyp**](https://github.com/lllamnyp) in #1498).
|
||||
|
||||
### API / Platform
|
||||
|
||||
* Decouple the Cozystack API from Cozystack Resource Definitions to allow independent upgrades ([**@lllamnyp**](https://github.com/lllamnyp) in #1494).
|
||||
* Add **label selectors** to app definitions for Secret include/exclude ([**@lllamnyp**](https://github.com/lllamnyp) in #1447).
|
||||
|
||||
### Monitoring & Ops
|
||||
|
||||
* Reduce node labelsets in target relabeling configs on cadvisor/kubelet metrics to reduce cardinality while keeping useful CPU metrics ([**@IvanHunters**](https://github.com/IvanHunters) in #1455).
|
||||
|
||||
### Storage & Backups
|
||||
|
||||
* PVC expansion in tenant clusters via KubeVirt CSI resizer; RBAC updates (Klinch0 in #1438).
|
||||
* Velero upgraded to **v1.17.0**; node agent enabled by default and a raft of usability features ([**@kvaps**](https://github.com/kvaps) in #1484).
|
||||
|
||||
### Kubernetes/tests & Tooling
|
||||
|
||||
* Smarter Kubernetes test flows: node readiness checks, kubelet version validation, longer rollout waits, per-component readiness ([**@IvanHunters**](https://github.com/IvanHunters) in #1485).
|
||||
|
||||
### UI/Icons
|
||||
|
||||
* New **VM-Disk** SVG icon ([**@kvapsova**](https://github.com/kvapsova) in #1435).
|
||||
|
||||
---
|
||||
|
||||
## Improvements (minor)
|
||||
|
||||
* Make the **Info** app deploy irrespective of OIDC settings ([**klinch0**](https://github.com/klinch0) in #1474).
|
||||
* Move SA token Secret creation to **Info** app ([**@lllamnyp**](https://github.com/lllamnyp) in #1446).
|
||||
* Explicitly set lineage labels for VictoriaMetrics resources ([**@lllamnyp**](https://github.com/lllamnyp) in #1452).
|
||||
|
||||
---
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* **Kubernetes**: fix MachineDeployment `spec.selector` mismatch to ensure proper targeting ([**@kvaps**](https://github.com/kvaps) in #1502).
|
||||
* **Old dashboard**: FerretDB spec typo prevented deploy/display ([**@lllamnyp**](https://github.com/lllamnyp) in #1440).
|
||||
* **SeaweedFS**: fix per-zone size fallback for multi-DC volumes; make migrations more robust ([**@kvaps**](https://github.com/kvaps) in #1476, #1430).
|
||||
* **CoreDNS**: pin tag to v1.12.4 ([**@kvaps**](https://github.com/kvaps) in #1469).
|
||||
* **OIDC**: avoid creating KeycloakRealmGroup before operator API is available ([**@lllamnyp**](https://github.com/lllamnyp) in #1495).
|
||||
* **Kafka**: disable noisy alerts when Kafka isn’t deployed ([**@lllamnyp**](https://github.com/lllamnyp) in #1488).
|
||||
|
||||
---
|
||||
|
||||
## Dependency & version updates
|
||||
|
||||
* **Velero → v1.17.0**; Helm chart v11; node agent default-on ([**@kvaps**](https://github.com/kvaps) in #1484).
|
||||
* **Cilium → v1.17.8** ([**@kvaps**](https://github.com/kvaps) in #1473).
|
||||
* **Flux Operator → v0.29.0** (Kingdon Barrett in #1466).
|
||||
|
||||
---
|
||||
|
||||
## Refactors & chores
|
||||
|
||||
* Remove legacy `versions_map`; unify packaging targets; tighten HelmRelease defaults; replace many chart versions with build-time placeholders ([**@kvaps**](https://github.com/kvaps) in #1453).
|
||||
* Pin CoreDNS image and refresh numerous images ([**@kvaps**](https://github.com/kvaps) in #1469; related image refreshes across #1448 work).
|
||||
|
||||
---
|
||||
|
||||
## Documentation & governance
|
||||
|
||||
* **Contributor Ladder** created and later updated (Timur Tukaev in #1224; Andrei Kvapil & Timur Tukaev in #1492).
|
||||
* **Code of Conduct** updated with a Vendor Neutrality Manifesto (Timur Tukaev in #1493).
|
||||
* **Adopters**: add Hidora (Matthieu Robin in #1429).
|
||||
* **MAINTAINERS**: add/remove entries (Nikita Bykov in #1487; Timur Tukaev in #1491).
|
||||
* **Issue templates**: new bug-report template and tweaks (Moriarti).
|
||||
* **README**: updated dark-theme screenshot ([**@kvaps**](https://github.com/kvaps) in #1459).
|
||||
|
||||
---
|
||||
|
||||
## Breaking changes & upgrade notes
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Security & stability
|
||||
|
||||
44
hack/e2e-apps/ferretdb.bats
Normal file
44
hack/e2e-apps/ferretdb.bats
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create DB FerretDB" {
|
||||
name='test'
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: FerretDB
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
backup:
|
||||
destinationPath: "s3://bucket/path/to/folder/"
|
||||
enabled: false
|
||||
endpointURL: "http://minio-gateway-service:9000"
|
||||
retentionPolicy: "30d"
|
||||
s3AccessKey: "<your-access-key>"
|
||||
s3SecretKey: "<your-secret-key>"
|
||||
schedule: "0 2 * * * *"
|
||||
bootstrap:
|
||||
enabled: false
|
||||
external: false
|
||||
quorum:
|
||||
maxSyncReplicas: 0
|
||||
minSyncReplicas: 0
|
||||
replicas: 2
|
||||
resources: {}
|
||||
resourcesPreset: "micro"
|
||||
size: "10Gi"
|
||||
users:
|
||||
testuser:
|
||||
password: xai7Wepo
|
||||
EOF
|
||||
sleep 5
|
||||
kubectl -n tenant-test wait hr ferretdb-$name --timeout=100s --for=condition=ready
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc ferretdb-$name-postgres-r -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc ferretdb-$name-postgres-ro -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 40 sh -ec "until kubectl -n tenant-test get svc ferretdb-$name-postgres-rw -o jsonpath='{.spec.ports[0].port}' | grep -q '5432'; do sleep 10; done"
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get endpoints ferretdb-$name-postgres-r -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
# for some reason it takes longer for the read-only endpoint to be ready
|
||||
#timeout 120 sh -ec "until kubectl -n tenant-test get endpoints ferretdb-$name-postgres-ro -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get endpoints ferretdb-$name-postgres-rw -o jsonpath='{.subsets[*].addresses[*].ip}' | grep -q '[0-9]'; do sleep 10; done"
|
||||
kubectl -n tenant-test delete ferretdb.apps.cozystack.io $name
|
||||
}
|
||||
121
hack/e2e-apps/foundationdb.bats
Normal file
121
hack/e2e-apps/foundationdb.bats
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
@test "Create DB FoundationDB" {
|
||||
name='test'
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: apps.cozystack.io/v1alpha1
|
||||
kind: FoundationDB
|
||||
metadata:
|
||||
name: $name
|
||||
namespace: tenant-test
|
||||
spec:
|
||||
cluster:
|
||||
version: "7.3.63"
|
||||
processCounts:
|
||||
storage: 3
|
||||
stateless: -1
|
||||
cluster_controller: 1
|
||||
redundancyMode: "double"
|
||||
storageEngine: "ssd-2"
|
||||
faultDomain:
|
||||
key: "foundationdb.org/none"
|
||||
valueFrom: "\$FDB_ZONE_ID"
|
||||
storage:
|
||||
size: "1Gi"
|
||||
storageClass: ""
|
||||
resourcesPreset: "small"
|
||||
backup:
|
||||
enabled: false
|
||||
s3:
|
||||
bucket: ""
|
||||
endpoint: ""
|
||||
region: ""
|
||||
credentials:
|
||||
accessKeyId: ""
|
||||
secretAccessKey: ""
|
||||
retentionPolicy: "7d"
|
||||
monitoring:
|
||||
enabled: true
|
||||
customParameters:
|
||||
- "knob_disable_posix_kernel_aio=1"
|
||||
imageType: "unified"
|
||||
automaticReplacements: true
|
||||
EOF
|
||||
sleep 15
|
||||
|
||||
# Wait for HelmRelease to be ready
|
||||
kubectl -n tenant-test wait hr foundationdb-$name --timeout=300s --for=condition=ready
|
||||
|
||||
# Wait for FoundationDBCluster to be created (name has foundationdb- prefix)
|
||||
timeout 300 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name; do sleep 15; done"
|
||||
|
||||
# Wait for cluster to become available (initial reconciliation takes time - allow 5 minutes)
|
||||
timeout 300 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.databaseConfiguration.usable_regions}' | grep -q '1'; do sleep 30; done"
|
||||
|
||||
# Check that storage processes are running
|
||||
timeout 300 sh -ec "until [ \$(kubectl -n tenant-test get pods -l foundationdb.org/fdb-cluster-name=foundationdb-$name,foundationdb.org/fdb-process-class=storage --field-selector=status.phase=Running --no-headers | wc -l) -eq 3 ]; do sleep 15; done"
|
||||
|
||||
# Check that log processes are running (these are the stateless processes)
|
||||
timeout 300 sh -ec "until [ \$(kubectl -n tenant-test get pods -l foundationdb.org/fdb-cluster-name=foundationdb-$name,foundationdb.org/fdb-process-class=log --field-selector=status.phase=Running --no-headers | wc -l) -ge 1 ]; do sleep 15; done"
|
||||
|
||||
# Check that cluster controller is running
|
||||
timeout 300 sh -ec "until [ \$(kubectl -n tenant-test get pods -l foundationdb.org/fdb-cluster-name=foundationdb-$name,foundationdb.org/fdb-process-class=cluster_controller --field-selector=status.phase=Running --no-headers | wc -l) -eq 1 ]; do sleep 15; done"
|
||||
|
||||
# Check WorkloadMonitor is created and configured
|
||||
timeout 120 sh -ec "until kubectl -n tenant-test get workloadmonitor foundationdb-$name; do sleep 10; done"
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get workloadmonitor foundationdb-$name -o jsonpath='{.spec.replicas}' | grep -q '3'; do sleep 5; done"
|
||||
|
||||
# Check dashboard resource map is created
|
||||
kubectl -n tenant-test get configmap foundationdb-$name-resourcemap
|
||||
|
||||
# Verify cluster is healthy (check cluster status) - allow extra time for initial setup
|
||||
timeout 300 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.health.available}' | grep -q 'true'; do sleep 20; done"
|
||||
|
||||
# Validate status.configured field
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.configured}' | grep -q 'true'; do sleep 10; done"
|
||||
|
||||
# Validate status.connectionString field exists and contains expected format
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.connectionString}' | grep -q '@.*\.svc\.cozy\.local'; do sleep 10; done"
|
||||
|
||||
# Validate comprehensive status.databaseConfiguration fields
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.databaseConfiguration.logs}' | grep -q '3'; do sleep 10; done"
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.databaseConfiguration.proxies}' | grep -q '3'; do sleep 10; done"
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.databaseConfiguration.redundancy_mode}' | grep -q 'double'; do sleep 10; done"
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.databaseConfiguration.resolvers}' | grep -q '1'; do sleep 10; done"
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.databaseConfiguration.storage_engine}' | grep -q 'ssd-2'; do sleep 10; done"
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.databaseConfiguration.usable_regions}' | grep -q '1'; do sleep 10; done"
|
||||
|
||||
# Validate status.desiredProcessGroups field
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.desiredProcessGroups}' | grep -q '^[0-9][0-9]*$'; do sleep 10; done"
|
||||
|
||||
# Validate status.generations.reconciled field
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.generations.reconciled}' | grep -q '^[0-9][0-9]*$'; do sleep 10; done"
|
||||
|
||||
# Validate status.hasListenIPsForAllPods field
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.hasListenIPsForAllPods}' | grep -q 'true'; do sleep 10; done"
|
||||
|
||||
# Validate comprehensive status.health fields
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.health.fullReplication}' | grep -q 'true'; do sleep 10; done"
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.status.health.healthy}' | grep -q 'true'; do sleep 10; done"
|
||||
|
||||
# Verify security context is applied correctly (non-root user)
|
||||
storage_pod=$(kubectl -n tenant-test get pods -l foundationdb.org/fdb-cluster-name=foundationdb-$name,foundationdb.org/fdb-process-class=storage --no-headers | head -n1 | awk '{print $1}')
|
||||
kubectl -n tenant-test get pod "$storage_pod" -o jsonpath='{.spec.containers[0].securityContext.runAsUser}' | grep -q '4059'
|
||||
kubectl -n tenant-test get pod "$storage_pod" -o jsonpath='{.spec.containers[0].securityContext.runAsGroup}' | grep -q '4059'
|
||||
|
||||
# Verify volumeClaimTemplate is properly configured in FoundationDBCluster CRD
|
||||
timeout 60 sh -ec "until kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name -o jsonpath='{.spec.processes.general.volumeClaimTemplate.spec.resources.requests.storage}' | grep -q '1Gi'; do sleep 10; done"
|
||||
|
||||
# Verify PVCs are created with correct storage size (1Gi as specified in test)
|
||||
timeout 120 sh -ec "until [ \$(kubectl -n tenant-test get pvc -l foundationdb.org/fdb-cluster-name=foundationdb-$name --no-headers | wc -l) -ge 3 ]; do sleep 10; done"
|
||||
kubectl -n tenant-test get pvc -l foundationdb.org/fdb-cluster-name=foundationdb-$name -o jsonpath='{.items[*].spec.resources.requests.storage}' | grep -q '1Gi'
|
||||
|
||||
# Verify actual PVC storage capacity matches requested size
|
||||
kubectl -n tenant-test get pvc -l foundationdb.org/fdb-cluster-name=foundationdb-$name -o jsonpath='{.items[*].status.capacity.storage}' | grep -q '1Gi'
|
||||
|
||||
# Clean up
|
||||
kubectl -n tenant-test delete foundationdb $name
|
||||
|
||||
# Wait for cleanup to complete
|
||||
timeout 120 sh -ec "while kubectl -n tenant-test get foundationdbclusters.apps.foundationdb.org foundationdb-$name 2>/dev/null; do sleep 10; done"
|
||||
}
|
||||
@@ -64,19 +64,19 @@ spec:
|
||||
EOF
|
||||
# Wait for the tenant-test namespace to be active
|
||||
kubectl wait namespace tenant-test --timeout=20s --for=jsonpath='{.status.phase}'=Active
|
||||
|
||||
|
||||
# Wait for the Kamaji control plane to be created (retry for up to 10 seconds)
|
||||
timeout 10 sh -ec 'until kubectl get kamajicontrolplane -n tenant-test kubernetes-'"${test_name}"'; do sleep 1; done'
|
||||
|
||||
# Wait for the tenant control plane to be fully created (timeout after 4 minutes)
|
||||
kubectl wait --for=condition=TenantControlPlaneCreated kamajicontrolplane -n tenant-test kubernetes-${test_name} --timeout=4m
|
||||
|
||||
|
||||
# Wait for Kubernetes resources to be ready (timeout after 2 minutes)
|
||||
kubectl wait tcp -n tenant-test kubernetes-${test_name} --timeout=2m --for=jsonpath='{.status.kubernetesResources.version.status}'=Ready
|
||||
|
||||
|
||||
# Wait for all required deployments to be available (timeout after 4 minutes)
|
||||
kubectl wait deploy --timeout=4m --for=condition=available -n tenant-test kubernetes-${test_name} kubernetes-${test_name}-cluster-autoscaler kubernetes-${test_name}-kccm kubernetes-${test_name}-kcsi-controller
|
||||
|
||||
|
||||
# Wait for the machine deployment to scale to 2 replicas (timeout after 1 minute)
|
||||
kubectl wait machinedeployment kubernetes-${test_name}-md0 -n tenant-test --timeout=1m --for=jsonpath='{.status.replicas}'=2
|
||||
# Get the admin kubeconfig and save it to a file
|
||||
@@ -87,14 +87,14 @@ EOF
|
||||
|
||||
|
||||
# Set up port forwarding to the Kubernetes API server for a 200 second timeout
|
||||
bash -c 'timeout 200s kubectl port-forward service/kubernetes-'"${test_name}"' -n tenant-test '"${port}"':6443 > /dev/null 2>&1 &'
|
||||
bash -c 'timeout 300s kubectl port-forward service/kubernetes-'"${test_name}"' -n tenant-test '"${port}"':6443 > /dev/null 2>&1 &'
|
||||
# Verify the Kubernetes version matches what we expect (retry for up to 20 seconds)
|
||||
timeout 20 sh -ec 'until kubectl --kubeconfig tenantkubeconfig version 2>/dev/null | grep -Fq "Server Version: ${k8s_version}"; do sleep 5; done'
|
||||
|
||||
# Wait for the nodes to be ready (timeout after 2 minutes)
|
||||
timeout 2m bash -c '
|
||||
timeout 3m bash -c '
|
||||
until [ "$(kubectl --kubeconfig tenantkubeconfig get nodes -o jsonpath="{.items[*].metadata.name}" | wc -w)" -eq 2 ]; do
|
||||
sleep 3
|
||||
sleep 2
|
||||
done
|
||||
'
|
||||
# Verify the nodes are ready
|
||||
@@ -105,9 +105,11 @@ EOF
|
||||
versions=$(kubectl --kubeconfig tenantkubeconfig get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}')
|
||||
node_ok=true
|
||||
|
||||
if [[ "$k8s_version" == v1.32* ]]; then
|
||||
echo "⚠️ TODO: Temporary stub — allowing nodes with v1.33 while k8s_version is v1.32"
|
||||
fi
|
||||
case "$k8s_version" in
|
||||
v1.32*)
|
||||
echo "⚠️ TODO: Temporary stub — allowing nodes with v1.33 while k8s_version is v1.32"
|
||||
;;
|
||||
esac
|
||||
|
||||
for v in $versions; do
|
||||
case "$k8s_version" in
|
||||
@@ -134,7 +136,7 @@ EOF
|
||||
esac
|
||||
done
|
||||
|
||||
if ! $node_ok; then
|
||||
if [ "$node_ok" != true ]; then
|
||||
echo "Kubelet versions did not match expected ${k8s_version}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -118,7 +118,7 @@ EOF
|
||||
}
|
||||
|
||||
@test "Check Cozystack API service" {
|
||||
kubectl wait --for=condition=Available apiservices/v1alpha1.apps.cozystack.io --timeout=2m
|
||||
kubectl wait --for=condition=Available apiservices/v1alpha1.apps.cozystack.io apiservices/v1alpha1.core.cozystack.io --timeout=2m
|
||||
}
|
||||
|
||||
@test "Configure Tenant and wait for applications" {
|
||||
|
||||
@@ -132,7 +132,6 @@ machine:
|
||||
- usermode_helper=disabled
|
||||
- name: zfs
|
||||
- name: spl
|
||||
- name: lldpd
|
||||
registries:
|
||||
mirrors:
|
||||
docker.io:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
@test "Test OpenAPI v3 endpoint" {
|
||||
kubectl get -v7 --raw '/openapi/v3/apis/apps.cozystack.io/v1alpha1' > /dev/null
|
||||
kubectl get -v7 --raw '/openapi/v3/apis/core.cozystack.io/v1alpha1' > /dev/null
|
||||
}
|
||||
|
||||
@test "Test OpenAPI v2 endpoint (protobuf)" {
|
||||
@@ -18,3 +19,26 @@
|
||||
curl -sS --fail 'http://localhost:21234/openapi/v2?timeout=32s' -H 'Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf' > /dev/null
|
||||
)
|
||||
}
|
||||
|
||||
@test "Test kinds" {
|
||||
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/tenants | jq -r '.kind')
|
||||
if [ "$val" != "TenantList" ]; then
|
||||
echo "Expected kind to be TenantList, got $val"
|
||||
exit 1
|
||||
fi
|
||||
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/tenants | jq -r '.items[0].kind')
|
||||
if [ "$val" != "Tenant" ]; then
|
||||
echo "Expected kind to be Tenant, got $val"
|
||||
exit 1
|
||||
fi
|
||||
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/ingresses | jq -r '.kind')
|
||||
if [ "$val" != "IngressList" ]; then
|
||||
echo "Expected kind to be IngressList, got $val"
|
||||
exit 1
|
||||
fi
|
||||
val=$(kubectl get --raw /apis/apps.cozystack.io/v1alpha1/ingresses | jq -r '.items[0].kind')
|
||||
if [ "$val" != "Ingress" ]; then
|
||||
echo "Expected kind to be Ingress, got $val"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -5,28 +5,21 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cozystack/cozystack/internal/controller/dashboard"
|
||||
"github.com/cozystack/cozystack/internal/shared/crdmem"
|
||||
|
||||
cozyv1alpha1 "github.com/cozystack/cozystack/api/v1alpha1"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/builder"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
@@ -40,128 +33,20 @@ type CozystackResourceDefinitionReconciler struct {
|
||||
lastEvent time.Time
|
||||
lastHandled time.Time
|
||||
|
||||
mem *crdmem.Memory
|
||||
|
||||
// Track static resources initialization
|
||||
staticResourcesInitialized bool
|
||||
staticResourcesMutex sync.Mutex
|
||||
CozystackAPIKind string
|
||||
}
|
||||
|
||||
func (r *CozystackResourceDefinitionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
logger := log.FromContext(ctx)
|
||||
|
||||
crd := &cozyv1alpha1.CozystackResourceDefinition{}
|
||||
err := r.Get(ctx, types.NamespacedName{Name: req.Name}, crd)
|
||||
if err == nil {
|
||||
if r.mem != nil {
|
||||
r.mem.Upsert(crd)
|
||||
}
|
||||
|
||||
mgr := dashboard.NewManager(
|
||||
r.Client,
|
||||
r.Scheme,
|
||||
dashboard.WithCRDListFunc(func(c context.Context) ([]cozyv1alpha1.CozystackResourceDefinition, error) {
|
||||
if r.mem != nil {
|
||||
return r.mem.ListFromCacheOrAPI(c, r.Client)
|
||||
}
|
||||
var list cozyv1alpha1.CozystackResourceDefinitionList
|
||||
if err := r.Client.List(c, &list); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list.Items, nil
|
||||
}),
|
||||
)
|
||||
|
||||
if res, derr := mgr.EnsureForCRD(ctx, crd); derr != nil || res.Requeue || res.RequeueAfter > 0 {
|
||||
return res, derr
|
||||
}
|
||||
|
||||
// After processing CRD, perform cleanup of orphaned resources
|
||||
// This should be done after cache warming to ensure all current resources are known
|
||||
if cleanupErr := mgr.CleanupOrphanedResources(ctx); cleanupErr != nil {
|
||||
logger.Error(cleanupErr, "Failed to cleanup orphaned dashboard resources")
|
||||
// Don't fail the reconciliation, just log the error
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
r.lastEvent = time.Now()
|
||||
r.mu.Unlock()
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// Handle error cases (err is guaranteed to be non-nil here)
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
// If resource is not found, clean up from memory
|
||||
if r.mem != nil {
|
||||
r.mem.Delete(req.Name)
|
||||
}
|
||||
if req.Namespace == "cozy-system" && req.Name == "cozystack-api" {
|
||||
return r.debouncedRestart(ctx, logger)
|
||||
}
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// initializeStaticResourcesOnce ensures static resources are created only once
|
||||
func (r *CozystackResourceDefinitionReconciler) initializeStaticResourcesOnce(ctx context.Context) error {
|
||||
r.staticResourcesMutex.Lock()
|
||||
defer r.staticResourcesMutex.Unlock()
|
||||
|
||||
if r.staticResourcesInitialized {
|
||||
return nil // Already initialized
|
||||
}
|
||||
|
||||
// Create dashboard manager and initialize static resources
|
||||
mgr := dashboard.NewManager(
|
||||
r.Client,
|
||||
r.Scheme,
|
||||
dashboard.WithCRDListFunc(func(c context.Context) ([]cozyv1alpha1.CozystackResourceDefinition, error) {
|
||||
if r.mem != nil {
|
||||
return r.mem.ListFromCacheOrAPI(c, r.Client)
|
||||
}
|
||||
var list cozyv1alpha1.CozystackResourceDefinitionList
|
||||
if err := r.Client.List(c, &list); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list.Items, nil
|
||||
}),
|
||||
)
|
||||
|
||||
if err := mgr.InitializeStaticResources(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.staticResourcesInitialized = true
|
||||
log.FromContext(ctx).Info("Static dashboard resources initialized successfully")
|
||||
return nil
|
||||
return r.debouncedRestart(ctx)
|
||||
}
|
||||
|
||||
func (r *CozystackResourceDefinitionReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
if r.Debounce == 0 {
|
||||
r.Debounce = 5 * time.Second
|
||||
}
|
||||
if r.mem == nil {
|
||||
r.mem = crdmem.Global()
|
||||
}
|
||||
if err := r.mem.EnsurePrimingWithManager(mgr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Initialize static resources once during controller startup using manager.Runnable
|
||||
if err := mgr.Add(manager.RunnableFunc(func(ctx context.Context) error {
|
||||
if err := r.initializeStaticResourcesOnce(ctx); err != nil {
|
||||
log.FromContext(ctx).Error(err, "Failed to initialize static resources")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
Named("cozystackresource-controller").
|
||||
For(&cozyv1alpha1.CozystackResourceDefinition{}, builder.WithPredicates()).
|
||||
Watches(
|
||||
&cozyv1alpha1.CozystackResourceDefinition{},
|
||||
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
|
||||
@@ -176,9 +61,6 @@ func (r *CozystackResourceDefinitionReconciler) SetupWithManager(mgr ctrl.Manage
|
||||
}}
|
||||
}),
|
||||
).
|
||||
WithOptions(controller.Options{
|
||||
MaxConcurrentReconciles: 5, // Allow more concurrent reconciles with proper rate limiting
|
||||
}).
|
||||
Complete(r)
|
||||
}
|
||||
|
||||
@@ -188,22 +70,18 @@ type crdHashView struct {
|
||||
}
|
||||
|
||||
func (r *CozystackResourceDefinitionReconciler) computeConfigHash(ctx context.Context) (string, error) {
|
||||
var items []cozyv1alpha1.CozystackResourceDefinition
|
||||
if r.mem != nil {
|
||||
list, err := r.mem.ListFromCacheOrAPI(ctx, r.Client)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
items = list
|
||||
list := &cozyv1alpha1.CozystackResourceDefinitionList{}
|
||||
if err := r.List(ctx, list); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sort.Slice(items, func(i, j int) bool { return items[i].Name < items[j].Name })
|
||||
slices.SortFunc(list.Items, sortCozyRDs)
|
||||
|
||||
views := make([]crdHashView, 0, len(items))
|
||||
for i := range items {
|
||||
views := make([]crdHashView, 0, len(list.Items))
|
||||
for i := range list.Items {
|
||||
views = append(views, crdHashView{
|
||||
Name: items[i].Name,
|
||||
Spec: items[i].Spec,
|
||||
Name: list.Items[i].Name,
|
||||
Spec: list.Items[i].Spec,
|
||||
})
|
||||
}
|
||||
b, err := json.Marshal(views)
|
||||
@@ -214,7 +92,9 @@ func (r *CozystackResourceDefinitionReconciler) computeConfigHash(ctx context.Co
|
||||
return hex.EncodeToString(sum[:]), nil
|
||||
}
|
||||
|
||||
func (r *CozystackResourceDefinitionReconciler) debouncedRestart(ctx context.Context, logger logr.Logger) (ctrl.Result, error) {
|
||||
func (r *CozystackResourceDefinitionReconciler) debouncedRestart(ctx context.Context) (ctrl.Result, error) {
|
||||
logger := log.FromContext(ctx)
|
||||
|
||||
r.mu.Lock()
|
||||
le := r.lastEvent
|
||||
lh := r.lastHandled
|
||||
@@ -239,15 +119,12 @@ func (r *CozystackResourceDefinitionReconciler) debouncedRestart(ctx context.Con
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
deploy := &appsv1.Deployment{}
|
||||
if err := r.Get(ctx, types.NamespacedName{Namespace: "cozy-system", Name: "cozystack-api"}, deploy); err != nil {
|
||||
tpl, obj, patch, err := r.getWorkload(ctx, types.NamespacedName{Namespace: "cozy-system", Name: "cozystack-api"})
|
||||
if err != nil {
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
||||
if deploy.Spec.Template.Annotations == nil {
|
||||
deploy.Spec.Template.Annotations = map[string]string{}
|
||||
}
|
||||
oldHash := deploy.Spec.Template.Annotations["cozystack.io/config-hash"]
|
||||
oldHash := tpl.Annotations["cozystack.io/config-hash"]
|
||||
|
||||
if oldHash == newHash && oldHash != "" {
|
||||
r.mu.Lock()
|
||||
@@ -257,10 +134,9 @@ func (r *CozystackResourceDefinitionReconciler) debouncedRestart(ctx context.Con
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
patch := client.MergeFrom(deploy.DeepCopy())
|
||||
deploy.Spec.Template.Annotations["cozystack.io/config-hash"] = newHash
|
||||
tpl.Annotations["cozystack.io/config-hash"] = newHash
|
||||
|
||||
if err := r.Patch(ctx, deploy, patch); err != nil {
|
||||
if err := r.Patch(ctx, obj, patch); err != nil {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
@@ -272,3 +148,40 @@ func (r *CozystackResourceDefinitionReconciler) debouncedRestart(ctx context.Con
|
||||
"old", oldHash, "new", newHash)
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
func (r *CozystackResourceDefinitionReconciler) getWorkload(
|
||||
ctx context.Context,
|
||||
key types.NamespacedName,
|
||||
) (tpl *corev1.PodTemplateSpec, obj client.Object, patch client.Patch, err error) {
|
||||
if r.CozystackAPIKind == "Deployment" {
|
||||
dep := &appsv1.Deployment{}
|
||||
if err := r.Get(ctx, key, dep); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
obj = dep
|
||||
tpl = &dep.Spec.Template
|
||||
patch = client.MergeFrom(dep.DeepCopy())
|
||||
} else {
|
||||
ds := &appsv1.DaemonSet{}
|
||||
if err := r.Get(ctx, key, ds); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
obj = ds
|
||||
tpl = &ds.Spec.Template
|
||||
patch = client.MergeFrom(ds.DeepCopy())
|
||||
}
|
||||
if tpl.Annotations == nil {
|
||||
tpl.Annotations = make(map[string]string)
|
||||
}
|
||||
return tpl, obj, patch, nil
|
||||
}
|
||||
|
||||
func sortCozyRDs(a, b cozyv1alpha1.CozystackResourceDefinition) int {
|
||||
if a.Name == b.Name {
|
||||
return 0
|
||||
}
|
||||
if a.Name < b.Name {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -58,8 +58,8 @@ func (m *Manager) ensureBreadcrumb(ctx context.Context, crd *cozyv1alpha1.Cozyst
|
||||
"breadcrumbItems": items,
|
||||
}
|
||||
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.scheme); err != nil {
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
|
||||
@@ -30,10 +30,6 @@ func (m *Manager) ensureCustomColumnsOverride(ctx context.Context, crd *cozyv1al
|
||||
name := fmt.Sprintf("stock-namespace-%s.%s.%s", g, v, plural)
|
||||
id := fmt.Sprintf("stock-namespace-/%s/%s/%s", g, v, plural)
|
||||
|
||||
// Badge content & color derived from kind
|
||||
badgeText := initialsFromKind(kind) // e.g., "VirtualMachine" -> "VM", "Bucket" -> "B"
|
||||
badgeColor := hexColorForKind(kind) // deterministic, dark enough for white text
|
||||
|
||||
obj := &dashv1alpha1.CustomColumnsOverride{}
|
||||
obj.SetName(name)
|
||||
|
||||
@@ -62,25 +58,11 @@ func (m *Manager) ensureCustomColumnsOverride(ctx context.Context, crd *cozyv1al
|
||||
},
|
||||
"children": []any{
|
||||
map[string]any{
|
||||
"type": "antdText",
|
||||
"type": "ResourceBadge",
|
||||
"data": map[string]any{
|
||||
"id": "header-badge",
|
||||
"text": badgeText,
|
||||
"title": strings.ToLower(kind), // optional tooltip
|
||||
"style": map[string]any{
|
||||
"backgroundColor": badgeColor,
|
||||
"borderRadius": "20px",
|
||||
"color": "#fff",
|
||||
"display": "inline-block",
|
||||
"fontFamily": "RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif",
|
||||
"fontSize": "15px",
|
||||
"fontWeight": 400,
|
||||
"lineHeight": "24px",
|
||||
"minWidth": 24,
|
||||
"padding": "0 9px",
|
||||
"textAlign": "center",
|
||||
"whiteSpace": "nowrap",
|
||||
},
|
||||
"value": kind,
|
||||
// abbreviation auto-generated by ResourceBadge from value
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
@@ -145,8 +127,8 @@ func (m *Manager) ensureCustomColumnsOverride(ctx context.Context, crd *cozyv1al
|
||||
},
|
||||
}
|
||||
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.scheme); err != nil {
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
// ensureCustomFormsOverride creates or updates a CustomFormsOverride resource for the given CRD
|
||||
@@ -45,16 +46,25 @@ func (m *Manager) ensureCustomFormsOverride(ctx context.Context, crd *cozyv1alph
|
||||
}
|
||||
}
|
||||
|
||||
// Build schema with multilineString for string fields without enum
|
||||
l := log.FromContext(ctx)
|
||||
schema, err := buildMultilineStringSchema(crd.Spec.Application.OpenAPISchema)
|
||||
if err != nil {
|
||||
// If schema parsing fails, log the error and use an empty schema
|
||||
l.Error(err, "failed to build multiline string schema, using empty schema", "crd", crd.Name)
|
||||
schema = map[string]any{}
|
||||
}
|
||||
|
||||
spec := map[string]any{
|
||||
"customizationId": customizationID,
|
||||
"hidden": hidden,
|
||||
"sort": sort,
|
||||
"schema": map[string]any{}, // {}
|
||||
"schema": schema,
|
||||
"strategy": "merge",
|
||||
}
|
||||
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.scheme); err != nil {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
@@ -73,3 +83,94 @@ func (m *Manager) ensureCustomFormsOverride(ctx context.Context, crd *cozyv1alph
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// buildMultilineStringSchema parses OpenAPI schema and creates schema with multilineString
|
||||
// for all string fields inside spec that don't have enum
|
||||
func buildMultilineStringSchema(openAPISchema string) (map[string]any, error) {
|
||||
if openAPISchema == "" {
|
||||
return map[string]any{}, nil
|
||||
}
|
||||
|
||||
var root map[string]any
|
||||
if err := json.Unmarshal([]byte(openAPISchema), &root); err != nil {
|
||||
return nil, fmt.Errorf("cannot parse openAPISchema: %w", err)
|
||||
}
|
||||
|
||||
props, _ := root["properties"].(map[string]any)
|
||||
if props == nil {
|
||||
return map[string]any{}, nil
|
||||
}
|
||||
|
||||
schema := map[string]any{
|
||||
"properties": map[string]any{},
|
||||
}
|
||||
|
||||
// Process spec properties recursively
|
||||
processSpecProperties(props, schema["properties"].(map[string]any))
|
||||
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
// processSpecProperties recursively processes spec properties and adds multilineString type
|
||||
// for string fields without enum
|
||||
func processSpecProperties(props map[string]any, schemaProps map[string]any) {
|
||||
for pname, raw := range props {
|
||||
sub, ok := raw.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
typ, _ := sub["type"].(string)
|
||||
|
||||
switch typ {
|
||||
case "string":
|
||||
// Check if this string field has enum
|
||||
if !hasEnum(sub) {
|
||||
// Add multilineString type for this field
|
||||
if schemaProps[pname] == nil {
|
||||
schemaProps[pname] = map[string]any{}
|
||||
}
|
||||
fieldSchema := schemaProps[pname].(map[string]any)
|
||||
fieldSchema["type"] = "multilineString"
|
||||
}
|
||||
case "object":
|
||||
// Recursively process nested objects
|
||||
if childProps, ok := sub["properties"].(map[string]any); ok {
|
||||
fieldSchema, ok := schemaProps[pname].(map[string]any)
|
||||
if !ok {
|
||||
fieldSchema = map[string]any{}
|
||||
schemaProps[pname] = fieldSchema
|
||||
}
|
||||
nestedSchemaProps, ok := fieldSchema["properties"].(map[string]any)
|
||||
if !ok {
|
||||
nestedSchemaProps = map[string]any{}
|
||||
fieldSchema["properties"] = nestedSchemaProps
|
||||
}
|
||||
processSpecProperties(childProps, nestedSchemaProps)
|
||||
}
|
||||
case "array":
|
||||
// Check if array items are objects with properties
|
||||
if items, ok := sub["items"].(map[string]any); ok {
|
||||
if itemProps, ok := items["properties"].(map[string]any); ok {
|
||||
// Create array item schema
|
||||
fieldSchema, ok := schemaProps[pname].(map[string]any)
|
||||
if !ok {
|
||||
fieldSchema = map[string]any{}
|
||||
schemaProps[pname] = fieldSchema
|
||||
}
|
||||
itemSchema, ok := fieldSchema["items"].(map[string]any)
|
||||
if !ok {
|
||||
itemSchema = map[string]any{}
|
||||
fieldSchema["items"] = itemSchema
|
||||
}
|
||||
itemSchemaProps, ok := itemSchema["properties"].(map[string]any)
|
||||
if !ok {
|
||||
itemSchemaProps = map[string]any{}
|
||||
itemSchema["properties"] = itemSchemaProps
|
||||
}
|
||||
processSpecProperties(itemProps, itemSchemaProps)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
155
internal/controller/dashboard/customformsoverride_test.go
Normal file
155
internal/controller/dashboard/customformsoverride_test.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBuildMultilineStringSchema(t *testing.T) {
|
||||
// Test OpenAPI schema with various field types
|
||||
openAPISchema := `{
|
||||
"properties": {
|
||||
"simpleString": {
|
||||
"type": "string",
|
||||
"description": "A simple string field"
|
||||
},
|
||||
"stringWithEnum": {
|
||||
"type": "string",
|
||||
"enum": ["option1", "option2"],
|
||||
"description": "String with enum should be skipped"
|
||||
},
|
||||
"numberField": {
|
||||
"type": "number",
|
||||
"description": "Number field should be skipped"
|
||||
},
|
||||
"nestedObject": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nestedString": {
|
||||
"type": "string",
|
||||
"description": "Nested string should get multilineString"
|
||||
},
|
||||
"nestedStringWithEnum": {
|
||||
"type": "string",
|
||||
"enum": ["a", "b"],
|
||||
"description": "Nested string with enum should be skipped"
|
||||
}
|
||||
}
|
||||
},
|
||||
"arrayOfObjects": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itemString": {
|
||||
"type": "string",
|
||||
"description": "String in array item"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
schema, err := buildMultilineStringSchema(openAPISchema)
|
||||
if err != nil {
|
||||
t.Fatalf("buildMultilineStringSchema failed: %v", err)
|
||||
}
|
||||
|
||||
// Marshal to JSON for easier inspection
|
||||
schemaJSON, err := json.MarshalIndent(schema, "", " ")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal schema: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("Generated schema:\n%s", schemaJSON)
|
||||
|
||||
// Verify that simpleString has multilineString type
|
||||
props, ok := schema["properties"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("schema.properties is not a map")
|
||||
}
|
||||
|
||||
// Check simpleString
|
||||
simpleString, ok := props["simpleString"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("simpleString not found in properties")
|
||||
}
|
||||
if simpleString["type"] != "multilineString" {
|
||||
t.Errorf("simpleString should have type multilineString, got %v", simpleString["type"])
|
||||
}
|
||||
|
||||
// Check stringWithEnum should not be present (or should not have multilineString)
|
||||
if stringWithEnum, ok := props["stringWithEnum"].(map[string]any); ok {
|
||||
if stringWithEnum["type"] == "multilineString" {
|
||||
t.Error("stringWithEnum should not have multilineString type")
|
||||
}
|
||||
}
|
||||
|
||||
// Check numberField should not be present
|
||||
if numberField, ok := props["numberField"].(map[string]any); ok {
|
||||
if numberField["type"] != nil {
|
||||
t.Error("numberField should not have any type override")
|
||||
}
|
||||
}
|
||||
|
||||
// Check nested object
|
||||
nestedObject, ok := props["nestedObject"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("nestedObject not found in properties")
|
||||
}
|
||||
nestedProps, ok := nestedObject["properties"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("nestedObject.properties is not a map")
|
||||
}
|
||||
|
||||
// Check nestedString
|
||||
nestedString, ok := nestedProps["nestedString"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("nestedString not found in nestedObject.properties")
|
||||
}
|
||||
if nestedString["type"] != "multilineString" {
|
||||
t.Errorf("nestedString should have type multilineString, got %v", nestedString["type"])
|
||||
}
|
||||
|
||||
// Check array of objects
|
||||
arrayOfObjects, ok := props["arrayOfObjects"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("arrayOfObjects not found in properties")
|
||||
}
|
||||
items, ok := arrayOfObjects["items"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("arrayOfObjects.items is not a map")
|
||||
}
|
||||
itemProps, ok := items["properties"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("arrayOfObjects.items.properties is not a map")
|
||||
}
|
||||
itemString, ok := itemProps["itemString"].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatal("itemString not found in arrayOfObjects.items.properties")
|
||||
}
|
||||
if itemString["type"] != "multilineString" {
|
||||
t.Errorf("itemString should have type multilineString, got %v", itemString["type"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildMultilineStringSchemaEmpty(t *testing.T) {
|
||||
schema, err := buildMultilineStringSchema("")
|
||||
if err != nil {
|
||||
t.Fatalf("buildMultilineStringSchema failed on empty string: %v", err)
|
||||
}
|
||||
if len(schema) != 0 {
|
||||
t.Errorf("Expected empty schema for empty input, got %v", schema)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildMultilineStringSchemaInvalidJSON(t *testing.T) {
|
||||
schema, err := buildMultilineStringSchema("{invalid json")
|
||||
if err == nil {
|
||||
t.Error("Expected error for invalid JSON")
|
||||
}
|
||||
if schema != nil {
|
||||
t.Errorf("Expected nil schema for invalid JSON, got %v", schema)
|
||||
}
|
||||
}
|
||||
@@ -56,8 +56,8 @@ func (m *Manager) ensureCustomFormsPrefill(ctx context.Context, crd *cozyv1alpha
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, m.client, cfp, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, cfp, m.scheme); err != nil {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, m.Client, cfp, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, cfp, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
|
||||
@@ -53,7 +53,6 @@ func (m *Manager) ensureFactory(ctx context.Context, crd *cozyv1alpha1.Cozystack
|
||||
Kind: kind,
|
||||
Plural: plural,
|
||||
Title: strings.ToLower(plural),
|
||||
Size: BadgeSizeLarge,
|
||||
}
|
||||
|
||||
spec := createUnifiedFactory(config, tabs, []any{resourceFetch})
|
||||
@@ -61,8 +60,8 @@ func (m *Manager) ensureFactory(ctx context.Context, crd *cozyv1alpha1.Cozystack
|
||||
obj := &dashv1alpha1.Factory{}
|
||||
obj.SetName(factoryName)
|
||||
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.scheme); err != nil {
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
@@ -115,7 +114,7 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str
|
||||
"gap": float64(6),
|
||||
},
|
||||
"children": []any{
|
||||
createUnifiedBadgeFromKind("ns-badge", "Namespace", "namespace", BadgeSizeMedium),
|
||||
createUnifiedBadgeFromKind("ns-badge", "Namespace"),
|
||||
antdLink("namespace-link",
|
||||
"{reqsJsonPath[0]['.metadata.namespace']['-']}",
|
||||
"/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace",
|
||||
@@ -222,7 +221,7 @@ func workloadsTab(kind string) map[string]any {
|
||||
"baseprefix": "/openapi-ui",
|
||||
"customizationId": "factory-details-v1alpha1.cozystack.io.workloadmonitors",
|
||||
"pathToItems": []any{"items"},
|
||||
"labelsSelector": map[string]any{
|
||||
"labelSelector": map[string]any{
|
||||
"apps.cozystack.io/application.group": "apps.cozystack.io",
|
||||
"apps.cozystack.io/application.kind": kind,
|
||||
"apps.cozystack.io/application.name": "{reqs[0]['metadata','name']}",
|
||||
@@ -247,7 +246,7 @@ func servicesTab(kind string) map[string]any {
|
||||
"baseprefix": "/openapi-ui",
|
||||
"customizationId": "factory-details-v1.services",
|
||||
"pathToItems": []any{"items"},
|
||||
"labelsSelector": map[string]any{
|
||||
"labelSelector": map[string]any{
|
||||
"apps.cozystack.io/application.group": "apps.cozystack.io",
|
||||
"apps.cozystack.io/application.kind": kind,
|
||||
"apps.cozystack.io/application.name": "{reqs[0]['metadata','name']}",
|
||||
@@ -273,7 +272,7 @@ func ingressesTab(kind string) map[string]any {
|
||||
"baseprefix": "/openapi-ui",
|
||||
"customizationId": "factory-details-networking.k8s.io.v1.ingresses",
|
||||
"pathToItems": []any{"items"},
|
||||
"labelsSelector": map[string]any{
|
||||
"labelSelector": map[string]any{
|
||||
"apps.cozystack.io/application.group": "apps.cozystack.io",
|
||||
"apps.cozystack.io/application.kind": kind,
|
||||
"apps.cozystack.io/application.name": "{reqs[0]['metadata','name']}",
|
||||
@@ -294,12 +293,12 @@ func secretsTab(kind string) map[string]any {
|
||||
"type": "EnrichedTable",
|
||||
"data": map[string]any{
|
||||
"id": "secrets-table",
|
||||
"fetchUrl": "/api/clusters/{2}/k8s/apis/core.cozystack.io/v1alpha1/namespaces/{3}/tenantsecretstables",
|
||||
"fetchUrl": "/api/clusters/{2}/k8s/apis/core.cozystack.io/v1alpha1/namespaces/{3}/tenantsecrets",
|
||||
"clusterNamePartOfUrl": "{2}",
|
||||
"baseprefix": "/openapi-ui",
|
||||
"customizationId": "factory-details-v1alpha1.core.cozystack.io.tenantsecretstables",
|
||||
"customizationId": "factory-details-v1alpha1.core.cozystack.io.tenantsecrets",
|
||||
"pathToItems": []any{"items"},
|
||||
"labelsSelector": map[string]any{
|
||||
"labelSelector": map[string]any{
|
||||
"apps.cozystack.io/application.group": "apps.cozystack.io",
|
||||
"apps.cozystack.io/application.kind": kind,
|
||||
"apps.cozystack.io/application.name": "{reqs[0]['metadata','name']}",
|
||||
@@ -324,6 +323,7 @@ func yamlTab(plural string) map[string]any {
|
||||
"type": "builtin",
|
||||
"typeName": plural,
|
||||
"prefillValuesRequestIndex": float64(0),
|
||||
"readOnly": true,
|
||||
"substractHeight": float64(400),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -57,97 +54,6 @@ func pickPlural(kind string, crd *cozyv1alpha1.CozystackResourceDefinition) stri
|
||||
return k + "s"
|
||||
}
|
||||
|
||||
// initialsFromKind splits CamelCase and returns the first letters in upper case.
|
||||
// "VirtualMachine" -> "VM"; "Bucket" -> "B".
|
||||
func initialsFromKind(kind string) string {
|
||||
parts := splitCamel(kind)
|
||||
if len(parts) == 0 {
|
||||
return strings.ToUpper(kind)
|
||||
}
|
||||
var b strings.Builder
|
||||
for _, p := range parts {
|
||||
if p == "" {
|
||||
continue
|
||||
}
|
||||
b.WriteString(strings.ToUpper(string(p[0])))
|
||||
// Limit to 3 chars to keep the badge compact (VM, PVC, etc.)
|
||||
if b.Len() >= 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// hexColorForKind returns a dark, saturated color (hex) derived from a stable hash of the kind.
|
||||
// We map the hash to an HSL hue; fix S/L for consistent readability with white text.
|
||||
func hexColorForKind(kind string) string {
|
||||
// Stable short hash (sha1 → bytes → hue)
|
||||
sum := sha1.Sum([]byte(kind))
|
||||
// Use first two bytes for hue [0..359]
|
||||
hue := int(sum[0])<<8 | int(sum[1])
|
||||
hue = hue % 360
|
||||
|
||||
// Fixed S/L chosen to contrast with white text:
|
||||
// S = 80%, L = 35% (dark enough so #fff is readable)
|
||||
r, g, b := hslToRGB(float64(hue), 0.80, 0.35)
|
||||
|
||||
return fmt.Sprintf("#%02x%02x%02x", r, g, b)
|
||||
}
|
||||
|
||||
// hslToRGB converts HSL (0..360, 0..1, 0..1) to sRGB (0..255).
|
||||
func hslToRGB(h float64, s float64, l float64) (uint8, uint8, uint8) {
|
||||
c := (1 - absFloat(2*l-1)) * s
|
||||
hp := h / 60.0
|
||||
x := c * (1 - absFloat(modFloat(hp, 2)-1))
|
||||
var r1, g1, b1 float64
|
||||
switch {
|
||||
case 0 <= hp && hp < 1:
|
||||
r1, g1, b1 = c, x, 0
|
||||
case 1 <= hp && hp < 2:
|
||||
r1, g1, b1 = x, c, 0
|
||||
case 2 <= hp && hp < 3:
|
||||
r1, g1, b1 = 0, c, x
|
||||
case 3 <= hp && hp < 4:
|
||||
r1, g1, b1 = 0, x, c
|
||||
case 4 <= hp && hp < 5:
|
||||
r1, g1, b1 = x, 0, c
|
||||
default:
|
||||
r1, g1, b1 = c, 0, x
|
||||
}
|
||||
m := l - c/2
|
||||
r := uint8(clamp01(r1+m) * 255.0)
|
||||
g := uint8(clamp01(g1+m) * 255.0)
|
||||
b := uint8(clamp01(b1+m) * 255.0)
|
||||
return r, g, b
|
||||
}
|
||||
|
||||
func absFloat(v float64) float64 {
|
||||
if v < 0 {
|
||||
return -v
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func modFloat(a, b float64) float64 {
|
||||
return a - b*float64(int(a/b))
|
||||
}
|
||||
|
||||
func clamp01(v float64) float64 {
|
||||
if v < 0 {
|
||||
return 0
|
||||
}
|
||||
if v > 1 {
|
||||
return 1
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// optional: tiny helper to expose the compact color hash (useful for debugging)
|
||||
func shortHashHex(s string) string {
|
||||
sum := sha1.Sum([]byte(s))
|
||||
return hex.EncodeToString(sum[:4])
|
||||
}
|
||||
|
||||
// ----------------------- Helpers (OpenAPI → values) -----------------------
|
||||
|
||||
// defaultOrZero returns the schema default if present; otherwise a reasonable zero value.
|
||||
@@ -295,12 +201,6 @@ func normalizeJSON(v any) any {
|
||||
}
|
||||
}
|
||||
|
||||
var camelSplitter = regexp.MustCompile(`(?m)([A-Z]+[a-z0-9]*|[a-z0-9]+)`)
|
||||
|
||||
func splitCamel(s string) []string {
|
||||
return camelSplitter.FindAllString(s, -1)
|
||||
}
|
||||
|
||||
// --- helpers for schema inspection ---
|
||||
|
||||
func isScalarType(n map[string]any) bool {
|
||||
|
||||
@@ -10,9 +10,12 @@ import (
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
managerpkg "sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
@@ -40,28 +43,51 @@ func AddToScheme(s *runtime.Scheme) error {
|
||||
// Manager owns logic for creating/updating dashboard resources derived from CRDs.
|
||||
// It’s easy to extend: add new ensure* methods and wire them into EnsureForCRD.
|
||||
type Manager struct {
|
||||
client client.Client
|
||||
scheme *runtime.Scheme
|
||||
crdListFn func(context.Context) ([]cozyv1alpha1.CozystackResourceDefinition, error)
|
||||
}
|
||||
|
||||
// Option pattern so callers can inject a custom lister.
|
||||
type Option func(*Manager)
|
||||
|
||||
// WithCRDListFunc overrides how Manager lists all CozystackResourceDefinitions.
|
||||
func WithCRDListFunc(fn func(context.Context) ([]cozyv1alpha1.CozystackResourceDefinition, error)) Option {
|
||||
return func(m *Manager) { m.crdListFn = fn }
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
// NewManager constructs a dashboard Manager.
|
||||
func NewManager(c client.Client, scheme *runtime.Scheme, opts ...Option) *Manager {
|
||||
m := &Manager{client: c, scheme: scheme}
|
||||
for _, o := range opts {
|
||||
o(m)
|
||||
}
|
||||
func NewManager(c client.Client, scheme *runtime.Scheme) *Manager {
|
||||
m := &Manager{Client: c, Scheme: scheme}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Manager) SetupWithManager(mgr ctrl.Manager) error {
|
||||
if err := ctrl.NewControllerManagedBy(mgr).
|
||||
Named("dashboard-reconciler").
|
||||
For(&cozyv1alpha1.CozystackResourceDefinition{}).
|
||||
Complete(m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return mgr.Add(managerpkg.RunnableFunc(func(ctx context.Context) error {
|
||||
if !mgr.GetCache().WaitForCacheSync(ctx) {
|
||||
return fmt.Errorf("dashboard static resources cache sync failed")
|
||||
}
|
||||
return m.ensureStaticResources(ctx)
|
||||
}))
|
||||
}
|
||||
|
||||
func (m *Manager) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
l := log.FromContext(ctx)
|
||||
|
||||
crd := &cozyv1alpha1.CozystackResourceDefinition{}
|
||||
|
||||
err := m.Get(ctx, types.NamespacedName{Name: req.Name}, crd)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
if err := m.CleanupOrphanedResources(ctx); err != nil {
|
||||
l.Error(err, "Failed to cleanup orphaned dashboard resources")
|
||||
}
|
||||
return ctrl.Result{}, nil // no point in requeuing here
|
||||
}
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
return m.EnsureForCRD(ctx, crd)
|
||||
}
|
||||
|
||||
// EnsureForCRD is the single entry-point used by the controller.
|
||||
// Add more ensure* calls here as you implement support for other resources:
|
||||
//
|
||||
@@ -171,21 +197,11 @@ func (m *Manager) getStaticResourceSelector() client.MatchingLabels {
|
||||
// CleanupOrphanedResources removes dashboard resources that are no longer needed
|
||||
// This should be called after cache warming to ensure all current resources are known
|
||||
func (m *Manager) CleanupOrphanedResources(ctx context.Context) error {
|
||||
// Get all current CRDs to determine which resources should exist
|
||||
var allCRDs []cozyv1alpha1.CozystackResourceDefinition
|
||||
if m.crdListFn != nil {
|
||||
s, err := m.crdListFn(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allCRDs = s
|
||||
} else {
|
||||
var crdList cozyv1alpha1.CozystackResourceDefinitionList
|
||||
if err := m.client.List(ctx, &crdList, &client.ListOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
allCRDs = crdList.Items
|
||||
var crdList cozyv1alpha1.CozystackResourceDefinitionList
|
||||
if err := m.List(ctx, &crdList, &client.ListOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
allCRDs := crdList.Items
|
||||
|
||||
// Build a set of expected resource names for each type
|
||||
expectedResources := m.buildExpectedResourceSet(allCRDs)
|
||||
@@ -349,7 +365,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
}
|
||||
|
||||
// List with dashboard labels
|
||||
if err := m.client.List(ctx, list, m.getDashboardResourceSelector()); err != nil {
|
||||
if err := m.List(ctx, list, m.getDashboardResourceSelector()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -358,7 +374,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
case *dashv1alpha1.CustomColumnsOverrideList:
|
||||
for _, item := range l.Items {
|
||||
if !expected[item.Name] {
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -369,7 +385,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
case *dashv1alpha1.CustomFormsOverrideList:
|
||||
for _, item := range l.Items {
|
||||
if !expected[item.Name] {
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -380,7 +396,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
case *dashv1alpha1.CustomFormsPrefillList:
|
||||
for _, item := range l.Items {
|
||||
if !expected[item.Name] {
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -391,7 +407,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
case *dashv1alpha1.MarketplacePanelList:
|
||||
for _, item := range l.Items {
|
||||
if !expected[item.Name] {
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -402,7 +418,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
case *dashv1alpha1.SidebarList:
|
||||
for _, item := range l.Items {
|
||||
if !expected[item.Name] {
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -413,7 +429,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
case *dashv1alpha1.TableUriMappingList:
|
||||
for _, item := range l.Items {
|
||||
if !expected[item.Name] {
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -426,7 +442,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
if !expected[item.Name] {
|
||||
logger := log.FromContext(ctx)
|
||||
logger.Info("Deleting orphaned Breadcrumb resource", "name", item.Name)
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
@@ -438,7 +454,7 @@ func (m *Manager) cleanupResourceType(ctx context.Context, resourceType client.O
|
||||
if !expected[item.Name] {
|
||||
logger := log.FromContext(ctx)
|
||||
logger.Info("Deleting orphaned Factory resource", "name", item.Name)
|
||||
if err := m.client.Delete(ctx, &item); err != nil {
|
||||
if err := m.Delete(ctx, &item); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -24,14 +24,14 @@ func (m *Manager) ensureMarketplacePanel(ctx context.Context, crd *cozyv1alpha1.
|
||||
|
||||
// If dashboard is not set, delete the panel if it exists.
|
||||
if crd.Spec.Dashboard == nil {
|
||||
err := m.client.Get(ctx, client.ObjectKey{Name: mp.Name}, mp)
|
||||
err := m.Get(ctx, client.ObjectKey{Name: mp.Name}, mp)
|
||||
if apierrors.IsNotFound(err) {
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
if err := m.client.Delete(ctx, mp); err != nil && !apierrors.IsNotFound(err) {
|
||||
if err := m.Delete(ctx, mp); err != nil && !apierrors.IsNotFound(err) {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
logger.Info("Deleted MarketplacePanel because dashboard is not set", "name", mp.Name)
|
||||
@@ -40,14 +40,14 @@ func (m *Manager) ensureMarketplacePanel(ctx context.Context, crd *cozyv1alpha1.
|
||||
|
||||
// Skip module and tenant resources (they don't need MarketplacePanel)
|
||||
if crd.Spec.Dashboard.Module || crd.Spec.Application.Kind == "Tenant" {
|
||||
err := m.client.Get(ctx, client.ObjectKey{Name: mp.Name}, mp)
|
||||
err := m.Get(ctx, client.ObjectKey{Name: mp.Name}, mp)
|
||||
if apierrors.IsNotFound(err) {
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
if err := m.client.Delete(ctx, mp); err != nil && !apierrors.IsNotFound(err) {
|
||||
if err := m.Delete(ctx, mp); err != nil && !apierrors.IsNotFound(err) {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
logger.Info("Deleted MarketplacePanel because resource is a module", "name", mp.Name)
|
||||
@@ -86,8 +86,8 @@ func (m *Manager) ensureMarketplacePanel(ctx context.Context, crd *cozyv1alpha1.
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, m.client, mp, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, mp, m.scheme); err != nil {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, m.Client, mp, func() error {
|
||||
if err := controllerutil.SetOwnerReference(crd, mp, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
|
||||
@@ -33,19 +33,11 @@ func (m *Manager) ensureSidebar(ctx context.Context, crd *cozyv1alpha1.Cozystack
|
||||
|
||||
// 1) Fetch all CRDs
|
||||
var all []cozyv1alpha1.CozystackResourceDefinition
|
||||
if m.crdListFn != nil {
|
||||
s, err := m.crdListFn(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
all = s
|
||||
} else {
|
||||
var crdList cozyv1alpha1.CozystackResourceDefinitionList
|
||||
if err := m.client.List(ctx, &crdList, &client.ListOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
all = crdList.Items
|
||||
var crdList cozyv1alpha1.CozystackResourceDefinitionList
|
||||
if err := m.List(ctx, &crdList, &client.ListOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
all = crdList.Items
|
||||
|
||||
// 2) Build category -> []item map (only for CRDs with spec.dashboard != nil)
|
||||
type item struct {
|
||||
@@ -251,7 +243,7 @@ func (m *Manager) upsertMultipleSidebars(
|
||||
obj := &dashv1alpha1.Sidebar{}
|
||||
obj.SetName(id)
|
||||
|
||||
if _, err := controllerutil.CreateOrUpdate(ctx, m.client, obj, func() error {
|
||||
if _, err := controllerutil.CreateOrUpdate(ctx, m.Client, obj, func() error {
|
||||
// Only set owner reference for dynamic sidebars (stock-project-factory-{kind}-details)
|
||||
// Static sidebars (stock-instance-*, stock-project-*) should not have owner references
|
||||
if strings.HasPrefix(id, "stock-project-factory-") && strings.HasSuffix(id, "-details") {
|
||||
@@ -260,7 +252,7 @@ func (m *Manager) upsertMultipleSidebars(
|
||||
lowerKind := strings.ToLower(kind)
|
||||
expectedID := fmt.Sprintf("stock-project-factory-%s-details", lowerKind)
|
||||
if id == expectedID {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.scheme); err != nil {
|
||||
if err := controllerutil.SetOwnerReference(crd, obj, m.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add dashboard labels to dynamic resources
|
||||
|
||||
@@ -122,7 +122,7 @@ func createCustomColumnsOverride(id string, additionalPrinterColumns []any) *das
|
||||
}
|
||||
}
|
||||
|
||||
if name == "factory-details-v1alpha1.core.cozystack.io.tenantsecretstables" {
|
||||
if name == "factory-details-v1alpha1.core.cozystack.io.tenantsecrets" {
|
||||
data["additionalPrinterColumnsTrimLengths"] = []any{
|
||||
map[string]any{
|
||||
"key": "Name",
|
||||
@@ -531,7 +531,6 @@ func createBreadcrumbItem(key, label string, link ...string) map[string]any {
|
||||
|
||||
// createCustomColumn creates a custom column with factory type and badge
|
||||
func createCustomColumn(name, kind, plural, href string) map[string]any {
|
||||
badge := createUnifiedBadgeFromKind("header-badge", kind, plural, BadgeSizeMedium)
|
||||
link := antdLink("name-link", "{reqsJsonPath[0]['.metadata.name']['-']}", href)
|
||||
|
||||
return map[string]any{
|
||||
@@ -541,8 +540,18 @@ func createCustomColumn(name, kind, plural, href string) map[string]any {
|
||||
"disableEventBubbling": true,
|
||||
"items": []any{
|
||||
map[string]any{
|
||||
"children": []any{badge, link},
|
||||
"type": "antdFlex",
|
||||
"children": []any{
|
||||
map[string]any{
|
||||
"type": "ResourceBadge",
|
||||
"data": map[string]any{
|
||||
"id": "header-badge",
|
||||
"value": kind,
|
||||
// abbreviation auto-generated by ResourceBadge from value
|
||||
},
|
||||
},
|
||||
link,
|
||||
},
|
||||
"type": "antdFlex",
|
||||
"data": map[string]any{
|
||||
"align": "center",
|
||||
"gap": float64(6),
|
||||
@@ -554,16 +563,16 @@ func createCustomColumn(name, kind, plural, href string) map[string]any {
|
||||
}
|
||||
|
||||
// createCustomColumnWithBadge creates a custom column with a specific badge
|
||||
func createCustomColumnWithBadge(name, badgeText, badgeColor, title, href string) map[string]any {
|
||||
config := BadgeConfig{
|
||||
Text: badgeText,
|
||||
Color: badgeColor,
|
||||
Title: title,
|
||||
Size: BadgeSizeMedium,
|
||||
}
|
||||
badge := createUnifiedBadge("header-badge", config)
|
||||
// badgeValue should be the kind in PascalCase (e.g., "Service", "Pod")
|
||||
// abbreviation is auto-generated by ResourceBadge from badgeValue
|
||||
func createCustomColumnWithBadge(name, badgeValue, href string) map[string]any {
|
||||
link := antdLink("name-link", "{reqsJsonPath[0]['.metadata.name']['-']}", href)
|
||||
|
||||
badgeData := map[string]any{
|
||||
"id": "header-badge",
|
||||
"value": badgeValue,
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"name": name,
|
||||
"type": "factory",
|
||||
@@ -571,8 +580,14 @@ func createCustomColumnWithBadge(name, badgeText, badgeColor, title, href string
|
||||
"disableEventBubbling": true,
|
||||
"items": []any{
|
||||
map[string]any{
|
||||
"children": []any{badge, link},
|
||||
"type": "antdFlex",
|
||||
"children": []any{
|
||||
map[string]any{
|
||||
"type": "ResourceBadge",
|
||||
"data": badgeData,
|
||||
},
|
||||
link,
|
||||
},
|
||||
"type": "antdFlex",
|
||||
"data": map[string]any{
|
||||
"align": "center",
|
||||
"gap": float64(6),
|
||||
@@ -583,17 +598,22 @@ func createCustomColumnWithBadge(name, badgeText, badgeColor, title, href string
|
||||
}
|
||||
}
|
||||
|
||||
// createCustomColumnWithSpecificColor creates a custom column with a specific color
|
||||
func createCustomColumnWithSpecificColor(name, kind, title, color, href string) map[string]any {
|
||||
config := BadgeConfig{
|
||||
Text: initialsFromKind(kind),
|
||||
Color: color,
|
||||
Title: title,
|
||||
Size: BadgeSizeMedium,
|
||||
}
|
||||
badge := createUnifiedBadge("header-badge", config)
|
||||
// createCustomColumnWithSpecificColor creates a custom column with a specific kind and optional color
|
||||
// badgeValue should be the kind in PascalCase (e.g., "Service", "Pod")
|
||||
func createCustomColumnWithSpecificColor(name, kind, color, href string) map[string]any {
|
||||
link := antdLink("name-link", "{reqsJsonPath[0]['.metadata.name']['-']}", href)
|
||||
|
||||
badgeData := map[string]any{
|
||||
"id": "header-badge",
|
||||
"value": kind,
|
||||
}
|
||||
// Add custom color if specified
|
||||
if color != "" {
|
||||
badgeData["style"] = map[string]any{
|
||||
"backgroundColor": color,
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"name": name,
|
||||
"type": "factory",
|
||||
@@ -602,8 +622,14 @@ func createCustomColumnWithSpecificColor(name, kind, title, color, href string)
|
||||
"disableEventBubbling": true,
|
||||
"items": []any{
|
||||
map[string]any{
|
||||
"children": []any{badge, link},
|
||||
"type": "antdFlex",
|
||||
"children": []any{
|
||||
map[string]any{
|
||||
"type": "ResourceBadge",
|
||||
"data": badgeData,
|
||||
},
|
||||
link,
|
||||
},
|
||||
"type": "antdFlex",
|
||||
"data": map[string]any{
|
||||
"align": "center",
|
||||
"gap": float64(6),
|
||||
@@ -668,7 +694,7 @@ func createTimestampColumn(name, jsonPath string) map[string]any {
|
||||
// createFactoryHeader creates a header for factory resources
|
||||
func createFactoryHeader(kind, plural string) map[string]any {
|
||||
lowerKind := strings.ToLower(kind)
|
||||
badge := createUnifiedBadgeFromKind("badge-"+lowerKind, kind, plural, BadgeSizeLarge)
|
||||
badge := createUnifiedBadgeFromKind("badge-"+lowerKind, kind)
|
||||
nameText := parsedText(lowerKind+"-name", "{reqsJsonPath[0]['.metadata.name']['-']}", map[string]any{
|
||||
"fontFamily": "RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif",
|
||||
"fontSize": float64(20),
|
||||
@@ -718,13 +744,26 @@ func createFactorySpec(key string, sidebarTags []any, urlsToFetch []any, header
|
||||
}
|
||||
|
||||
// createCustomColumnWithJsonPath creates a column with a custom badge and link using jsonPath
|
||||
func createCustomColumnWithJsonPath(name, jsonPath, badgeText, badgeTitle, badgeColor, linkHref string) map[string]any {
|
||||
// badgeValue should be the kind in PascalCase (e.g., "Service", "VirtualMachine")
|
||||
// abbreviation is auto-generated by ResourceBadge from badgeValue
|
||||
func createCustomColumnWithJsonPath(name, jsonPath, badgeValue, badgeColor, linkHref string) map[string]any {
|
||||
// Determine link ID based on jsonPath
|
||||
linkId := "name-link"
|
||||
if jsonPath == ".metadata.namespace" {
|
||||
linkId = "namespace-link"
|
||||
}
|
||||
|
||||
badgeData := map[string]any{
|
||||
"id": "header-badge",
|
||||
"value": badgeValue,
|
||||
}
|
||||
// Add custom color if specified
|
||||
if badgeColor != "" {
|
||||
badgeData["style"] = map[string]any{
|
||||
"backgroundColor": badgeColor,
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"name": name,
|
||||
"type": "factory",
|
||||
@@ -741,26 +780,8 @@ func createCustomColumnWithJsonPath(name, jsonPath, badgeText, badgeTitle, badge
|
||||
},
|
||||
"children": []any{
|
||||
map[string]any{
|
||||
"type": "antdText",
|
||||
"data": map[string]any{
|
||||
"id": "header-badge",
|
||||
"text": badgeText,
|
||||
"title": badgeTitle,
|
||||
"style": map[string]any{
|
||||
"backgroundColor": badgeColor,
|
||||
"borderRadius": "20px",
|
||||
"color": "#fff",
|
||||
"display": "inline-block",
|
||||
"fontFamily": "RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif",
|
||||
"fontSize": "15px",
|
||||
"fontWeight": 400,
|
||||
"lineHeight": "24px",
|
||||
"minWidth": 24,
|
||||
"padding": "0 9px",
|
||||
"textAlign": "center",
|
||||
"whiteSpace": "nowrap",
|
||||
},
|
||||
},
|
||||
"type": "ResourceBadge",
|
||||
"data": badgeData,
|
||||
},
|
||||
map[string]any{
|
||||
"type": "antdLink",
|
||||
@@ -778,7 +799,20 @@ func createCustomColumnWithJsonPath(name, jsonPath, badgeText, badgeTitle, badge
|
||||
}
|
||||
|
||||
// createCustomColumnWithoutJsonPath creates a column with a custom badge and link without jsonPath
|
||||
func createCustomColumnWithoutJsonPath(name, badgeText, badgeTitle, badgeColor, linkHref string) map[string]any {
|
||||
// badgeValue should be the kind in PascalCase (e.g., "Node", "Pod")
|
||||
// abbreviation is auto-generated by ResourceBadge from badgeValue
|
||||
func createCustomColumnWithoutJsonPath(name, badgeValue, badgeColor, linkHref string) map[string]any {
|
||||
badgeData := map[string]any{
|
||||
"id": "header-badge",
|
||||
"value": badgeValue,
|
||||
}
|
||||
// Add custom color if specified
|
||||
if badgeColor != "" {
|
||||
badgeData["style"] = map[string]any{
|
||||
"backgroundColor": badgeColor,
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"name": name,
|
||||
"type": "factory",
|
||||
@@ -794,26 +828,8 @@ func createCustomColumnWithoutJsonPath(name, badgeText, badgeTitle, badgeColor,
|
||||
},
|
||||
"children": []any{
|
||||
map[string]any{
|
||||
"type": "antdText",
|
||||
"data": map[string]any{
|
||||
"id": "header-badge",
|
||||
"text": badgeText,
|
||||
"title": badgeTitle,
|
||||
"style": map[string]any{
|
||||
"backgroundColor": badgeColor,
|
||||
"borderRadius": "20px",
|
||||
"color": "#fff",
|
||||
"display": "inline-block",
|
||||
"fontFamily": "RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif",
|
||||
"fontSize": "15px",
|
||||
"fontWeight": 400,
|
||||
"lineHeight": "24px",
|
||||
"minWidth": 24,
|
||||
"padding": "0 9px",
|
||||
"textAlign": "center",
|
||||
"whiteSpace": "nowrap",
|
||||
},
|
||||
},
|
||||
"type": "ResourceBadge",
|
||||
"data": badgeData,
|
||||
},
|
||||
map[string]any{
|
||||
"type": "antdLink",
|
||||
@@ -1030,6 +1046,15 @@ func createConverterBytesColumn(name, jsonPath string) map[string]any {
|
||||
}
|
||||
}
|
||||
|
||||
// createFlatMapColumn creates a flatMap column that expands a map into separate rows
|
||||
func createFlatMapColumn(name, jsonPath string) map[string]any {
|
||||
return map[string]any{
|
||||
"name": name,
|
||||
"type": "flatMap",
|
||||
"jsonPath": jsonPath,
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Factory UI helper functions ----------------
|
||||
|
||||
// labelsEditor creates a Labels editor component
|
||||
|
||||
@@ -32,7 +32,7 @@ func (m *Manager) ensureStaticResource(ctx context.Context, obj client.Object) e
|
||||
// Add dashboard labels to static resources
|
||||
m.addDashboardLabels(resource, nil, ResourceTypeStatic)
|
||||
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.client, resource, func() error {
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, m.Client, resource, func() error {
|
||||
// For static resources, we don't need to set owner references
|
||||
// as they are meant to be persistent across CRD changes
|
||||
// Copy Spec from the original object to the live object
|
||||
|
||||
@@ -132,7 +132,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
return []*dashboardv1alpha1.CustomColumnsOverride{
|
||||
// Factory details v1 services
|
||||
createCustomColumnsOverride("factory-details-v1.services", []any{
|
||||
createCustomColumnWithSpecificColor("Name", "Service", "service", getColorForType("service"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithSpecificColor("Name", "Service", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createStringColumn("ClusterIP", ".spec.clusterIP"),
|
||||
createStringColumn("LoadbalancerIP", ".spec.loadBalancerIP"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
@@ -140,15 +140,15 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Stock namespace v1 services
|
||||
createCustomColumnsOverride("stock-namespace-/v1/services", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "S", "service", getColorForType("service"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Service", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createStringColumn("ClusterIP", ".spec.clusterIP"),
|
||||
createStringColumn("LoadbalancerIP", ".spec.loadBalancerIP"),
|
||||
createStringColumn("LoadbalancerIP", ".status.loadBalancer.ingress[0].ip"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
|
||||
// Stock namespace core cozystack io v1alpha1 tenantmodules
|
||||
createCustomColumnsOverride("stock-namespace-/core.cozystack.io/v1alpha1/tenantmodules", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "M", "module", getColorForType("module"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/{reqsJsonPath[0]['.metadata.name']['-']}-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Module", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/{reqsJsonPath[0]['.metadata.name']['-']}-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createReadyColumn(),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
createStringColumn("Version", ".status.version"),
|
||||
@@ -164,7 +164,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Factory details v1alpha1 cozystack io workloadmonitors
|
||||
createCustomColumnsOverride("factory-details-v1alpha1.cozystack.io.workloadmonitors", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "W", "workloadmonitor", getColorForType("workloadmonitor"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/workloadmonitor-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "WorkloadMonitor", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/workloadmonitor-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createStringColumn("TYPE", ".spec.type"),
|
||||
createStringColumn("VERSION", ".spec.version"),
|
||||
createStringColumn("REPLICAS", ".spec.replicas"),
|
||||
@@ -173,18 +173,19 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
createStringColumn("OBSERVED", ".status.observedReplicas"),
|
||||
}),
|
||||
|
||||
// Factory details v1alpha1 core cozystack io tenantsecretstables
|
||||
createCustomColumnsOverride("factory-details-v1alpha1.core.cozystack.io.tenantsecretstables", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "S", "secret", getColorForType("secret"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-secret-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createStringColumn("Key", ".data.key"),
|
||||
createSecretBase64Column("Value", ".data.value"),
|
||||
// Factory details v1alpha1 core cozystack io tenantsecrets
|
||||
createCustomColumnsOverride("factory-details-v1alpha1.core.cozystack.io.tenantsecrets", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Secret", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-secret-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createFlatMapColumn("Data", ".data"),
|
||||
createStringColumn("Key", "_flatMapData_Key"),
|
||||
createSecretBase64Column("Value", "._flatMapData_Value"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
|
||||
// Factory ingress details rules
|
||||
createCustomColumnsOverride("factory-kube-ingress-details-rules", []any{
|
||||
createStringColumn("Host", ".host"),
|
||||
createCustomColumnWithJsonPath("Service", ".http.paths[0].backend.service.name", "S", "service", getColorForType("service"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.http.paths[0].backend.service.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Service", ".http.paths[0].backend.service.name", "Service", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-service-details/{reqsJsonPath[0]['.http.paths[0].backend.service.name']['-']}"),
|
||||
createStringColumn("Port", ".http.paths[0].backend.service.port.number"),
|
||||
createStringColumn("Path", ".http.paths[0].path"),
|
||||
}),
|
||||
@@ -250,7 +251,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Factory details networking k8s io v1 ingresses
|
||||
createCustomColumnsOverride("factory-details-networking.k8s.io.v1.ingresses", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "I", "ingress", getColorForType("ingress"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-ingress-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Ingress", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-ingress-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createStringColumn("Hosts", ".spec.rules[*].host"),
|
||||
createStringColumn("Address", ".status.loadBalancer.ingress[0].ip"),
|
||||
createStringColumn("Port", ".spec.defaultBackend.service.port.number"),
|
||||
@@ -259,7 +260,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Stock namespace networking k8s io v1 ingresses
|
||||
createCustomColumnsOverride("stock-namespace-/networking.k8s.io/v1/ingresses", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "I", "ingress", getColorForType("ingress"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-ingress-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Ingress", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-ingress-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createStringColumn("Hosts", ".spec.rules[*].host"),
|
||||
createStringColumn("Address", ".status.loadBalancer.ingress[0].ip"),
|
||||
createStringColumn("Port", ".spec.defaultBackend.service.port.number"),
|
||||
@@ -268,34 +269,34 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Stock cluster v1 configmaps
|
||||
createCustomColumnsOverride("stock-cluster-/v1/configmaps", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "CM", "configmap", getColorForType("configmap"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/configmap-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "NS", "namespace", getColorForType("namespace"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "ConfigMap", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/configmap-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "Namespace", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
|
||||
// Stock namespace v1 configmaps
|
||||
createCustomColumnsOverride("stock-namespace-/v1/configmaps", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "CM", "configmap", getColorForType("configmap"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/configmap-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "ConfigMap", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/configmap-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
|
||||
// Cluster v1 configmaps
|
||||
createCustomColumnsOverride("cluster-/v1/configmaps", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "CM", "configmap", getColorForType("configmap"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/configmap-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "NS", "namespace", getColorForType("namespace"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "ConfigMap", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/configmap-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "Namespace", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
|
||||
// Stock cluster v1 nodes
|
||||
createCustomColumnsOverride("stock-cluster-/v1/nodes", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "N", "node", getColorForType("node"), "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Node", "", "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createSimpleStatusColumn("Status", "node-status"),
|
||||
}),
|
||||
|
||||
// Factory node details v1 pods
|
||||
createCustomColumnsOverride("factory-node-details-v1.pods", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "P", "pod", getColorForType("pod"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "NS", "namespace", getColorForType("namespace"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Pod", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "Namespace", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace"),
|
||||
createStringColumn("Restart Policy", ".spec.restartPolicy"),
|
||||
createStringColumn("Pod IP", ".status.podIP"),
|
||||
createStringColumn("QOS", ".status.qosClass"),
|
||||
@@ -304,8 +305,8 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Factory v1 pods
|
||||
createCustomColumnsOverride("factory-v1.pods", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "P", "pod", getColorForType("pod"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithoutJsonPath("Node", "N", "node", getColorForType("node"), "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.spec.nodeName']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Pod", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithoutJsonPath("Node", "Node", "", "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.spec.nodeName']['-']}"),
|
||||
createStringColumn("Restart Policy", ".spec.restartPolicy"),
|
||||
createStringColumn("Pod IP", ".status.podIP"),
|
||||
createStringColumn("QOS", ".status.qosClass"),
|
||||
@@ -314,9 +315,9 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Stock cluster v1 pods
|
||||
createCustomColumnsOverride("stock-cluster-/v1/pods", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "P", "pod", "#009596", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "NS", "namespace", "#a25792ff", "/openapi-ui/{2}/factory/tenantnamespace/{reqsJsonPath[0]['.metadata.namespace']['-']}"),
|
||||
createCustomColumnWithJsonPath("Node", ".spec.nodeName", "N", "node", "#8476d1", "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.spec.nodeName']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Pod", "#009596", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "Namespace", "#a25792ff", "/openapi-ui/{2}/factory/tenantnamespace/{reqsJsonPath[0]['.metadata.namespace']['-']}"),
|
||||
createCustomColumnWithJsonPath("Node", ".spec.nodeName", "Node", "#8476d1", "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.spec.nodeName']['-']}"),
|
||||
createStringColumn("Restart Policy", ".spec.restartPolicy"),
|
||||
createStringColumn("Pod IP", ".status.podIP"),
|
||||
createStringColumn("QOS", ".status.qosClass"),
|
||||
@@ -325,8 +326,8 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Stock namespace v1 pods
|
||||
createCustomColumnsOverride("stock-namespace-/v1/pods", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "P", "pod", "#009596", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithoutJsonPath("Node", "N", "node", "#8476d1", "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.spec.nodeName']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Pod", "#009596", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/pod-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithoutJsonPath("Node", "Node", "#8476d1", "/openapi-ui/{2}/factory/node-details/{reqsJsonPath[0]['.spec.nodeName']['-']}"),
|
||||
createStringColumn("Restart Policy", ".spec.restartPolicy"),
|
||||
createStringColumn("Pod IP", ".status.podIP"),
|
||||
createStringColumn("QOS", ".status.qosClass"),
|
||||
@@ -335,15 +336,15 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Stock cluster v1 secrets
|
||||
createCustomColumnsOverride("stock-cluster-/v1/secrets", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "S", "secret", "#c46100", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-secret-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "NS", "namespace", "#a25792ff", "/openapi-ui/{2}/factory/tenantnamespace/{reqsJsonPath[0]['.metadata.namespace']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Secret", "#c46100", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-secret-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Namespace", ".metadata.namespace", "Namespace", "#a25792ff", "/openapi-ui/{2}/factory/tenantnamespace/{reqsJsonPath[0]['.metadata.namespace']['-']}"),
|
||||
createStringColumn("Type", ".type"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
|
||||
// Stock namespace v1 secrets
|
||||
createCustomColumnsOverride("stock-namespace-/v1/secrets", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "S", "secret", "#c46100", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-secret-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "Secret", "#c46100", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/kube-secret-details/{reqsJsonPath[0]['.metadata.name']['-']}"),
|
||||
createStringColumn("Type", ".type"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
@@ -360,7 +361,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid
|
||||
|
||||
// Stock cluster core cozystack io v1alpha1 tenantnamespaces
|
||||
createCustomColumnsOverride("stock-cluster-/core.cozystack.io/v1alpha1/tenantnamespaces", []any{
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "TN", "tenantnamespace", getColorForType("tenantnamespace"), "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.name']['-']}/factory/marketplace"),
|
||||
createCustomColumnWithJsonPath("Name", ".metadata.name", "TenantNamespace", "", "/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.name']['-']}/factory/marketplace"),
|
||||
createTimestampColumn("Created", ".metadata.creationTimestamp"),
|
||||
}),
|
||||
}
|
||||
@@ -496,7 +497,6 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory {
|
||||
Kind: "Namespace",
|
||||
Plural: "namespaces",
|
||||
Title: "namespace",
|
||||
Size: BadgeSizeLarge,
|
||||
}
|
||||
namespaceSpec := createUnifiedFactory(namespaceConfig, nil, []any{"/api/clusters/{2}/k8s/api/v1/namespaces/{5}"})
|
||||
|
||||
@@ -796,6 +796,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory {
|
||||
"substractHeight": float64(400),
|
||||
"type": "builtin",
|
||||
"typeName": "secrets",
|
||||
"readOnly": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1055,7 +1056,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory {
|
||||
"clusterNamePartOfUrl": "{2}",
|
||||
"customizationId": "factory-kube-service-details-endpointslice",
|
||||
"fetchUrl": "/api/clusters/{2}/k8s/apis/discovery.k8s.io/v1/namespaces/{3}/endpointslices",
|
||||
"labelsSelector": map[string]any{
|
||||
"labelSelector": map[string]any{
|
||||
"kubernetes.io/service-name": "{reqsJsonPath[0]['.metadata.name']['-']}",
|
||||
},
|
||||
"pathToItems": ".items[*].endpoints",
|
||||
@@ -1201,7 +1202,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory {
|
||||
"gap": 6,
|
||||
},
|
||||
"children": []any{
|
||||
createUnifiedBadgeFromKind("ns-badge", "Namespace", "namespace", BadgeSizeMedium),
|
||||
createUnifiedBadgeFromKind("ns-badge", "Namespace"),
|
||||
antdLink("namespace-link",
|
||||
"{reqsJsonPath[0]['.metadata.namespace']['-']}",
|
||||
"/openapi-ui/{2}/{reqsJsonPath[0]['.metadata.namespace']['-']}/factory/marketplace",
|
||||
@@ -1396,7 +1397,7 @@ func CreateAllFactories() []*dashboardv1alpha1.Factory {
|
||||
"clusterNamePartOfUrl": "{2}",
|
||||
"customizationId": "factory-details-v1alpha1.cozystack.io.workloads",
|
||||
"fetchUrl": "/api/clusters/{2}/k8s/apis/cozystack.io/v1alpha1/namespaces/{3}/workloads",
|
||||
"labelsSelector": map[string]any{
|
||||
"labelSelector": map[string]any{
|
||||
"workloads.cozystack.io/monitor": "{reqs[0]['metadata','name']}",
|
||||
},
|
||||
"pathToItems": []any{"items"},
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package dashboard
|
||||
|
||||
import "strings"
|
||||
|
||||
// ---------------- UI helpers (use float64 for numeric fields) ----------------
|
||||
|
||||
func contentCard(id string, style map[string]any, children []any) map[string]any {
|
||||
@@ -200,10 +198,10 @@ func createBadge(id, text, color, title string) map[string]any {
|
||||
|
||||
// createBadgeFromKind creates a badge using the existing badge generation functions
|
||||
func createBadgeFromKind(id, kind, title string) map[string]any {
|
||||
return createUnifiedBadgeFromKind(id, kind, title, BadgeSizeMedium)
|
||||
return createUnifiedBadgeFromKind(id, kind)
|
||||
}
|
||||
|
||||
// createHeaderBadge creates a badge specifically for headers with consistent styling
|
||||
func createHeaderBadge(id, kind, plural string) map[string]any {
|
||||
return createUnifiedBadgeFromKind(id, kind, strings.ToLower(plural), BadgeSizeLarge)
|
||||
return createUnifiedBadgeFromKind(id, kind)
|
||||
}
|
||||
|
||||
@@ -81,86 +81,47 @@ func isAlphanumeric(c byte) bool {
|
||||
|
||||
// BadgeConfig holds configuration for badge generation
|
||||
type BadgeConfig struct {
|
||||
Text string
|
||||
Color string
|
||||
Title string
|
||||
Size BadgeSize
|
||||
Kind string // Resource kind in PascalCase (e.g., "VirtualMachine") - used for value and auto-generation
|
||||
Text string // Optional abbreviation override (if empty, ResourceBadge auto-generates from Kind)
|
||||
Color string // Optional custom backgroundColor override
|
||||
}
|
||||
|
||||
// BadgeSize represents the size of the badge
|
||||
type BadgeSize int
|
||||
|
||||
const (
|
||||
BadgeSizeSmall BadgeSize = iota
|
||||
BadgeSizeMedium
|
||||
BadgeSizeLarge
|
||||
)
|
||||
|
||||
// generateBadgeConfig creates a BadgeConfig from kind and optional custom values
|
||||
func generateBadgeConfig(kind string, customText, customColor, customTitle string) BadgeConfig {
|
||||
config := BadgeConfig{
|
||||
Text: initialsFromKind(kind),
|
||||
Color: hexColorForKind(kind),
|
||||
Title: strings.ToLower(kind),
|
||||
Size: BadgeSizeMedium,
|
||||
}
|
||||
|
||||
// Override with custom values if provided
|
||||
if customText != "" {
|
||||
config.Text = customText
|
||||
}
|
||||
if customColor != "" {
|
||||
config.Color = customColor
|
||||
}
|
||||
if customTitle != "" {
|
||||
config.Title = customTitle
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// createUnifiedBadge creates a badge using the unified BadgeConfig
|
||||
// createUnifiedBadge creates a badge using the unified BadgeConfig with ResourceBadge component
|
||||
func createUnifiedBadge(id string, config BadgeConfig) map[string]any {
|
||||
fontSize := "15px"
|
||||
if config.Size == BadgeSizeLarge {
|
||||
fontSize = "20px"
|
||||
} else if config.Size == BadgeSizeSmall {
|
||||
fontSize = "12px"
|
||||
data := map[string]any{
|
||||
"id": id,
|
||||
"value": config.Kind,
|
||||
}
|
||||
|
||||
// Add abbreviation override if specified (otherwise ResourceBadge auto-generates from Kind)
|
||||
if config.Text != "" {
|
||||
data["abbreviation"] = config.Text
|
||||
}
|
||||
|
||||
// Add custom color if specified
|
||||
if config.Color != "" {
|
||||
data["style"] = map[string]any{
|
||||
"backgroundColor": config.Color,
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"type": "antdText",
|
||||
"data": map[string]any{
|
||||
"id": id,
|
||||
"text": config.Text,
|
||||
"title": config.Title,
|
||||
"style": map[string]any{
|
||||
"backgroundColor": config.Color,
|
||||
"borderRadius": "20px",
|
||||
"color": "#fff",
|
||||
"display": "inline-block",
|
||||
"fontFamily": "RedHatDisplay, Overpass, overpass, helvetica, arial, sans-serif",
|
||||
"fontSize": fontSize,
|
||||
"fontWeight": float64(400),
|
||||
"lineHeight": "24px",
|
||||
"minWidth": float64(24),
|
||||
"padding": "0 9px",
|
||||
"textAlign": "center",
|
||||
"whiteSpace": "nowrap",
|
||||
},
|
||||
},
|
||||
"type": "ResourceBadge",
|
||||
"data": data,
|
||||
}
|
||||
}
|
||||
|
||||
// createUnifiedBadgeFromKind creates a badge from kind with automatic color generation
|
||||
func createUnifiedBadgeFromKind(id, kind, title string, size BadgeSize) map[string]any {
|
||||
config := BadgeConfig{
|
||||
Text: initialsFromKind(kind),
|
||||
Color: hexColorForKind(kind),
|
||||
Title: title,
|
||||
Size: size,
|
||||
// createUnifiedBadgeFromKind creates a badge from kind with ResourceBadge component
|
||||
// Abbreviation is auto-generated by ResourceBadge from kind, but can be customized if needed
|
||||
func createUnifiedBadgeFromKind(id, kind string) map[string]any {
|
||||
return map[string]any{
|
||||
"type": "ResourceBadge",
|
||||
"data": map[string]any{
|
||||
"id": id,
|
||||
"value": kind,
|
||||
// abbreviation is optional - ResourceBadge auto-generates from value
|
||||
},
|
||||
}
|
||||
return createUnifiedBadge(id, config)
|
||||
}
|
||||
|
||||
// ---------------- Resource creation helpers with unified approach ----------------
|
||||
@@ -183,7 +144,9 @@ func createResourceConfig(components []string, kind, title string) ResourceConfi
|
||||
metadataName := generateMetadataName(specID)
|
||||
|
||||
// Generate badge config
|
||||
badgeConfig := generateBadgeConfig(kind, "", "", title)
|
||||
badgeConfig := BadgeConfig{
|
||||
Kind: kind,
|
||||
}
|
||||
|
||||
return ResourceConfig{
|
||||
SpecID: specID,
|
||||
@@ -196,35 +159,6 @@ func createResourceConfig(components []string, kind, title string) ResourceConfi
|
||||
|
||||
// ---------------- Enhanced color generation ----------------
|
||||
|
||||
// getColorForKind returns a color for a specific kind with improved distribution
|
||||
func getColorForKind(kind string) string {
|
||||
// Use existing hexColorForKind function
|
||||
return hexColorForKind(kind)
|
||||
}
|
||||
|
||||
// getColorForType returns a color for a specific type (like "namespace", "service", etc.)
|
||||
func getColorForType(typeName string) string {
|
||||
// Map common types to specific colors for consistency
|
||||
colorMap := map[string]string{
|
||||
"namespace": "#a25792ff",
|
||||
"service": "#6ca100",
|
||||
"pod": "#009596",
|
||||
"node": "#8476d1",
|
||||
"secret": "#c46100",
|
||||
"configmap": "#b48c78ff",
|
||||
"ingress": "#2e7dff",
|
||||
"workloadmonitor": "#c46100",
|
||||
"module": "#8b5cf6",
|
||||
}
|
||||
|
||||
if color, exists := colorMap[strings.ToLower(typeName)]; exists {
|
||||
return color
|
||||
}
|
||||
|
||||
// Fall back to hash-based color generation
|
||||
return hexColorForKind(typeName)
|
||||
}
|
||||
|
||||
// ---------------- Automatic ID generation for UI elements ----------------
|
||||
|
||||
// generateElementID creates an ID for UI elements based on context and type
|
||||
@@ -282,7 +216,6 @@ type UnifiedResourceConfig struct {
|
||||
Title string
|
||||
Color string
|
||||
BadgeText string
|
||||
Size BadgeSize
|
||||
}
|
||||
|
||||
// createUnifiedFactory creates a factory using unified approach
|
||||
@@ -292,16 +225,9 @@ func createUnifiedFactory(config UnifiedResourceConfig, tabs []any, urlsToFetch
|
||||
|
||||
// Create header with unified badge
|
||||
badgeConfig := BadgeConfig{
|
||||
Kind: config.Kind,
|
||||
Text: config.BadgeText,
|
||||
Color: config.Color,
|
||||
Title: config.Title,
|
||||
Size: config.Size,
|
||||
}
|
||||
if badgeConfig.Text == "" {
|
||||
badgeConfig.Text = initialsFromKind(config.Kind)
|
||||
}
|
||||
if badgeConfig.Color == "" {
|
||||
badgeConfig.Color = getColorForKind(config.Kind)
|
||||
}
|
||||
|
||||
badge := createUnifiedBadge(generateBadgeID("header", config.Kind), badgeConfig)
|
||||
@@ -348,7 +274,9 @@ func createUnifiedFactory(config UnifiedResourceConfig, tabs []any, urlsToFetch
|
||||
|
||||
// createUnifiedCustomColumn creates a custom column using unified approach
|
||||
func createUnifiedCustomColumn(name, jsonPath, kind, title, href string) map[string]any {
|
||||
badgeConfig := generateBadgeConfig(kind, "", "", title)
|
||||
badgeConfig := BadgeConfig{
|
||||
Kind: kind,
|
||||
}
|
||||
badge := createUnifiedBadge(generateBadgeID("column", kind), badgeConfig)
|
||||
|
||||
linkID := generateLinkID("column", "name")
|
||||
|
||||
@@ -38,6 +38,9 @@ func (l *LineageControllerWebhook) Map(hr *helmv2.HelmRelease) (string, string,
|
||||
if !ok {
|
||||
return "", "", "", fmt.Errorf("failed to load chart-app mapping from config")
|
||||
}
|
||||
if hr.Spec.Chart == nil {
|
||||
return "", "", "", fmt.Errorf("cannot map helm release %s/%s to dynamic app", hr.Namespace, hr.Name)
|
||||
}
|
||||
s := hr.Spec.Chart.Spec
|
||||
val, ok := cfg.chartAppMap[chartRef{s.SourceRef.Name, s.Chart}]
|
||||
if !ok {
|
||||
|
||||
@@ -26,6 +26,13 @@ var (
|
||||
AncestryAmbiguous = fmt.Errorf("object ancestry is ambiguous")
|
||||
)
|
||||
|
||||
const (
|
||||
ManagedObjectKey = "internal.cozystack.io/managed-by-cozystack"
|
||||
ManagerGroupKey = "apps.cozystack.io/application.group"
|
||||
ManagerKindKey = "apps.cozystack.io/application.kind"
|
||||
ManagerNameKey = "apps.cozystack.io/application.name"
|
||||
)
|
||||
|
||||
// getResourceSelectors returns the appropriate CozystackResourceDefinitionResources for a given GroupKind
|
||||
func (h *LineageControllerWebhook) getResourceSelectors(gk schema.GroupKind, crd *cozyv1alpha1.CozystackResourceDefinition) *cozyv1alpha1.CozystackResourceDefinitionResources {
|
||||
switch {
|
||||
@@ -91,7 +98,7 @@ func (h *LineageControllerWebhook) Handle(ctx context.Context, req admission.Req
|
||||
labels, err := h.computeLabels(ctx, obj)
|
||||
for {
|
||||
if err != nil && errors.Is(err, NoAncestors) {
|
||||
return admission.Allowed("object not managed by app")
|
||||
break // not a problem, mark object as unmanaged
|
||||
}
|
||||
if err != nil && errors.Is(err, AncestryAmbiguous) {
|
||||
warn = append(warn, "object ancestry ambiguous, using first ancestor found")
|
||||
@@ -119,7 +126,7 @@ func (h *LineageControllerWebhook) Handle(ctx context.Context, req admission.Req
|
||||
func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstructured.Unstructured) (map[string]string, error) {
|
||||
owners := lineage.WalkOwnershipGraph(ctx, h.dynClient, h.mapper, h, o)
|
||||
if len(owners) == 0 {
|
||||
return nil, NoAncestors
|
||||
return map[string]string{ManagedObjectKey: "false"}, NoAncestors
|
||||
}
|
||||
obj, err := owners[0].GetUnstructured(ctx, h.dynClient, h.mapper)
|
||||
if err != nil {
|
||||
@@ -135,7 +142,8 @@ func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstruc
|
||||
}
|
||||
labels := map[string]string{
|
||||
// truncate apigroup to first 63 chars
|
||||
"apps.cozystack.io/application.group": func(s string) string {
|
||||
ManagedObjectKey: "true",
|
||||
ManagerGroupKey: func(s string) string {
|
||||
if len(s) < 63 {
|
||||
return s
|
||||
}
|
||||
@@ -145,8 +153,8 @@ func (h *LineageControllerWebhook) computeLabels(ctx context.Context, o *unstruc
|
||||
}
|
||||
return s
|
||||
}(gv.Group),
|
||||
"apps.cozystack.io/application.kind": obj.GetKind(),
|
||||
"apps.cozystack.io/application.name": obj.GetName(),
|
||||
ManagerKindKey: obj.GetKind(),
|
||||
ManagerNameKey: obj.GetName(),
|
||||
}
|
||||
templateLabels := map[string]string{
|
||||
"kind": strings.ToLower(obj.GetKind()),
|
||||
|
||||
@@ -23,53 +23,53 @@ For more details, read [Restic: Effective Backup from Stdin](https://blog.aenix.
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of Clickhouse replicas | `int` | `2` |
|
||||
| `shards` | Number of Clickhouse shards | `int` | `1` |
|
||||
| `resources` | Explicit CPU and memory configuration for each Clickhouse replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------- |
|
||||
| `replicas` | Number of ClickHouse replicas. | `int` | `2` |
|
||||
| `shards` | Number of ClickHouse shards. | `int` | `1` |
|
||||
| `resources` | Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` |
|
||||
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | ------------------------------------------------------------ | ------------------- | ------- |
|
||||
| `logStorageSize` | Size of Persistent Volume for logs | `quantity` | `2Gi` |
|
||||
| `logTTL` | TTL (expiration time) for `query_log` and `query_thread_log` | `int` | `15` |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| `users[name].readonly` | User is `readonly`, default is `false`. | `*bool` | `null` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | ------------------------------------------------------------- | ------------------- | ------- |
|
||||
| `logStorageSize` | Size of Persistent Volume for logs. | `quantity` | `2Gi` |
|
||||
| `logTTL` | TTL (expiration time) for `query_log` and `query_thread_log`. | `int` | `15` |
|
||||
| `users` | Users configuration map. | `map[string]object` | `{}` |
|
||||
| `users[name].password` | Password for the user. | `string` | `""` |
|
||||
| `users[name].readonly` | User is readonly (default: false). | `bool` | `false` |
|
||||
|
||||
|
||||
### Backup parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------- | -------- | ------------------------------------------------------ |
|
||||
| `backup` | Backup configuration | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups, default is `false` | `bool` | `false` |
|
||||
| `backup.s3Region` | AWS S3 region where backups are stored | `string` | `us-east-1` |
|
||||
| `backup.s3Bucket` | S3 bucket used for storing backups | `string` | `s3.example.org/clickhouse-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `string` | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | Retention strategy for cleaning up old backups | `string` | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `string` | `<your-secret-key>` |
|
||||
| `backup.resticPassword` | Password for Restic backup encryption | `string` | `<password>` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ----------------------------------------------- | -------- | ------------------------------------------------------ |
|
||||
| `backup` | Backup configuration. | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups (default: false). | `bool` | `false` |
|
||||
| `backup.s3Region` | AWS S3 region where backups are stored. | `string` | `us-east-1` |
|
||||
| `backup.s3Bucket` | S3 bucket used for storing backups. | `string` | `s3.example.org/clickhouse-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | Retention strategy for cleaning up old backups. | `string` | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3 authentication. | `string` | `<your-secret-key>` |
|
||||
| `backup.resticPassword` | Password for Restic backup encryption. | `string` | `<password>` |
|
||||
|
||||
|
||||
### Clickhouse Keeper parameters
|
||||
### ClickHouse Keeper parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `clickhouseKeeper` | Clickhouse Keeper configuration | `*object` | `null` |
|
||||
| `clickhouseKeeper.enabled` | Deploy ClickHouse Keeper for cluster coordination | `*bool` | `true` |
|
||||
| `clickhouseKeeper.size` | Persistent Volume Claim size, available for application data | `*quantity` | `1Gi` |
|
||||
| `clickhouseKeeper.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `micro` |
|
||||
| `clickhouseKeeper.replicas` | Number of Keeper replicas | `*int` | `3` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------------------- | ------------------------------------------------------------ | ---------- | ------- |
|
||||
| `clickhouseKeeper` | ClickHouse Keeper configuration. | `object` | `{}` |
|
||||
| `clickhouseKeeper.enabled` | Deploy ClickHouse Keeper for cluster coordination. | `bool` | `true` |
|
||||
| `clickhouseKeeper.size` | Persistent Volume Claim size available for application data. | `quantity` | `1Gi` |
|
||||
| `clickhouseKeeper.resourcesPreset` | Default sizing preset. | `string` | `micro` |
|
||||
| `clickhouseKeeper.replicas` | Number of Keeper replicas. | `int` | `3` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup": {
|
||||
"description": "Backup configuration",
|
||||
"description": "Backup configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -18,67 +18,64 @@
|
||||
],
|
||||
"properties": {
|
||||
"cleanupStrategy": {
|
||||
"description": "Retention strategy for cleaning up old backups",
|
||||
"description": "Retention strategy for cleaning up old backups.",
|
||||
"type": "string",
|
||||
"default": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Enable regular backups, default is `false`",
|
||||
"description": "Enable regular backups (default: false).",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"resticPassword": {
|
||||
"description": "Password for Restic backup encryption",
|
||||
"description": "Password for Restic backup encryption.",
|
||||
"type": "string",
|
||||
"default": "\u003cpassword\u003e"
|
||||
},
|
||||
"s3AccessKey": {
|
||||
"description": "Access key for S3, used for authentication",
|
||||
"description": "Access key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-access-key\u003e"
|
||||
},
|
||||
"s3Bucket": {
|
||||
"description": "S3 bucket used for storing backups",
|
||||
"description": "S3 bucket used for storing backups.",
|
||||
"type": "string",
|
||||
"default": "s3.example.org/clickhouse-backups"
|
||||
},
|
||||
"s3Region": {
|
||||
"description": "AWS S3 region where backups are stored",
|
||||
"description": "AWS S3 region where backups are stored.",
|
||||
"type": "string",
|
||||
"default": "us-east-1"
|
||||
},
|
||||
"s3SecretKey": {
|
||||
"description": "Secret key for S3, used for authentication",
|
||||
"description": "Secret key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-secret-key\u003e"
|
||||
},
|
||||
"schedule": {
|
||||
"description": "Cron schedule for automated backups",
|
||||
"description": "Cron schedule for automated backups.",
|
||||
"type": "string",
|
||||
"default": "0 2 * * *"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clickhouseKeeper": {
|
||||
"description": "Clickhouse Keeper configuration",
|
||||
"description": "ClickHouse Keeper configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"resourcesPreset"
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Deploy ClickHouse Keeper for cluster coordination",
|
||||
"description": "Deploy ClickHouse Keeper for cluster coordination.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of Keeper replicas",
|
||||
"description": "Number of Keeper replicas.",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
@@ -92,7 +89,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "1Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -108,7 +105,7 @@
|
||||
}
|
||||
},
|
||||
"logStorageSize": {
|
||||
"description": "Size of Persistent Volume for logs",
|
||||
"description": "Size of Persistent Volume for logs.",
|
||||
"default": "2Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -122,22 +119,22 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"logTTL": {
|
||||
"description": "TTL (expiration time) for `query_log` and `query_thread_log`",
|
||||
"description": "TTL (expiration time) for `query_log` and `query_thread_log`.",
|
||||
"type": "integer",
|
||||
"default": 15
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of Clickhouse replicas",
|
||||
"description": "Number of ClickHouse replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each Clickhouse replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -150,7 +147,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -165,7 +162,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "small",
|
||||
"enum": [
|
||||
@@ -179,12 +176,12 @@
|
||||
]
|
||||
},
|
||||
"shards": {
|
||||
"description": "Number of Clickhouse shards",
|
||||
"description": "Number of ClickHouse shards.",
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -198,22 +195,23 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"description": "Users configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"description": "Password for the user.",
|
||||
"type": "string"
|
||||
},
|
||||
"readonly": {
|
||||
"description": "User is `readonly`, default is `false`.",
|
||||
"description": "User is readonly (default: false).",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,54 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of Clickhouse replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each ClickHouse replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of ClickHouse replicas.
|
||||
replicas: 2
|
||||
## @param shards {int} Number of Clickhouse shards
|
||||
|
||||
## @param {int} shards - Number of ClickHouse shards.
|
||||
shards: 1
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each Clickhouse replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each ClickHouse replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
|
||||
|
||||
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
## @param {ResourcesPreset} resourcesPreset="small" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "small"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
|
||||
## @param {quantity} size - Persistent Volume Claim size available for application data.
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param logStorageSize {quantity} Size of Persistent Volume for logs
|
||||
|
||||
## @param {quantity} logStorageSize - Size of Persistent Volume for logs.
|
||||
logStorageSize: 2Gi
|
||||
## @param logTTL {int} TTL (expiration time) for `query_log` and `query_thread_log`
|
||||
|
||||
## @param {int} logTTL - TTL (expiration time) for `query_log` and `query_thread_log`.
|
||||
logTTL: 15
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {*string} Password for the user
|
||||
## @field user.readonly {*bool} User is `readonly`, default is `false`.
|
||||
|
||||
## @typedef {struct} User - User configuration.
|
||||
## @field {string} [password] - Password for the user.
|
||||
## @field {bool} [readonly] - User is readonly (default: false).
|
||||
|
||||
## @param {map[string]User} users - Users configuration map.
|
||||
users: {}
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
@@ -39,20 +57,22 @@ logTTL: 15
|
||||
## readonly: true
|
||||
## password: hackme
|
||||
##
|
||||
users: {}
|
||||
|
||||
|
||||
##
|
||||
## @section Backup parameters
|
||||
##
|
||||
|
||||
## @param backup {backup} Backup configuration
|
||||
## @field backup.enabled {bool} Enable regular backups, default is `false`
|
||||
## @field backup.s3Region {string} AWS S3 region where backups are stored
|
||||
## @field backup.s3Bucket {string} S3 bucket used for storing backups
|
||||
## @field backup.schedule {string} Cron schedule for automated backups
|
||||
## @field backup.cleanupStrategy {string} Retention strategy for cleaning up old backups
|
||||
## @field backup.s3AccessKey {string} Access key for S3, used for authentication
|
||||
## @field backup.s3SecretKey {string} Secret key for S3, used for authentication
|
||||
## @field backup.resticPassword {string} Password for Restic backup encryption
|
||||
## @typedef {struct} Backup - Backup configuration.
|
||||
## @field {bool} enabled - Enable regular backups (default: false).
|
||||
## @field {string} s3Region - AWS S3 region where backups are stored.
|
||||
## @field {string} s3Bucket - S3 bucket used for storing backups.
|
||||
## @field {string} schedule - Cron schedule for automated backups.
|
||||
## @field {string} cleanupStrategy - Retention strategy for cleaning up old backups.
|
||||
## @field {string} s3AccessKey - Access key for S3 authentication.
|
||||
## @field {string} s3SecretKey - Secret key for S3 authentication.
|
||||
## @field {string} resticPassword - Password for Restic backup encryption.
|
||||
|
||||
## @param {Backup} backup - Backup configuration.
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
@@ -63,13 +83,17 @@ backup:
|
||||
s3SecretKey: "<your-secret-key>"
|
||||
resticPassword: "<password>"
|
||||
|
||||
##
|
||||
## @section ClickHouse Keeper parameters
|
||||
##
|
||||
|
||||
## @section Clickhouse Keeper parameters
|
||||
## @param clickhouseKeeper {*clickhouseKeeper} Clickhouse Keeper configuration
|
||||
## @field clickhouseKeeper.enabled {*bool} Deploy ClickHouse Keeper for cluster coordination
|
||||
## @field clickhouseKeeper.size {*quantity} Persistent Volume Claim size, available for application data
|
||||
## @field clickhouseKeeper.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
## @field clickhouseKeeper.replicas {*int} Number of Keeper replicas
|
||||
## @typedef {struct} ClickHouseKeeper - ClickHouse Keeper configuration.
|
||||
## @field {bool} [enabled] - Deploy ClickHouse Keeper for cluster coordination.
|
||||
## @field {quantity} [size] - Persistent Volume Claim size available for application data.
|
||||
## @field {ResourcesPreset} [resourcesPreset] - Default sizing preset.
|
||||
## @field {int} [replicas] - Number of Keeper replicas.
|
||||
|
||||
## @param {ClickHouseKeeper} clickhouseKeeper - ClickHouse Keeper configuration.
|
||||
clickhouseKeeper:
|
||||
enabled: true
|
||||
size: 1Gi
|
||||
|
||||
@@ -8,51 +8,51 @@ Internally, FerretDB service is backed by Postgres.
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of replicas | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each FerretDB replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `micro` |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `replicas` | Number of replicas. | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each FerretDB replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `micro` |
|
||||
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------- |
|
||||
| `quorum` | Configuration for the quorum-based synchronous replication | `object` | `{}` |
|
||||
| `quorum.minSyncReplicas` | Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed | `int` | `0` |
|
||||
| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the total number of replicas) | `int` | `0` |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------------------------------------------- | ------------------- | ----- |
|
||||
| `quorum` | Configuration for quorum-based synchronous replication. | `object` | `{}` |
|
||||
| `quorum.minSyncReplicas` | Minimum number of synchronous replicas required for commit. | `int` | `0` |
|
||||
| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas allowed (must be less than total replicas). | `int` | `0` |
|
||||
| `users` | Users configuration map. | `map[string]object` | `{}` |
|
||||
| `users[name].password` | Password for the user. | `string` | `""` |
|
||||
|
||||
|
||||
### Backup parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------------------- | -------- | ----------------------------------- |
|
||||
| `backup` | Backup configuration | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups, default is `false`. | `bool` | `false` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `string` | `0 2 * * * *` |
|
||||
| `backup.retentionPolicy` | Retention policy | `string` | `30d` |
|
||||
| `backup.endpointURL` | S3 Endpoint used to upload data to the cloud | `string` | `http://minio-gateway-service:9000` |
|
||||
| `backup.destinationPath` | Path to store the backup (i.e. s3://bucket/path/to/folder) | `string` | `s3://bucket/path/to/folder/` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `string` | `<your-secret-key>` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ------------------------------------------------------------ | -------- | ----------------------------------- |
|
||||
| `backup` | Backup configuration. | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups (default: false). | `bool` | `false` |
|
||||
| `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * * *` |
|
||||
| `backup.retentionPolicy` | Retention policy. | `string` | `30d` |
|
||||
| `backup.endpointURL` | S3 endpoint URL for uploads. | `string` | `http://minio-gateway-service:9000` |
|
||||
| `backup.destinationPath` | Path to store the backup (e.g. s3://bucket/path/to/folder/). | `string` | `s3://bucket/path/to/folder/` |
|
||||
| `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3 authentication. | `string` | `<your-secret-key>` |
|
||||
|
||||
|
||||
### Bootstrap (recovery) parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | --------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
|
||||
| `bootstrap` | Bootstrap (recovery) configuration | `object` | `{}` |
|
||||
| `bootstrap.enabled` | Restore database cluster from a backup | `*bool` | `false` |
|
||||
| `bootstrap.recoveryTime` | Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest. | `*string` | `""` |
|
||||
| `bootstrap.oldName` | Name of database cluster before deleting | `*string` | `""` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ------------------------------------------------------------------- | -------- | ------- |
|
||||
| `bootstrap` | Bootstrap configuration. | `object` | `{}` |
|
||||
| `bootstrap.enabled` | Restore database cluster from a backup. | `bool` | `false` |
|
||||
| `bootstrap.recoveryTime` | Timestamp (RFC3339) for point-in-time recovery; empty means latest. | `string` | `""` |
|
||||
| `bootstrap.oldName` | Name of database cluster before deletion. | `string` | `""` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup": {
|
||||
"description": "Backup configuration",
|
||||
"description": "Backup configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -17,69 +17,71 @@
|
||||
],
|
||||
"properties": {
|
||||
"destinationPath": {
|
||||
"description": "Path to store the backup (i.e. s3://bucket/path/to/folder)",
|
||||
"description": "Path to store the backup (e.g. s3://bucket/path/to/folder/).",
|
||||
"type": "string",
|
||||
"default": "s3://bucket/path/to/folder/"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Enable regular backups, default is `false`.",
|
||||
"description": "Enable regular backups (default: false).",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"endpointURL": {
|
||||
"description": "S3 Endpoint used to upload data to the cloud",
|
||||
"description": "S3 endpoint URL for uploads.",
|
||||
"type": "string",
|
||||
"default": "http://minio-gateway-service:9000"
|
||||
},
|
||||
"retentionPolicy": {
|
||||
"description": "Retention policy",
|
||||
"description": "Retention policy.",
|
||||
"type": "string",
|
||||
"default": "30d"
|
||||
},
|
||||
"s3AccessKey": {
|
||||
"description": "Access key for S3, used for authentication",
|
||||
"description": "Access key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-access-key\u003e"
|
||||
},
|
||||
"s3SecretKey": {
|
||||
"description": "Secret key for S3, used for authentication",
|
||||
"description": "Secret key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-secret-key\u003e"
|
||||
},
|
||||
"schedule": {
|
||||
"description": "Cron schedule for automated backups",
|
||||
"description": "Cron schedule for automated backups.",
|
||||
"type": "string",
|
||||
"default": "0 2 * * * *"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bootstrap": {
|
||||
"description": "Bootstrap (recovery) configuration",
|
||||
"description": "Bootstrap configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Restore database cluster from a backup",
|
||||
"description": "Restore database cluster from a backup.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"oldName": {
|
||||
"description": "Name of database cluster before deleting",
|
||||
"type": "string"
|
||||
"description": "Name of database cluster before deletion.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"recoveryTime": {
|
||||
"description": "Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest.",
|
||||
"type": "string"
|
||||
"description": "Timestamp (RFC3339) for point-in-time recovery; empty means latest.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"quorum": {
|
||||
"description": "Configuration for the quorum-based synchronous replication",
|
||||
"description": "Configuration for quorum-based synchronous replication.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -88,29 +90,29 @@
|
||||
],
|
||||
"properties": {
|
||||
"maxSyncReplicas": {
|
||||
"description": "Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the total number of replicas)",
|
||||
"description": "Maximum number of synchronous replicas allowed (must be less than total replicas).",
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"minSyncReplicas": {
|
||||
"description": "Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed",
|
||||
"description": "Minimum number of synchronous replicas required for commit.",
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of replicas",
|
||||
"description": "Number of replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each FerretDB replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each FerretDB replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -123,7 +125,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -138,7 +140,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
@@ -152,7 +154,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -166,18 +168,19 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"description": "Users configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"description": "Password for the user.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,56 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each FerretDB replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of replicas.
|
||||
replicas: 2
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each FerretDB replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each FerretDB replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
## @param {ResourcesPreset} resourcesPreset="micro" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "micro"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
|
||||
## @param {quantity} size - Persistent Volume Claim size available for application data.
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param quorum {quorum} Configuration for the quorum-based synchronous replication
|
||||
## @field quorum.minSyncReplicas {int} Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed
|
||||
## @field quorum.maxSyncReplicas {int} Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the total number of replicas)
|
||||
|
||||
## @typedef {struct} Quorum - Configuration for quorum-based synchronous replication.
|
||||
## @field {int} minSyncReplicas - Minimum number of synchronous replicas required for commit.
|
||||
## @field {int} maxSyncReplicas - Maximum number of synchronous replicas allowed (must be less than total replicas).
|
||||
|
||||
## @param {Quorum} quorum - Configuration for quorum-based synchronous replication.
|
||||
quorum:
|
||||
minSyncReplicas: 0
|
||||
maxSyncReplicas: 0
|
||||
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {*string} Password for the user
|
||||
## @typedef {struct} User - User configuration.
|
||||
## @field {string} [password] - Password for the user.
|
||||
|
||||
## @param {map[string]User} users - Users configuration map.
|
||||
users: {}
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
@@ -37,21 +58,21 @@ quorum:
|
||||
## user2:
|
||||
## password: hackme
|
||||
##
|
||||
users: {}
|
||||
|
||||
|
||||
|
||||
##
|
||||
## @section Backup parameters
|
||||
##
|
||||
|
||||
## @param backup {backup} Backup configuration
|
||||
## @field backup.enabled {bool} Enable regular backups, default is `false`.
|
||||
## @field backup.schedule {string} Cron schedule for automated backups
|
||||
## @field backup.retentionPolicy {string} Retention policy
|
||||
## @field backup.endpointURL {string} S3 Endpoint used to upload data to the cloud
|
||||
## @field backup.destinationPath {string} Path to store the backup (i.e. s3://bucket/path/to/folder)
|
||||
## @field backup.s3AccessKey {string} Access key for S3, used for authentication
|
||||
## @field backup.s3SecretKey {string} Secret key for S3, used for authentication
|
||||
## @typedef {struct} Backup - Backup configuration.
|
||||
## @field {bool} enabled - Enable regular backups (default: false).
|
||||
## @field {string} schedule - Cron schedule for automated backups.
|
||||
## @field {string} retentionPolicy - Retention policy.
|
||||
## @field {string} endpointURL - S3 endpoint URL for uploads.
|
||||
## @field {string} destinationPath - Path to store the backup (e.g. s3://bucket/path/to/folder/).
|
||||
## @field {string} s3AccessKey - Access key for S3 authentication.
|
||||
## @field {string} s3SecretKey - Secret key for S3 authentication.
|
||||
|
||||
## @param {Backup} backup - Backup configuration.
|
||||
backup:
|
||||
enabled: false
|
||||
schedule: "0 2 * * * *"
|
||||
@@ -61,18 +82,17 @@ backup:
|
||||
s3AccessKey: "<your-access-key>"
|
||||
s3SecretKey: "<your-secret-key>"
|
||||
|
||||
|
||||
##
|
||||
## @section Bootstrap (recovery) parameters
|
||||
##
|
||||
## @param bootstrap {bootstrap} Bootstrap (recovery) configuration
|
||||
## @field bootstrap.enabled {*bool} Restore database cluster from a backup
|
||||
## @field bootstrap.recoveryTime {*string} Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest.
|
||||
## @field bootstrap.oldName {*string} Name of database cluster before deleting
|
||||
##
|
||||
|
||||
## @typedef {struct} Bootstrap - Bootstrap configuration for restoring a database cluster from a backup.
|
||||
## @field {bool} [enabled] - Restore database cluster from a backup.
|
||||
## @field {string} [recoveryTime] - Timestamp (RFC3339) for point-in-time recovery; empty means latest.
|
||||
## @field {string} [oldName] - Name of database cluster before deletion.
|
||||
|
||||
## @param {Bootstrap} bootstrap - Bootstrap configuration.
|
||||
bootstrap:
|
||||
enabled: false
|
||||
# example: 2020-11-26 15:22:00.00000+00
|
||||
recoveryTime: ""
|
||||
oldName: ""
|
||||
|
||||
|
||||
|
||||
1
packages/apps/foundationdb/.helmignore
Normal file
1
packages/apps/foundationdb/.helmignore
Normal file
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
25
packages/apps/foundationdb/Chart.yaml
Normal file
25
packages/apps/foundationdb/Chart.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: v2
|
||||
name: foundationdb
|
||||
description: Managed FoundationDB service
|
||||
icon: /logos/foundationdb.svg
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "7.3.63"
|
||||
4
packages/apps/foundationdb/Makefile
Normal file
4
packages/apps/foundationdb/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
include ../../../scripts/package.mk
|
||||
|
||||
generate:
|
||||
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
|
||||
195
packages/apps/foundationdb/README.md
Normal file
195
packages/apps/foundationdb/README.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# FoundationDB
|
||||
|
||||
A managed FoundationDB service for Cozystack.
|
||||
|
||||
## Overview
|
||||
|
||||
FoundationDB is a distributed database designed to handle large volumes of structured data across clusters of commodity servers. It organizes data as an ordered key-value store and employs ACID transactions for all operations.
|
||||
|
||||
This package provides a managed FoundationDB cluster deployment using the FoundationDB Kubernetes Operator.
|
||||
|
||||
## Features
|
||||
|
||||
- **High Availability**: Multi-instance deployment with automatic failover
|
||||
- **ACID Transactions**: Full ACID transaction support across the cluster
|
||||
- **Scalable**: Easily scale storage and compute resources
|
||||
- **Backup Integration**: Optional S3-compatible backup storage
|
||||
- **Monitoring**: Built-in monitoring and alerting through WorkloadMonitor
|
||||
- **Flexible Configuration**: Support for custom FoundationDB parameters
|
||||
|
||||
## Configuration
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
```yaml
|
||||
# Cluster process configuration
|
||||
cluster:
|
||||
version: "7.3.63"
|
||||
processCounts:
|
||||
storage: 3 # Number of storage processes (determines cluster size)
|
||||
stateless: -1 # Automatically calculated
|
||||
cluster_controller: 1
|
||||
faultDomain:
|
||||
key: "kubernetes.io/hostname"
|
||||
valueFrom: "spec.nodeName"
|
||||
```
|
||||
|
||||
### Storage
|
||||
|
||||
```yaml
|
||||
storage:
|
||||
size: "16Gi" # Storage size per instance
|
||||
storageClass: "" # Storage class (optional)
|
||||
```
|
||||
|
||||
### Resources
|
||||
|
||||
```yaml
|
||||
# Use preset sizing
|
||||
resourcesPreset: "medium" # small, medium, large, xlarge, 2xlarge
|
||||
|
||||
# Or custom resource configuration
|
||||
resources:
|
||||
cpu: "2000m"
|
||||
memory: "4Gi"
|
||||
```
|
||||
|
||||
### Backup (Optional)
|
||||
|
||||
```yaml
|
||||
backup:
|
||||
enabled: true
|
||||
s3:
|
||||
bucket: "my-fdb-backups"
|
||||
endpoint: "https://s3.amazonaws.com"
|
||||
region: "us-east-1"
|
||||
credentials:
|
||||
accessKeyId: "AKIA..."
|
||||
secretAccessKey: "..."
|
||||
retentionPolicy: "7d"
|
||||
```
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
```yaml
|
||||
# Custom FoundationDB parameters
|
||||
customParameters:
|
||||
- "knob_disable_posix_kernel_aio=1"
|
||||
|
||||
# Image type (unified is default and recommended for new deployments)
|
||||
imageType: "unified"
|
||||
|
||||
# Enable automatic pod replacements
|
||||
automaticReplacements: true
|
||||
|
||||
# Security context configuration
|
||||
securityContext:
|
||||
runAsUser: 4059
|
||||
runAsGroup: 4059
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- FoundationDB Operator must be installed in the cluster
|
||||
- Sufficient storage and compute resources
|
||||
- For backups: S3-compatible storage credentials
|
||||
|
||||
## Deployment
|
||||
|
||||
1. Install the FoundationDB operator (system package)
|
||||
2. Deploy this application package with your desired configuration
|
||||
3. The cluster will be automatically provisioned and configured
|
||||
|
||||
## Monitoring
|
||||
|
||||
This package includes WorkloadMonitor integration for cluster health monitoring and resource tracking. Monitoring can be disabled by setting:
|
||||
|
||||
```yaml
|
||||
monitoring:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
- All containers run with restricted security contexts
|
||||
- No privilege escalation allowed
|
||||
- Read-only root filesystem where possible
|
||||
- Custom security context configurations supported
|
||||
|
||||
## Fault Tolerance
|
||||
|
||||
FoundationDB is designed for high availability:
|
||||
- Automatic failure detection and recovery
|
||||
- Data replication across instances
|
||||
- Configurable fault domains for rack/zone awareness
|
||||
- Transaction log redundancy
|
||||
|
||||
The included `WorkloadMonitor` is automatically configured based on the `cluster.redundancyMode` value. It sets the `minReplicas` property on the `WorkloadMonitor` resource to ensure the cluster's health status accurately reflects its fault tolerance level. The number of tolerated failures is as follows:
|
||||
- `single`: 0 failures
|
||||
- `double`: 1 failure
|
||||
- `triple` and datacenter-aware modes: 2 failures
|
||||
|
||||
For example, with the default configuration (`redundancyMode: double` and 3 storage pods), `minReplicas` will be set to 2.
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Use SSD storage for better performance
|
||||
- Consider dedicating nodes for storage processes
|
||||
- Monitor cluster metrics for optimization opportunities
|
||||
- Scale storage and stateless processes based on workload
|
||||
|
||||
## Support
|
||||
|
||||
For issues related to FoundationDB itself, refer to the [FoundationDB documentation](https://apple.github.io/foundationdb/).
|
||||
|
||||
For Cozystack-specific issues, consult the Cozystack documentation or support channels.
|
||||
|
||||
## Parameters
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------ |
|
||||
| `cluster` | Cluster configuration. | `object` | `{}` |
|
||||
| `cluster.processCounts` | Process counts for different roles. | `object` | `{}` |
|
||||
| `cluster.processCounts.stateless` | Number of stateless processes (-1 for automatic). | `int` | `-1` |
|
||||
| `cluster.processCounts.storage` | Number of storage processes (determines cluster size). | `int` | `3` |
|
||||
| `cluster.processCounts.cluster_controller` | Number of cluster controller processes. | `int` | `1` |
|
||||
| `cluster.version` | Version of FoundationDB to use. | `string` | `7.3.63` |
|
||||
| `cluster.redundancyMode` | Database redundancy mode (single, double, triple, three_datacenter, three_datacenter_fallback). | `string` | `double` |
|
||||
| `cluster.storageEngine` | Storage engine (ssd-2, ssd-redwood-v1, ssd-rocksdb-v1, memory). | `string` | `ssd-2` |
|
||||
| `cluster.faultDomain` | Fault domain configuration. | `object` | `{}` |
|
||||
| `cluster.faultDomain.key` | Fault domain key. | `string` | `kubernetes.io/hostname` |
|
||||
| `cluster.faultDomain.valueFrom` | Fault domain value source. | `string` | `spec.nodeName` |
|
||||
| `storage` | Storage configuration. | `object` | `{}` |
|
||||
| `storage.size` | Size of persistent volumes for each instance. | `quantity` | `16Gi` |
|
||||
| `storage.storageClass` | Storage class (if not set, uses cluster default). | `string` | `""` |
|
||||
| `resources` | Explicit CPU and memory configuration for each FoundationDB instance. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each instance. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each instance. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `medium` |
|
||||
| `backup` | Backup configuration. | `object` | `{}` |
|
||||
| `backup.enabled` | Enable backups. | `bool` | `false` |
|
||||
| `backup.s3` | S3 configuration for backups. | `object` | `{}` |
|
||||
| `backup.s3.bucket` | S3 bucket name. | `string` | `""` |
|
||||
| `backup.s3.endpoint` | S3 endpoint URL. | `string` | `""` |
|
||||
| `backup.s3.region` | S3 region. | `string` | `us-east-1` |
|
||||
| `backup.s3.credentials` | S3 credentials. | `object` | `{}` |
|
||||
| `backup.s3.credentials.accessKeyId` | S3 access key ID. | `string` | `""` |
|
||||
| `backup.s3.credentials.secretAccessKey` | S3 secret access key. | `string` | `""` |
|
||||
| `backup.retentionPolicy` | Retention policy for backups. | `string` | `7d` |
|
||||
| `monitoring` | Monitoring configuration. | `object` | `{}` |
|
||||
| `monitoring.enabled` | Enable WorkloadMonitor integration. | `bool` | `true` |
|
||||
|
||||
|
||||
### FoundationDB configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------------- | ------------------------------------------ | ---------- | --------- |
|
||||
| `customParameters` | Custom parameters to pass to FoundationDB. | `[]string` | `[]` |
|
||||
| `imageType` | Container image deployment type. | `string` | `unified` |
|
||||
| `securityContext` | Security context for containers. | `object` | `{}` |
|
||||
| `securityContext.runAsUser` | User ID to run the container. | `int` | `4059` |
|
||||
| `securityContext.runAsGroup` | Group ID to run the container. | `int` | `4059` |
|
||||
| `automaticReplacements` | Enable automatic pod replacements. | `bool` | `true` |
|
||||
|
||||
1
packages/apps/foundationdb/charts/cozy-lib
Symbolic link
1
packages/apps/foundationdb/charts/cozy-lib
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../library/cozy-lib
|
||||
106
packages/apps/foundationdb/logos/foundationdb.svg
Normal file
106
packages/apps/foundationdb/logos/foundationdb.svg
Normal file
@@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="144"
|
||||
height="144"
|
||||
viewBox="0 0 144 144"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="foundationdb.svg"
|
||||
inkscape:version="1.4.2 (unknown)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview4"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="6.0902778"
|
||||
inkscape:cx="72"
|
||||
inkscape:cy="72.492588"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1128"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<rect
|
||||
width="144"
|
||||
height="144"
|
||||
rx="24"
|
||||
fill="url(#paint0_linear_fdb)"
|
||||
id="rect1"
|
||||
style="fill:#ffffff" />
|
||||
<!-- FoundationDB Icon (scaled and positioned) -->
|
||||
<!-- FoundationDB Text -->
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="paint0_linear_fdb"
|
||||
x1="140"
|
||||
y1="130.5"
|
||||
x2="4"
|
||||
y2="9.49999"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#047BFE"
|
||||
id="stop3" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3F9AFB"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="g1134"
|
||||
transform="matrix(3.132791,0,0,3.132791,-115.98385,6.9294227)">
|
||||
<g
|
||||
transform="matrix(0.08541251,0,0,0.08541251,8.7615159,9.5962543)"
|
||||
id="g10">
|
||||
<polygon
|
||||
style="fill:#3f9afb"
|
||||
class="st0"
|
||||
points="457.2,150.5 457.2,98.6 561.4,124 561.6,164.8 666.6,150.9 666.3,98.7 845.8,143 846.4,189.9 667.4,165.8 560.6,177.3 457.1,165.4 354.2,177.6 354.1,165.7 "
|
||||
id="polygon4" />
|
||||
|
||||
<path
|
||||
style="fill:#0b70e0"
|
||||
inkscape:connector-curvature="0"
|
||||
class="st1"
|
||||
d="m 666.6,183.2 179.6,18.6 v 46 H 353.8 l -0.5,-12.2 h 103.5 c 0,0 0,-34.2 0,-52.3 34.8,3.4 103.8,10.2 103.8,10.2 v 40.9 h 106 z"
|
||||
id="path6" />
|
||||
|
||||
<path
|
||||
style="fill:#9eccfd"
|
||||
inkscape:connector-curvature="0"
|
||||
class="st2"
|
||||
d="m 561.4,109.1 -0.3,-12.6 c 0,0 68.1,-20.4 103.3,-30.8 0,-16.9 0,-33.2 0,-52.9 61.8,24.8 121.2,48.8 181.2,72.9 0,15 0,29.4 0,45.4 -61.5,-16.9 -121.7,-33.5 -180.2,-49.6 -35.6,9.5 -104,27.6 -104,27.6 z"
|
||||
id="path8" />
|
||||
|
||||
</g>
|
||||
<polygon
|
||||
transform="matrix(0.08541251,0,0,0.08541251,8.7795597,9.6869671)"
|
||||
style="fill:#3f9afb"
|
||||
class="st0"
|
||||
points="666.6,150.9 666.3,98.7 845.8,143 846.4,189.9 667.4,165.8 560.6,177.3 457.1,165.4 354.2,177.6 354.1,165.7 457.2,150.5 457.2,98.6 561.4,124 561.6,164.8 "
|
||||
id="polygon856" />
|
||||
<path
|
||||
style="fill:#0b70e0;stroke-width:0.0854125"
|
||||
inkscape:connector-curvature="0"
|
||||
class="st1"
|
||||
d="m 65.715539,25.334539 15.340087,1.588673 v 3.928975 h -42.05712 l -0.04271,-1.042033 h 8.840195 c 0,0 0,-2.921107 0,-4.467074 2.972356,0.290403 8.865819,0.871208 8.865819,0.871208 v 3.493371 h 9.053726 z"
|
||||
id="path858" />
|
||||
<path
|
||||
style="fill:#9eccfd;stroke-width:0.0854125"
|
||||
inkscape:connector-curvature="0"
|
||||
class="st2"
|
||||
d="m 56.730143,19.005472 -0.02562,-1.076198 c 0,0 5.816592,-1.742415 8.823112,-2.630705 0,-1.443471 0,-2.835695 0,-4.518322 5.278493,2.11823 10.351997,4.168131 15.476747,6.226572 0,1.281188 0,2.511128 0,3.877728 -5.252869,-1.443471 -10.394702,-2.861319 -15.391334,-4.23646 -3.040686,0.811419 -8.882901,2.357385 -8.882901,2.357385 z"
|
||||
id="path860" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
47
packages/apps/foundationdb/templates/_resources.tpl
Normal file
47
packages/apps/foundationdb/templates/_resources.tpl
Normal file
@@ -0,0 +1,47 @@
|
||||
{{/*
|
||||
Common resource definitions
|
||||
*/}}
|
||||
{{- define "foundationdb.resources" -}}
|
||||
{{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resources.preset .Values.resources $) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "foundationdb.labels" -}}
|
||||
helm.sh/chart: {{ include "foundationdb.chart" . }}
|
||||
{{ include "foundationdb.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "foundationdb.selectorLabels" -}}
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Chart name and version
|
||||
*/}}
|
||||
{{- define "foundationdb.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Calculate minReplicas for WorkloadMonitor based on redundancyMode
|
||||
*/}}
|
||||
{{- define "foundationdb.minReplicas" -}}
|
||||
{{- $replicas := .Values.cluster.processCounts.storage -}}
|
||||
{{- if or (eq .Values.cluster.redundancyMode "triple") (eq .Values.cluster.redundancyMode "three_data_hall") (eq .Values.cluster.redundancyMode "three_datacenter") (eq .Values.cluster.redundancyMode "three_datacenter_fallback") (eq .Values.cluster.redundancyMode "three_data_hall_fallback") }}
|
||||
{{- print (max 1 (sub $replicas 2)) -}}
|
||||
{{- else if eq .Values.cluster.redundancyMode "double" }}
|
||||
{{- print (max 1 (sub $replicas 1)) -}}
|
||||
{{- else }}
|
||||
{{- print $replicas -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
65
packages/apps/foundationdb/templates/backup.yaml
Normal file
65
packages/apps/foundationdb/templates/backup.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-s3-creds
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
type: Opaque
|
||||
data:
|
||||
AWS_ACCESS_KEY_ID: {{ .Values.backup.s3.credentials.accessKeyId | b64enc }}
|
||||
AWS_SECRET_ACCESS_KEY: {{ .Values.backup.s3.credentials.secretAccessKey | b64enc }}
|
||||
|
||||
---
|
||||
apiVersion: apps.foundationdb.org/v1beta2
|
||||
kind: FoundationDBBackup
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-backup
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
clusterName: {{ .Release.Name }}
|
||||
|
||||
backupState: Running
|
||||
|
||||
backupDeploymentSpec:
|
||||
podTemplateSpec:
|
||||
spec:
|
||||
containers:
|
||||
- name: foundationdb
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
|
||||
customParameters:
|
||||
- backup_agent_snapshot_mode=0
|
||||
|
||||
snapshotPeriodSeconds: 3600
|
||||
|
||||
blobStoreConfiguration:
|
||||
accountName: {{ .Values.backup.s3.bucket }}
|
||||
bucket: {{ .Values.backup.s3.bucket }}
|
||||
{{- if .Values.backup.s3.endpoint }}
|
||||
endpoint: {{ .Values.backup.s3.endpoint }}
|
||||
{{- end }}
|
||||
credentials:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-s3-creds
|
||||
key: AWS_ACCESS_KEY_ID
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
secretKeyRef:
|
||||
name: {{ .Release.Name }}-s3-creds
|
||||
key: AWS_SECRET_ACCESS_KEY
|
||||
{{- end }}
|
||||
98
packages/apps/foundationdb/templates/cluster.yaml
Normal file
98
packages/apps/foundationdb/templates/cluster.yaml
Normal file
@@ -0,0 +1,98 @@
|
||||
{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" | default (dict "data" (dict)) }}
|
||||
{{- $clusterDomain := index $cozyConfig.data "cluster-domain" | default "cozy.local" }}
|
||||
---
|
||||
apiVersion: apps.foundationdb.org/v1beta2
|
||||
kind: FoundationDBCluster
|
||||
metadata:
|
||||
name: {{ .Release.Name }}
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
version: {{ .Values.cluster.version | quote }}
|
||||
|
||||
databaseConfiguration:
|
||||
redundancy_mode: {{ .Values.cluster.redundancyMode }}
|
||||
storage_engine: {{ .Values.cluster.storageEngine }}
|
||||
|
||||
processCounts:
|
||||
{{- toYaml .Values.cluster.processCounts | nindent 4 }}
|
||||
|
||||
automationOptions:
|
||||
replacements:
|
||||
enabled: {{ .Values.automaticReplacements }}
|
||||
faultDomain:
|
||||
key: {{ .Values.cluster.faultDomain.key }}
|
||||
{{- if .Values.cluster.faultDomain.valueFrom }}
|
||||
valueFrom: {{ .Values.cluster.faultDomain.valueFrom }}
|
||||
{{- end }}
|
||||
imageType: {{ .Values.imageType }}
|
||||
labels:
|
||||
filterOnOwnerReference: false
|
||||
matchLabels:
|
||||
foundationdb.org/fdb-cluster-name: {{ .Release.Name }}
|
||||
processClassLabels:
|
||||
- foundationdb.org/fdb-process-class
|
||||
processGroupIDLabels:
|
||||
- foundationdb.org/fdb-process-group-id
|
||||
minimumUptimeSecondsForBounce: 60
|
||||
|
||||
processes:
|
||||
general:
|
||||
{{- if .Values.customParameters }}
|
||||
customParameters:
|
||||
{{- range .Values.customParameters }}
|
||||
- {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
podTemplate:
|
||||
metadata:
|
||||
labels:
|
||||
policy.cozystack.io/allow-to-apiserver: "true"
|
||||
spec:
|
||||
serviceAccountName: {{ .Release.Name }}-foundationdb
|
||||
securityContext:
|
||||
fsGroup: {{ .Values.securityContext.runAsGroup }}
|
||||
containers:
|
||||
- name: foundationdb
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 16 }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 16 }}
|
||||
- name: foundationdb-kubernetes-sidecar
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 16 }}
|
||||
initContainers:
|
||||
- name: foundationdb-kubernetes-init
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 16 }}
|
||||
volumeClaimTemplate:
|
||||
spec:
|
||||
{{- if .Values.storage.storageClass }}
|
||||
storageClassName: {{ .Values.storage.storageClass }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.storage.size }}
|
||||
|
||||
routing:
|
||||
dnsDomain: {{ $clusterDomain }}
|
||||
defineDNSLocalityFields: true
|
||||
|
||||
sidecarContainer:
|
||||
enableLivenessProbe: true
|
||||
enableReadinessProbe: true
|
||||
@@ -0,0 +1,22 @@
|
||||
{{- if .Values.monitoring.enabled }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-resourcemap
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
app.cozystack.io/type: dashboard-resourcemap
|
||||
data:
|
||||
resources: |
|
||||
- apiVersion: apps.foundationdb.org/v1beta2
|
||||
kind: FoundationDBCluster
|
||||
name: {{ .Release.Name }}
|
||||
{{- if .Values.backup.enabled }}
|
||||
- apiVersion: apps.foundationdb.org/v1beta2
|
||||
kind: FoundationDBBackup
|
||||
name: {{ .Release.Name }}-backup
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
22
packages/apps/foundationdb/templates/role.yaml
Normal file
22
packages/apps/foundationdb/templates/role.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-foundationdb
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
17
packages/apps/foundationdb/templates/rolebinding.yaml
Normal file
17
packages/apps/foundationdb/templates/rolebinding.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-foundationdb
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ .Release.Name }}-foundationdb
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ .Release.Name }}-foundationdb
|
||||
namespace: {{ .Release.Namespace }}
|
||||
9
packages/apps/foundationdb/templates/serviceaccount.yaml
Normal file
9
packages/apps/foundationdb/templates/serviceaccount.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-foundationdb
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
20
packages/apps/foundationdb/templates/workloadmonitor.yaml
Normal file
20
packages/apps/foundationdb/templates/workloadmonitor.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
{{- if .Values.monitoring.enabled }}
|
||||
---
|
||||
apiVersion: cozystack.io/v1alpha1
|
||||
kind: WorkloadMonitor
|
||||
metadata:
|
||||
name: {{ .Release.Name }}
|
||||
labels:
|
||||
app.kubernetes.io/name: foundationdb
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
replicas: {{ .Values.cluster.processCounts.storage }}
|
||||
minReplicas: {{ include "foundationdb.minReplicas" . }}
|
||||
kind: foundationdb
|
||||
type: foundationdb
|
||||
selector:
|
||||
foundationdb.org/fdb-cluster-name: {{ .Release.Name }}
|
||||
foundationdb.org/fdb-process-class: storage
|
||||
version: {{ .Chart.Version }}
|
||||
{{- end }}
|
||||
287
packages/apps/foundationdb/values.schema.json
Normal file
287
packages/apps/foundationdb/values.schema.json
Normal file
@@ -0,0 +1,287 @@
|
||||
{
|
||||
"title": "Chart Values",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"automaticReplacements": {
|
||||
"description": "Enable automatic pod replacements.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"backup": {
|
||||
"description": "Backup configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"enabled",
|
||||
"retentionPolicy",
|
||||
"s3"
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable backups.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"retentionPolicy": {
|
||||
"description": "Retention policy for backups.",
|
||||
"type": "string",
|
||||
"default": "7d"
|
||||
},
|
||||
"s3": {
|
||||
"description": "S3 configuration for backups.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"bucket",
|
||||
"credentials",
|
||||
"endpoint",
|
||||
"region"
|
||||
],
|
||||
"properties": {
|
||||
"bucket": {
|
||||
"description": "S3 bucket name.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"credentials": {
|
||||
"description": "S3 credentials.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"accessKeyId",
|
||||
"secretAccessKey"
|
||||
],
|
||||
"properties": {
|
||||
"accessKeyId": {
|
||||
"description": "S3 access key ID.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"secretAccessKey": {
|
||||
"description": "S3 secret access key.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"endpoint": {
|
||||
"description": "S3 endpoint URL.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"region": {
|
||||
"description": "S3 region.",
|
||||
"type": "string",
|
||||
"default": "us-east-1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cluster": {
|
||||
"description": "Cluster configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"faultDomain",
|
||||
"processCounts",
|
||||
"redundancyMode",
|
||||
"storageEngine",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"faultDomain": {
|
||||
"description": "Fault domain configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"key",
|
||||
"valueFrom"
|
||||
],
|
||||
"properties": {
|
||||
"key": {
|
||||
"description": "Fault domain key.",
|
||||
"type": "string",
|
||||
"default": "kubernetes.io/hostname"
|
||||
},
|
||||
"valueFrom": {
|
||||
"description": "Fault domain value source.",
|
||||
"type": "string",
|
||||
"default": "spec.nodeName"
|
||||
}
|
||||
}
|
||||
},
|
||||
"processCounts": {
|
||||
"description": "Process counts for different roles.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"cluster_controller",
|
||||
"stateless",
|
||||
"storage"
|
||||
],
|
||||
"properties": {
|
||||
"cluster_controller": {
|
||||
"description": "Number of cluster controller processes.",
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
},
|
||||
"stateless": {
|
||||
"description": "Number of stateless processes (-1 for automatic).",
|
||||
"type": "integer",
|
||||
"default": -1
|
||||
},
|
||||
"storage": {
|
||||
"description": "Number of storage processes (determines cluster size).",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
"redundancyMode": {
|
||||
"description": "Database redundancy mode (single, double, triple, three_datacenter, three_datacenter_fallback).",
|
||||
"type": "string",
|
||||
"default": "double"
|
||||
},
|
||||
"storageEngine": {
|
||||
"description": "Storage engine (ssd-2, ssd-redwood-v1, ssd-rocksdb-v1, memory).",
|
||||
"type": "string",
|
||||
"default": "ssd-2"
|
||||
},
|
||||
"version": {
|
||||
"description": "Version of FoundationDB to use.",
|
||||
"type": "string",
|
||||
"default": "7.3.63"
|
||||
}
|
||||
}
|
||||
},
|
||||
"customParameters": {
|
||||
"description": "Custom parameters to pass to FoundationDB.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"imageType": {
|
||||
"description": "Container image deployment type.",
|
||||
"type": "string",
|
||||
"default": "unified",
|
||||
"enum": [
|
||||
"unified",
|
||||
"split"
|
||||
]
|
||||
},
|
||||
"monitoring": {
|
||||
"description": "Monitoring configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable WorkloadMonitor integration.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each FoundationDB instance. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each instance.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each instance.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"x-kubernetes-int-or-string": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "medium",
|
||||
"enum": [
|
||||
"small",
|
||||
"medium",
|
||||
"large",
|
||||
"xlarge",
|
||||
"2xlarge"
|
||||
]
|
||||
},
|
||||
"securityContext": {
|
||||
"description": "Security context for containers.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"runAsGroup",
|
||||
"runAsUser"
|
||||
],
|
||||
"properties": {
|
||||
"runAsGroup": {
|
||||
"description": "Group ID to run the container.",
|
||||
"type": "integer",
|
||||
"default": 4059
|
||||
},
|
||||
"runAsUser": {
|
||||
"description": "User ID to run the container.",
|
||||
"type": "integer",
|
||||
"default": 4059
|
||||
}
|
||||
}
|
||||
},
|
||||
"storage": {
|
||||
"description": "Storage configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"size",
|
||||
"storageClass"
|
||||
],
|
||||
"properties": {
|
||||
"size": {
|
||||
"description": "Size of persistent volumes for each instance.",
|
||||
"default": "16Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "Storage class (if not set, uses cluster default).",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
120
packages/apps/foundationdb/values.yaml
Normal file
120
packages/apps/foundationdb/values.yaml
Normal file
@@ -0,0 +1,120 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
|
||||
## @typedef {struct} ClusterProcessCounts - Process counts for different roles.
|
||||
## @field {int} stateless - Number of stateless processes (-1 for automatic).
|
||||
## @field {int} storage - Number of storage processes (determines cluster size).
|
||||
## @field {int} cluster_controller - Number of cluster controller processes.
|
||||
|
||||
## @typedef {struct} ClusterFaultDomain - Fault domain configuration.
|
||||
## @field {string} key - Fault domain key.
|
||||
## @field {string} valueFrom - Fault domain value source.
|
||||
|
||||
## @typedef {struct} Cluster - Cluster configuration.
|
||||
## @field {ClusterProcessCounts} processCounts - Process counts for different roles.
|
||||
## @field {string} version - Version of FoundationDB to use.
|
||||
## @field {string} redundancyMode - Database redundancy mode (single, double, triple, three_datacenter, three_datacenter_fallback).
|
||||
## @field {string} storageEngine - Storage engine (ssd-2, ssd-redwood-v1, ssd-rocksdb-v1, memory).
|
||||
## @field {ClusterFaultDomain} faultDomain - Fault domain configuration.
|
||||
|
||||
## @param {Cluster} cluster - Cluster configuration.
|
||||
cluster:
|
||||
processCounts:
|
||||
stateless: -1
|
||||
storage: 3
|
||||
cluster_controller: 1
|
||||
|
||||
version: "7.3.63"
|
||||
redundancyMode: "double"
|
||||
storageEngine: "ssd-2"
|
||||
|
||||
faultDomain:
|
||||
key: "kubernetes.io/hostname"
|
||||
valueFrom: "spec.nodeName"
|
||||
|
||||
## @typedef {struct} Storage - Storage configuration.
|
||||
## @field {quantity} size - Size of persistent volumes for each instance.
|
||||
## @field {string} storageClass - Storage class (if not set, uses cluster default).
|
||||
|
||||
## @param {Storage} storage - Storage configuration.
|
||||
storage:
|
||||
size: "16Gi"
|
||||
storageClass: ""
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each FoundationDB instance.
|
||||
## @field {quantity} [cpu] - CPU available to each instance.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each instance.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each FoundationDB instance. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
|
||||
## @param {ResourcesPreset} resourcesPreset="medium" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "medium"
|
||||
|
||||
## @typedef {struct} BackupS3Credentials - S3 credentials.
|
||||
## @field {string} accessKeyId - S3 access key ID.
|
||||
## @field {string} secretAccessKey - S3 secret access key.
|
||||
|
||||
## @typedef {struct} BackupS3 - S3 configuration for backups.
|
||||
## @field {string} bucket - S3 bucket name.
|
||||
## @field {string} endpoint - S3 endpoint URL.
|
||||
## @field {string} region - S3 region.
|
||||
## @field {BackupS3Credentials} credentials - S3 credentials.
|
||||
|
||||
## @typedef {struct} Backup - Backup configuration.
|
||||
## @field {bool} enabled - Enable backups.
|
||||
## @field {BackupS3} s3 - S3 configuration for backups.
|
||||
## @field {string} retentionPolicy - Retention policy for backups.
|
||||
|
||||
## @param {Backup} backup - Backup configuration.
|
||||
backup:
|
||||
enabled: false
|
||||
s3:
|
||||
bucket: ""
|
||||
endpoint: ""
|
||||
region: "us-east-1"
|
||||
credentials:
|
||||
accessKeyId: ""
|
||||
secretAccessKey: ""
|
||||
retentionPolicy: "7d"
|
||||
|
||||
## @typedef {struct} Monitoring - Monitoring configuration.
|
||||
## @field {bool} enabled - Enable WorkloadMonitor integration.
|
||||
|
||||
## @param {Monitoring} monitoring - Monitoring configuration.
|
||||
monitoring:
|
||||
enabled: true
|
||||
|
||||
##
|
||||
## @section FoundationDB configuration
|
||||
##
|
||||
|
||||
## @param {[]string} customParameters - Custom parameters to pass to FoundationDB.
|
||||
customParameters: []
|
||||
|
||||
## @enum {string} ImageType - Container image deployment type.
|
||||
## @value unified
|
||||
## @value split
|
||||
|
||||
## @param {ImageType} imageType="unified" - Container image deployment type.
|
||||
imageType: "unified"
|
||||
|
||||
## @typedef {struct} SecurityContext - Security context for containers.
|
||||
## @field {int} runAsUser - User ID to run the container.
|
||||
## @field {int} runAsGroup - Group ID to run the container.
|
||||
|
||||
## @param {SecurityContext} securityContext - Security context for containers.
|
||||
securityContext:
|
||||
runAsUser: 4059
|
||||
runAsGroup: 4059
|
||||
|
||||
## @param {bool} automaticReplacements - Enable automatic pod replacements.
|
||||
automaticReplacements: true
|
||||
@@ -62,40 +62,40 @@ The deployment architecture is illustrated in the diagram below:
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| -------------- | ------------------------------------------------------------ | ---------- | ------- |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ----------- | ----------------------------------------------- | ---------- | ----- |
|
||||
| `endpoints` | Endpoints configuration, as a list of <ip:port> | `[]string` | `[]` |
|
||||
| Name | Description | Type | Value |
|
||||
| ----------- | ------------------------------------------------ | ---------- | ----- |
|
||||
| `endpoints` | Endpoints configuration, as a list of <ip:port>. | `[]string` | `[]` |
|
||||
|
||||
|
||||
### HAProxy parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------ |
|
||||
| `haproxy` | HAProxy configuration | `object` | `{}` |
|
||||
| `haproxy.replicas` | Number of HAProxy replicas | `int` | `2` |
|
||||
| `haproxy.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `haproxy.resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `haproxy.resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `haproxy.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------- | -------------------------------------------------------------------------------------------------------- | ---------- | ------ |
|
||||
| `haproxy` | HAProxy configuration. | `object` | `{}` |
|
||||
| `haproxy.replicas` | Number of HAProxy replicas. | `int` | `2` |
|
||||
| `haproxy.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `haproxy.resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `haproxy.resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `haproxy.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` |
|
||||
|
||||
|
||||
### Nginx parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------ |
|
||||
| `nginx` | Nginx configuration | `object` | `{}` |
|
||||
| `nginx.replicas` | Number of Nginx replicas | `int` | `2` |
|
||||
| `nginx.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `nginx.resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `nginx.resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `nginx.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------- | ---------- | ------ |
|
||||
| `nginx` | Nginx configuration. | `object` | `{}` |
|
||||
| `nginx.replicas` | Number of Nginx replicas. | `int` | `2` |
|
||||
| `nginx.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `nginx.resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `nginx.resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `nginx.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"endpoints": {
|
||||
"description": "Endpoints configuration, as a list of \u003cip:port\u003e",
|
||||
"description": "Endpoints configuration, as a list of \u003cip:port\u003e.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
@@ -11,32 +11,31 @@
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"haproxy": {
|
||||
"description": "HAProxy configuration",
|
||||
"description": "HAProxy configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"replicas",
|
||||
"resources",
|
||||
"resourcesPreset"
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of HAProxy replicas",
|
||||
"description": "Number of HAProxy replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -49,7 +48,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -64,7 +63,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
@@ -80,7 +79,7 @@
|
||||
}
|
||||
},
|
||||
"nginx": {
|
||||
"description": "Nginx configuration",
|
||||
"description": "Nginx configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -89,17 +88,17 @@
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of Nginx replicas",
|
||||
"description": "Number of Nginx replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -112,7 +111,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -127,7 +126,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
@@ -143,7 +142,7 @@
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -157,8 +156,9 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,22 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
external: false
|
||||
## @section Application-specific parameters
|
||||
|
||||
## @param endpoints {[]string} Endpoints configuration, as a list of <ip:port>
|
||||
## @param {quantity} size - Persistent Volume Claim size available for application data.
|
||||
size: 10Gi
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
|
||||
## @param {[]string} endpoints - Endpoints configuration, as a list of <ip:port>.
|
||||
endpoints: []
|
||||
## Example:
|
||||
## endpoints:
|
||||
## - 10.100.3.1:80
|
||||
@@ -17,37 +25,46 @@ external: false
|
||||
## - 10.100.3.12:80
|
||||
## - 10.100.3.3:80
|
||||
## - 10.100.3.13:80
|
||||
|
||||
##
|
||||
endpoints: []
|
||||
|
||||
|
||||
## @section HAProxy parameters
|
||||
##
|
||||
## @param haproxy {haproxy} HAProxy configuration
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @typedef {struct} HAProxy - HAProxy configuration.
|
||||
## @field {int} replicas - Number of HAProxy replicas.
|
||||
## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
## @field {ResourcesPreset} resourcesPreset - Default sizing preset used when `resources` is omitted.
|
||||
|
||||
## @param {HAProxy} haproxy - HAProxy configuration.
|
||||
haproxy:
|
||||
## @field haproxy.replicas {int} Number of HAProxy replicas
|
||||
replicas: 2
|
||||
## @field haproxy.resources {resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
resources: {}
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
## @field haproxy.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "nano"
|
||||
|
||||
##
|
||||
## @section Nginx parameters
|
||||
##
|
||||
## @param nginx {nginx} Nginx configuration
|
||||
nginx:
|
||||
## @field nginx.replicas {int} Number of Nginx replicas
|
||||
replicas: 2
|
||||
## @field nginx.resources {*resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
|
||||
## @field nginx.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
## @typedef {struct} Nginx - Nginx configuration.
|
||||
## @field {int} replicas - Number of Nginx replicas.
|
||||
## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
## @field {ResourcesPreset} resourcesPreset - Default sizing preset used when `resources` is omitted.
|
||||
|
||||
## @param {Nginx} nginx - Nginx configuration.
|
||||
nginx:
|
||||
replicas: 2
|
||||
resources: {}
|
||||
resourcesPreset: "nano"
|
||||
|
||||
@@ -4,48 +4,48 @@
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------- | ----------------------------------------------- | ------ | ------- |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------- | ------------------------------------------------ | ------ | ------- |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | -------------------- | ---------- | ----- |
|
||||
| `topics` | Topics configuration | `[]object` | `[]` |
|
||||
| `topics[i].name` | Topic name | `string` | `""` |
|
||||
| `topics[i].partitions` | Number of partitions | `int` | `0` |
|
||||
| `topics[i].replicas` | Number of replicas | `int` | `0` |
|
||||
| `topics[i].config` | Topic configuration | `object` | `{}` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | --------------------- | ---------- | ----- |
|
||||
| `topics` | Topics configuration. | `[]object` | `[]` |
|
||||
| `topics[i].name` | Topic name. | `string` | `""` |
|
||||
| `topics[i].partitions` | Number of partitions. | `int` | `0` |
|
||||
| `topics[i].replicas` | Number of replicas. | `int` | `0` |
|
||||
| `topics[i].config` | Topic configuration. | `object` | `{}` |
|
||||
|
||||
|
||||
### Kafka configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `kafka` | Kafka configuration | `object` | `{}` |
|
||||
| `kafka.replicas` | Number of Kafka replicas | `int` | `3` |
|
||||
| `kafka.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `kafka.resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `kafka.resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `kafka.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `kafka.size` | Persistent Volume size for Kafka | `quantity` | `10Gi` |
|
||||
| `kafka.storageClass` | StorageClass used to store the Kafka data | `string` | `""` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `kafka` | Kafka configuration. | `object` | `{}` |
|
||||
| `kafka.replicas` | Number of Kafka replicas. | `int` | `3` |
|
||||
| `kafka.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `kafka.resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `kafka.resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `kafka.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` |
|
||||
| `kafka.size` | Persistent Volume size for Kafka. | `quantity` | `10Gi` |
|
||||
| `kafka.storageClass` | StorageClass used to store the Kafka data. | `string` | `""` |
|
||||
|
||||
|
||||
### Zookeeper configuration
|
||||
### ZooKeeper configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `zookeeper` | Zookeeper configuration | `object` | `{}` |
|
||||
| `zookeeper.replicas` | Number of ZooKeeper replicas | `int` | `3` |
|
||||
| `zookeeper.resources` | Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `zookeeper.resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `zookeeper.resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `zookeeper.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `small` |
|
||||
| `zookeeper.size` | Persistent Volume size for ZooKeeper | `quantity` | `5Gi` |
|
||||
| `zookeeper.storageClass` | StorageClass used to store the ZooKeeper data | `string` | `""` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `zookeeper` | ZooKeeper configuration. | `object` | `{}` |
|
||||
| `zookeeper.replicas` | Number of ZooKeeper replicas. | `int` | `3` |
|
||||
| `zookeeper.resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `zookeeper.resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `zookeeper.resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `zookeeper.resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `small` |
|
||||
| `zookeeper.size` | Persistent Volume size for ZooKeeper. | `quantity` | `5Gi` |
|
||||
| `zookeeper.storageClass` | StorageClass used to store the ZooKeeper data. | `string` | `""` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"kafka": {
|
||||
"description": "Kafka configuration",
|
||||
"description": "Kafka configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -19,17 +19,17 @@
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of Kafka replicas",
|
||||
"description": "Number of Kafka replicas.",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -42,7 +42,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -57,7 +57,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "small",
|
||||
"enum": [
|
||||
@@ -71,7 +71,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume size for Kafka",
|
||||
"description": "Persistent Volume size for Kafka.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -85,13 +85,14 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the Kafka data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the Kafka data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"topics": {
|
||||
"description": "Topics configuration",
|
||||
"description": "Topics configuration.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
@@ -104,27 +105,27 @@
|
||||
],
|
||||
"properties": {
|
||||
"config": {
|
||||
"description": "Topic configuration",
|
||||
"description": "Topic configuration.",
|
||||
"type": "object",
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"name": {
|
||||
"description": "Topic name",
|
||||
"description": "Topic name.",
|
||||
"type": "string"
|
||||
},
|
||||
"partitions": {
|
||||
"description": "Number of partitions",
|
||||
"description": "Number of partitions.",
|
||||
"type": "integer"
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of replicas",
|
||||
"description": "Number of replicas.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"zookeeper": {
|
||||
"description": "Zookeeper configuration",
|
||||
"description": "ZooKeeper configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -135,17 +136,17 @@
|
||||
],
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"description": "Number of ZooKeeper replicas",
|
||||
"description": "Number of ZooKeeper replicas.",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -158,7 +159,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -173,7 +174,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "small",
|
||||
"enum": [
|
||||
@@ -187,7 +188,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume size for ZooKeeper",
|
||||
"description": "Persistent Volume size for ZooKeeper.",
|
||||
"default": "5Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -201,8 +202,9 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the ZooKeeper data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the ZooKeeper data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param topics {[]topic} Topics configuration
|
||||
## @field topic {topic} Topic
|
||||
## @field topic.name {string} Topic name
|
||||
## @field topic.partitions {int} Number of partitions
|
||||
## @field topic.replicas {int} Number of replicas
|
||||
## @field topic.config {object} Topic configuration
|
||||
|
||||
## @typedef {struct} Topic - Topic configuration.
|
||||
## @field {string} name - Topic name.
|
||||
## @field {int} partitions - Number of partitions.
|
||||
## @field {int} replicas - Number of replicas.
|
||||
## @field {object} config - Topic configuration.
|
||||
|
||||
## @param {[]Topic} topics - Topics configuration.
|
||||
topics: []
|
||||
## Example:
|
||||
## topics:
|
||||
## - name: Results
|
||||
@@ -27,46 +32,54 @@ external: false
|
||||
## min.insync.replicas: 2
|
||||
## partitions: 1
|
||||
## replicas: 3
|
||||
##
|
||||
topics: []
|
||||
|
||||
##
|
||||
## @section Kafka configuration
|
||||
##
|
||||
## @param kafka {kafka} Kafka configuration
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @typedef {struct} Kafka - Kafka configuration.
|
||||
## @field {int} replicas - Number of Kafka replicas.
|
||||
## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
## @field {ResourcesPreset} resourcesPreset - Default sizing preset used when `resources` is omitted.
|
||||
## @field {quantity} size - Persistent Volume size for Kafka.
|
||||
## @field {string} storageClass - StorageClass used to store the Kafka data.
|
||||
|
||||
## @param {Kafka} kafka - Kafka configuration.
|
||||
kafka:
|
||||
## @field kafka.replicas {int} Number of Kafka replicas
|
||||
replicas: 3
|
||||
## @field kafka.resources {*resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
## @field kafka.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "small"
|
||||
## @field kafka.size {quantity} Persistent Volume size for Kafka
|
||||
size: 10Gi
|
||||
## @field kafka.storageClass {string} StorageClass used to store the Kafka data
|
||||
storageClass: ""
|
||||
|
||||
|
||||
## @section Zookeeper configuration
|
||||
##
|
||||
## @param zookeeper {zookeeper} Zookeeper configuration
|
||||
## @section ZooKeeper configuration
|
||||
##
|
||||
|
||||
## @typedef {struct} ZooKeeper - ZooKeeper configuration.
|
||||
## @field {int} replicas - Number of ZooKeeper replicas.
|
||||
## @field {Resources} [resources] - Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
## @field {ResourcesPreset} resourcesPreset - Default sizing preset used when `resources` is omitted.
|
||||
## @field {quantity} size - Persistent Volume size for ZooKeeper.
|
||||
## @field {string} storageClass - StorageClass used to store the ZooKeeper data.
|
||||
|
||||
## @param {ZooKeeper} zookeeper - ZooKeeper configuration.
|
||||
zookeeper:
|
||||
## @field zookeeper.replicas {int} Number of ZooKeeper replicas
|
||||
replicas: 3
|
||||
## @field zookeeper.resources {*resources} Explicit CPU and memory configuration for each replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
resources: {}
|
||||
|
||||
## @field zookeeper.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "small"
|
||||
## @field zookeeper.size {quantity} Persistent Volume size for ZooKeeper
|
||||
size: 5Gi
|
||||
## @field zookeeper.storageClass {string} StorageClass used to store the ZooKeeper data
|
||||
storageClass: ""
|
||||
|
||||
|
||||
@@ -84,92 +84,92 @@ See the reference for components utilized in this service:
|
||||
|
||||
### Common Parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| -------------- | ----------------------------------- | -------- | ------------ |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `replicated` |
|
||||
| Name | Description | Type | Value |
|
||||
| -------------- | ------------------------------------ | -------- | ------------ |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `replicated` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
### Application-specific Parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------- | ----------- |
|
||||
| `version` | Kubernetes version given as vMAJOR.MINOR. Available are versions from 1.28 to 1.33. | `string` | `v1.33` |
|
||||
| `host` | Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty. | `string` | `""` |
|
||||
| `nodeGroups` | Worker nodes configuration | `map[string]object` | `{...}` |
|
||||
| `nodeGroups[name].minReplicas` | Minimum amount of replicas | `int` | `0` |
|
||||
| `nodeGroups[name].maxReplicas` | Maximum amount of replicas | `int` | `10` |
|
||||
| `nodeGroups[name].instanceType` | Virtual machine instance type | `string` | `u1.medium` |
|
||||
| `nodeGroups[name].ephemeralStorage` | Ephemeral storage size | `quantity` | `20Gi` |
|
||||
| `nodeGroups[name].roles` | List of node's roles | `[]string` | `[]` |
|
||||
| `nodeGroups[name].resources` | Resources available to each worker node | `object` | `{}` |
|
||||
| `nodeGroups[name].resources.cpu` | CPU available to each worker node | `*quantity` | `null` |
|
||||
| `nodeGroups[name].resources.memory` | Memory (RAM) available to each worker node | `*quantity` | `null` |
|
||||
| `nodeGroups[name].gpus` | List of GPUs to attach (WARN: NVIDIA driver requires at least 4 GiB of RAM) | `[]object` | `{}` |
|
||||
| `nodeGroups[name].gpus[i].name` | Name of GPU, such as "nvidia.com/AD102GL_L40S" | `string` | `""` |
|
||||
| Name | Description | Type | Value |
|
||||
| ----------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------- | ----------- |
|
||||
| `nodeGroups` | Worker nodes configuration map. | `map[string]object` | `{...}` |
|
||||
| `nodeGroups[name].minReplicas` | Minimum number of replicas. | `int` | `0` |
|
||||
| `nodeGroups[name].maxReplicas` | Maximum number of replicas. | `int` | `10` |
|
||||
| `nodeGroups[name].instanceType` | Virtual machine instance type. | `string` | `u1.medium` |
|
||||
| `nodeGroups[name].ephemeralStorage` | Ephemeral storage size. | `quantity` | `20Gi` |
|
||||
| `nodeGroups[name].roles` | List of node roles. | `[]string` | `[]` |
|
||||
| `nodeGroups[name].resources` | CPU and memory resources for each worker node. | `object` | `{}` |
|
||||
| `nodeGroups[name].resources.cpu` | CPU available. | `quantity` | `""` |
|
||||
| `nodeGroups[name].resources.memory` | Memory (RAM) available. | `quantity` | `""` |
|
||||
| `nodeGroups[name].gpus` | List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM). | `[]object` | `[]` |
|
||||
| `nodeGroups[name].gpus[i].name` | Name of GPU, such as "nvidia.com/AD102GL_L40S". | `string` | `""` |
|
||||
| `version` | Kubernetes version (vMAJOR.MINOR). Supported: 1.28–1.33. | `string` | `v1.33` |
|
||||
| `host` | External hostname for Kubernetes cluster. Defaults to `<cluster-name>.<tenant-host>` if empty. | `string` | `""` |
|
||||
|
||||
|
||||
### Cluster Addons
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | --------- |
|
||||
| `addons` | Cluster addons configuration | `object` | `{}` |
|
||||
| `addons.certManager` | Cert-manager: automatically creates and manages SSL/TLS certificate | `object` | `{}` |
|
||||
| `addons.certManager.enabled` | Enable cert-manager, which automatically creates and manages SSL/TLS certificates. | `bool` | `false` |
|
||||
| `addons.certManager.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.cilium` | Cilium CNI plugin | `object` | `{}` |
|
||||
| `addons.cilium.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gatewayAPI` | Gateway API | `object` | `{}` |
|
||||
| `addons.gatewayAPI.enabled` | Enable the Gateway API | `bool` | `false` |
|
||||
| `addons.ingressNginx` | Ingress-NGINX Controller | `object` | `{}` |
|
||||
| `addons.ingressNginx.enabled` | Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role). | `bool` | `false` |
|
||||
| `addons.ingressNginx.exposeMethod` | Method to expose the Ingress-NGINX controller. Allowed values: `Proxied`, `LoadBalancer`. | `string` | `Proxied` |
|
||||
| `addons.ingressNginx.hosts` | List of domain names that the parent cluster should route to this tenant cluster. Taken into account only when `exposeMethod` is set to `Proxied`. | `[]string` | `[]` |
|
||||
| `addons.ingressNginx.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.gpuOperator` | GPU-operator: NVIDIA GPU Operator | `object` | `{}` |
|
||||
| `addons.gpuOperator.enabled` | Enable the GPU-operator | `bool` | `false` |
|
||||
| `addons.gpuOperator.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.fluxcd` | Flux CD | `object` | `{}` |
|
||||
| `addons.fluxcd.enabled` | Enable FluxCD | `bool` | `false` |
|
||||
| `addons.fluxcd.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.monitoringAgents` | MonitoringAgents | `object` | `{}` |
|
||||
| `addons.monitoringAgents.enabled` | Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage. | `bool` | `false` |
|
||||
| `addons.monitoringAgents.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler` | VerticalPodAutoscaler | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.velero` | Velero | `object` | `{}` |
|
||||
| `addons.velero.enabled` | Enable Velero for backup and recovery of a tenant Kubernetes cluster. | `bool` | `false` |
|
||||
| `addons.velero.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| `addons.coredns` | Coredns | `object` | `{}` |
|
||||
| `addons.coredns.valuesOverride` | Custom values to override | `object` | `{}` |
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------------- | --------------------------------------------------------------------------- | ---------- | --------- |
|
||||
| `addons` | Cluster addons configuration. | `object` | `{}` |
|
||||
| `addons.certManager` | Cert-manager addon. | `object` | `{}` |
|
||||
| `addons.certManager.enabled` | Enable cert-manager. | `bool` | `false` |
|
||||
| `addons.certManager.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.cilium` | Cilium CNI plugin. | `object` | `{}` |
|
||||
| `addons.cilium.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.gatewayAPI` | Gateway API addon. | `object` | `{}` |
|
||||
| `addons.gatewayAPI.enabled` | Enable Gateway API. | `bool` | `false` |
|
||||
| `addons.ingressNginx` | Ingress-NGINX controller. | `object` | `{}` |
|
||||
| `addons.ingressNginx.enabled` | Enable the controller (requires nodes labeled `ingress-nginx`). | `bool` | `false` |
|
||||
| `addons.ingressNginx.exposeMethod` | Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`. | `string` | `Proxied` |
|
||||
| `addons.ingressNginx.hosts` | Domains routed to this tenant cluster when `exposeMethod` is `Proxied`. | `[]string` | `[]` |
|
||||
| `addons.ingressNginx.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.gpuOperator` | NVIDIA GPU Operator. | `object` | `{}` |
|
||||
| `addons.gpuOperator.enabled` | Enable GPU Operator. | `bool` | `false` |
|
||||
| `addons.gpuOperator.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.fluxcd` | FluxCD GitOps operator. | `object` | `{}` |
|
||||
| `addons.fluxcd.enabled` | Enable FluxCD. | `bool` | `false` |
|
||||
| `addons.fluxcd.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.monitoringAgents` | Monitoring agents. | `object` | `{}` |
|
||||
| `addons.monitoringAgents.enabled` | Enable monitoring agents. | `bool` | `false` |
|
||||
| `addons.monitoringAgents.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler` | Vertical Pod Autoscaler. | `object` | `{}` |
|
||||
| `addons.verticalPodAutoscaler.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.velero` | Velero backup/restore addon. | `object` | `{}` |
|
||||
| `addons.velero.enabled` | Enable Velero. | `bool` | `false` |
|
||||
| `addons.velero.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
| `addons.coredns` | CoreDNS addon. | `object` | `{}` |
|
||||
| `addons.coredns.valuesOverride` | Custom Helm values overrides. | `object` | `{}` |
|
||||
|
||||
|
||||
### Kubernetes Control Plane Configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------- |
|
||||
| `controlPlane` | Control Plane Configuration | `object` | `{}` |
|
||||
| `controlPlane.replicas` | Number of replicas for Kubernetes control plane components. | `int` | `2` |
|
||||
| `controlPlane.apiServer` | Control plane API server configuration. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources` | Explicit CPU and memory configuration for the API Server. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources.cpu` | CPU available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resources.memory` | Memory (RAM) available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.apiServer.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `medium` |
|
||||
| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources` | Explicit CPU and memory configuration for the Controller Manager. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | CPU available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.controllerManager.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `micro` |
|
||||
| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources` | Explicit CPU and memory configuration for the Scheduler. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources.cpu` | CPU available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resources.memory` | Memory (RAM) available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.scheduler.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server` | Konnectivity server configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources` | Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | CPU available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available to each worker node | `*quantity` | `null` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `micro` |
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------------------- | ------------------------------------------------ | ---------- | -------- |
|
||||
| `controlPlane` | Kubernetes control-plane configuration. | `object` | `{}` |
|
||||
| `controlPlane.replicas` | Number of control-plane replicas. | `int` | `2` |
|
||||
| `controlPlane.apiServer` | API Server configuration. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources` | CPU and memory resources for API Server. | `object` | `{}` |
|
||||
| `controlPlane.apiServer.resources.cpu` | CPU available. | `quantity` | `""` |
|
||||
| `controlPlane.apiServer.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
|
||||
| `controlPlane.apiServer.resourcesPreset` | Preset if `resources` omitted. | `string` | `medium` |
|
||||
| `controlPlane.controllerManager` | Controller Manager configuration. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources` | CPU and memory resources for Controller Manager. | `object` | `{}` |
|
||||
| `controlPlane.controllerManager.resources.cpu` | CPU available. | `quantity` | `""` |
|
||||
| `controlPlane.controllerManager.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
|
||||
| `controlPlane.controllerManager.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
|
||||
| `controlPlane.scheduler` | Scheduler configuration. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources` | CPU and memory resources for Scheduler. | `object` | `{}` |
|
||||
| `controlPlane.scheduler.resources.cpu` | CPU available. | `quantity` | `""` |
|
||||
| `controlPlane.scheduler.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
|
||||
| `controlPlane.scheduler.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
|
||||
| `controlPlane.konnectivity` | Konnectivity configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server` | Konnectivity Server configuration. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources` | CPU and memory resources for Konnectivity. | `object` | `{}` |
|
||||
| `controlPlane.konnectivity.server.resources.cpu` | CPU available. | `quantity` | `""` |
|
||||
| `controlPlane.konnectivity.server.resources.memory` | Memory (RAM) available. | `quantity` | `""` |
|
||||
| `controlPlane.konnectivity.server.resourcesPreset` | Preset if `resources` omitted. | `string` | `micro` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -147,7 +147,7 @@ spec:
|
||||
podAdditionalMetadata:
|
||||
labels:
|
||||
policy.cozystack.io/allow-to-etcd: "true"
|
||||
replicas: 2
|
||||
replicas: {{ .Values.controlPlane.replicas }}
|
||||
version: {{ include "kubernetes.versionMap" $ }}
|
||||
---
|
||||
apiVersion: cozystack.io/v1alpha1
|
||||
|
||||
76
packages/apps/kubernetes/templates/csi/delete.yaml
Normal file
76
packages/apps/kubernetes/templates/csi/delete.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
annotations:
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-weight": "10"
|
||||
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
|
||||
name: {{ .Release.Name }}-datavolume-cleanup
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
serviceAccountName: {{ .Release.Name }}-datavolume-cleanup
|
||||
restartPolicy: Never
|
||||
tolerations:
|
||||
- key: CriticalAddonsOnly
|
||||
operator: Exists
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: Exists
|
||||
effect: "NoSchedule"
|
||||
containers:
|
||||
- name: kubectl
|
||||
image: docker.io/clastix/kubectl:v1.32
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- kubectl -n {{ .Release.Namespace }} delete datavolumes
|
||||
-l "cluster.x-k8s.io/cluster-name={{ .Release.Name }}"
|
||||
--ignore-not-found=true
|
||||
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-datavolume-cleanup
|
||||
annotations:
|
||||
helm.sh/hook: post-delete
|
||||
helm.sh/hook-delete-policy: before-hook-creation,hook-failed,hook-succeeded
|
||||
helm.sh/hook-weight: "0"
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
annotations:
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
|
||||
"helm.sh/hook-weight": "5"
|
||||
name: {{ .Release.Name }}-datavolume-cleanup
|
||||
rules:
|
||||
- apiGroups:
|
||||
- "cdi.kubevirt.io"
|
||||
resources:
|
||||
- datavolumes
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- delete
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
annotations:
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-delete-policy": hook-succeeded,before-hook-creation,hook-failed
|
||||
"helm.sh/hook-weight": "5"
|
||||
name: {{ .Release.Name }}-datavolume-cleanup
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ .Release.Name }}-datavolume-cleanup
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ .Release.Name }}-datavolume-cleanup
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
@@ -24,26 +24,26 @@ spec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
kubectl
|
||||
--namespace={{ .Release.Namespace }}
|
||||
patch
|
||||
helmrelease
|
||||
{{ .Release.Name }}-cilium
|
||||
{{ .Release.Name }}-gateway-api-crds
|
||||
{{ .Release.Name }}-csi
|
||||
{{ .Release.Name }}-cert-manager
|
||||
{{ .Release.Name }}-cert-manager-crds
|
||||
{{ .Release.Name }}-vertical-pod-autoscaler
|
||||
{{ .Release.Name }}-vertical-pod-autoscaler-crds
|
||||
{{ .Release.Name }}-ingress-nginx
|
||||
{{ .Release.Name }}-fluxcd-operator
|
||||
{{ .Release.Name }}-fluxcd
|
||||
{{ .Release.Name }}-gpu-operator
|
||||
{{ .Release.Name }}-velero
|
||||
{{ .Release.Name }}-coredns
|
||||
-p '{"spec": {"suspend": true}}'
|
||||
--type=merge --field-manager=flux-client-side-apply || true
|
||||
- >-
|
||||
kubectl
|
||||
--namespace={{ .Release.Namespace }}
|
||||
patch
|
||||
helmrelease
|
||||
{{ .Release.Name }}-cilium
|
||||
{{ .Release.Name }}-gateway-api-crds
|
||||
{{ .Release.Name }}-csi
|
||||
{{ .Release.Name }}-cert-manager
|
||||
{{ .Release.Name }}-cert-manager-crds
|
||||
{{ .Release.Name }}-vertical-pod-autoscaler
|
||||
{{ .Release.Name }}-vertical-pod-autoscaler-crds
|
||||
{{ .Release.Name }}-ingress-nginx
|
||||
{{ .Release.Name }}-fluxcd-operator
|
||||
{{ .Release.Name }}-fluxcd
|
||||
{{ .Release.Name }}-gpu-operator
|
||||
{{ .Release.Name }}-velero
|
||||
{{ .Release.Name }}-coredns
|
||||
-p '{"spec": {"suspend": true}}'
|
||||
--type=merge --field-manager=flux-client-side-apply || true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
@@ -51,7 +51,7 @@ metadata:
|
||||
name: {{ .Release.Name }}-flux-teardown
|
||||
annotations:
|
||||
helm.sh/hook: pre-delete
|
||||
helm.sh/hook-delete-policy: before-hook-creation,hook-failed
|
||||
helm.sh/hook-delete-policy: before-hook-creation,hook-failed,hook-succeeded
|
||||
helm.sh/hook-weight: "0"
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
@@ -75,6 +75,7 @@ rules:
|
||||
- {{ .Release.Name }}-csi
|
||||
- {{ .Release.Name }}-cert-manager
|
||||
- {{ .Release.Name }}-cert-manager-crds
|
||||
- {{ .Release.Name }}-gateway-api-crds
|
||||
- {{ .Release.Name }}-vertical-pod-autoscaler
|
||||
- {{ .Release.Name }}-vertical-pod-autoscaler-crds
|
||||
- {{ .Release.Name }}-ingress-nginx
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"addons": {
|
||||
"description": "Cluster addons configuration",
|
||||
"description": "Cluster addons configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -20,7 +20,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"certManager": {
|
||||
"description": "Cert-manager: automatically creates and manages SSL/TLS certificate",
|
||||
"description": "Cert-manager addon.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -29,12 +29,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable cert-manager, which automatically creates and manages SSL/TLS certificates.",
|
||||
"description": "Enable cert-manager.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -42,7 +42,7 @@
|
||||
}
|
||||
},
|
||||
"cilium": {
|
||||
"description": "Cilium CNI plugin",
|
||||
"description": "Cilium CNI plugin.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -50,7 +50,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -58,7 +58,7 @@
|
||||
}
|
||||
},
|
||||
"coredns": {
|
||||
"description": "Coredns",
|
||||
"description": "CoreDNS addon.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -66,7 +66,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -74,7 +74,7 @@
|
||||
}
|
||||
},
|
||||
"fluxcd": {
|
||||
"description": "Flux CD",
|
||||
"description": "FluxCD GitOps operator.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -83,12 +83,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable FluxCD",
|
||||
"description": "Enable FluxCD.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -96,7 +96,7 @@
|
||||
}
|
||||
},
|
||||
"gatewayAPI": {
|
||||
"description": "Gateway API",
|
||||
"description": "Gateway API addon.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -104,14 +104,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable the Gateway API",
|
||||
"description": "Enable Gateway API.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"gpuOperator": {
|
||||
"description": "GPU-operator: NVIDIA GPU Operator",
|
||||
"description": "NVIDIA GPU Operator.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -120,12 +120,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable the GPU-operator",
|
||||
"description": "Enable GPU Operator.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -133,7 +133,7 @@
|
||||
}
|
||||
},
|
||||
"ingressNginx": {
|
||||
"description": "Ingress-NGINX Controller",
|
||||
"description": "Ingress-NGINX controller.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -143,21 +143,17 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role).",
|
||||
"description": "Enable the controller (requires nodes labeled `ingress-nginx`).",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"exposeMethod": {
|
||||
"description": "Method to expose the Ingress-NGINX controller. Allowed values: `Proxied`, `LoadBalancer`.",
|
||||
"description": "Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.",
|
||||
"type": "string",
|
||||
"default": "Proxied",
|
||||
"enum": [
|
||||
"Proxied",
|
||||
"LoadBalancer"
|
||||
]
|
||||
"default": "Proxied"
|
||||
},
|
||||
"hosts": {
|
||||
"description": "List of domain names that the parent cluster should route to this tenant cluster. Taken into account only when `exposeMethod` is set to `Proxied`.",
|
||||
"description": "Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
@@ -165,7 +161,7 @@
|
||||
}
|
||||
},
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -173,7 +169,7 @@
|
||||
}
|
||||
},
|
||||
"monitoringAgents": {
|
||||
"description": "MonitoringAgents",
|
||||
"description": "Monitoring agents.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -182,12 +178,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage.",
|
||||
"description": "Enable monitoring agents.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -195,7 +191,7 @@
|
||||
}
|
||||
},
|
||||
"velero": {
|
||||
"description": "Velero",
|
||||
"description": "Velero backup/restore addon.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -204,12 +200,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable Velero for backup and recovery of a tenant Kubernetes cluster.",
|
||||
"description": "Enable Velero.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -217,7 +213,7 @@
|
||||
}
|
||||
},
|
||||
"verticalPodAutoscaler": {
|
||||
"description": "VerticalPodAutoscaler",
|
||||
"description": "Vertical Pod Autoscaler.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -225,7 +221,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"valuesOverride": {
|
||||
"description": "Custom values to override",
|
||||
"description": "Custom Helm values overrides.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -235,7 +231,7 @@
|
||||
}
|
||||
},
|
||||
"controlPlane": {
|
||||
"description": "Control Plane Configuration",
|
||||
"description": "Kubernetes control-plane configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -247,7 +243,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"apiServer": {
|
||||
"description": "Control plane API server configuration.",
|
||||
"description": "API Server configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -256,12 +252,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for the API Server. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "CPU and memory resources for API Server.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each worker node",
|
||||
"description": "CPU available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -274,7 +270,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each worker node",
|
||||
"description": "Memory (RAM) available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -289,7 +285,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Preset if `resources` omitted.",
|
||||
"type": "string",
|
||||
"default": "medium",
|
||||
"enum": [
|
||||
@@ -314,12 +310,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for the Controller Manager. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "CPU and memory resources for Controller Manager.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each worker node",
|
||||
"description": "CPU available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -332,7 +328,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each worker node",
|
||||
"description": "Memory (RAM) available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -347,7 +343,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Preset if `resources` omitted.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
@@ -371,7 +367,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"server": {
|
||||
"description": "Konnectivity server configuration.",
|
||||
"description": "Konnectivity Server configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -380,12 +376,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "CPU and memory resources for Konnectivity.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each worker node",
|
||||
"description": "CPU available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -398,7 +394,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each worker node",
|
||||
"description": "Memory (RAM) available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -413,7 +409,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Preset if `resources` omitted.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
@@ -431,7 +427,7 @@
|
||||
}
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of replicas for Kubernetes control plane components.",
|
||||
"description": "Number of control-plane replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
@@ -445,12 +441,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for the Scheduler. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "CPU and memory resources for Scheduler.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each worker node",
|
||||
"description": "CPU available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -463,7 +459,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each worker node",
|
||||
"description": "Memory (RAM) available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -478,7 +474,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Preset if `resources` omitted.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
@@ -496,11 +492,12 @@
|
||||
}
|
||||
},
|
||||
"host": {
|
||||
"description": "Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty.",
|
||||
"type": "string"
|
||||
"description": "External hostname for Kubernetes cluster. Defaults to `<cluster-name>.<tenant-host>` if empty.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"nodeGroups": {
|
||||
"description": "Worker nodes configuration",
|
||||
"description": "Worker nodes configuration map.",
|
||||
"type": "object",
|
||||
"default": {
|
||||
"md0": {
|
||||
@@ -526,7 +523,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"ephemeralStorage": {
|
||||
"description": "Ephemeral storage size",
|
||||
"description": "Ephemeral storage size.",
|
||||
"default": "20Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -540,9 +537,8 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"gpus": {
|
||||
"description": "List of GPUs to attach (WARN: NVIDIA driver requires at least 4 GiB of RAM)",
|
||||
"description": "List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -550,34 +546,33 @@
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Name of GPU, such as \"nvidia.com/AD102GL_L40S\"",
|
||||
"description": "Name of GPU, such as \"nvidia.com/AD102GL_L40S\".",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"instanceType": {
|
||||
"description": "Virtual machine instance type",
|
||||
"description": "Virtual machine instance type.",
|
||||
"type": "string",
|
||||
"default": "u1.medium"
|
||||
},
|
||||
"maxReplicas": {
|
||||
"description": "Maximum amount of replicas",
|
||||
"description": "Maximum number of replicas.",
|
||||
"type": "integer",
|
||||
"default": 10
|
||||
},
|
||||
"minReplicas": {
|
||||
"description": "Minimum amount of replicas",
|
||||
"description": "Minimum number of replicas.",
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"resources": {
|
||||
"description": "Resources available to each worker node",
|
||||
"description": "CPU and memory resources for each worker node.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each worker node",
|
||||
"description": "CPU available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -590,7 +585,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each worker node",
|
||||
"description": "Memory (RAM) available.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -605,7 +600,7 @@
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"description": "List of node's roles",
|
||||
"description": "List of node roles.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
@@ -615,12 +610,12 @@
|
||||
}
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": "replicated"
|
||||
},
|
||||
"version": {
|
||||
"description": "Kubernetes version given as vMAJOR.MINOR. Available are versions from 1.28 to 1.33.",
|
||||
"description": "Kubernetes version (vMAJOR.MINOR). Supported: 1.28–1.33.",
|
||||
"type": "string",
|
||||
"default": "v1.33",
|
||||
"enum": [
|
||||
|
||||
@@ -1,27 +1,40 @@
|
||||
##
|
||||
## @section Common Parameters
|
||||
##
|
||||
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: replicated
|
||||
|
||||
## @section Application-specific parameters
|
||||
## @param version {string} Kubernetes version given as vMAJOR.MINOR. Available are versions from 1.28 to 1.33.
|
||||
version: "v1.33"
|
||||
## @param host {string} Hostname used to access the Kubernetes cluster externally. Defaults to `<cluster-name>.<tenant-host>` when empty.
|
||||
host: ""
|
||||
|
||||
## @param nodeGroups {map[string]nodeGroup} Worker nodes configuration
|
||||
## @field nodeGroup {nodeGroup} Node configuration
|
||||
## @field nodeGroup.minReplicas {int default=0} Minimum amount of replicas
|
||||
## @field nodeGroup.maxReplicas {int default=10} Maximum amount of replicas
|
||||
## @field nodeGroup.instanceType {string default="u1.medium"} Virtual machine instance type
|
||||
## @field nodeGroup.ephemeralStorage {quantity default="20Gi"} Ephemeral storage size
|
||||
## @field nodeGroup.roles {[]string default=[]} List of node's roles
|
||||
## @field nodeGroup.resources {resources default={}} Resources available to each worker node
|
||||
## @field resources.cpu {*quantity} CPU available to each worker node
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each worker node
|
||||
## @field nodeGroup.gpus {[]gpu default={}} List of GPUs to attach (WARN: NVIDIA driver requires at least 4 GiB of RAM)
|
||||
## @field gpu.name {string} Name of GPU, such as "nvidia.com/AD102GL_L40S"
|
||||
##
|
||||
## @section Application-specific Parameters
|
||||
##
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for a node or component.
|
||||
## @field {quantity} [cpu] - CPU available.
|
||||
## @field {quantity} [memory] - Memory (RAM) available.
|
||||
|
||||
## @typedef {struct} GPU - GPU configuration.
|
||||
## @field {string} name - Name of GPU, such as "nvidia.com/AD102GL_L40S".
|
||||
|
||||
## @typedef {struct} NodeGroup - Worker node group configuration.
|
||||
## @field {int} minReplicas=0 - Minimum number of replicas.
|
||||
## @field {int} maxReplicas=10 - Maximum number of replicas.
|
||||
## @field {string} instanceType="u1.medium" - Virtual machine instance type.
|
||||
## @field {quantity} ephemeralStorage="20Gi" - Ephemeral storage size.
|
||||
## @field {[]string} roles - List of node roles.
|
||||
## @field {Resources} resources - CPU and memory resources for each worker node.
|
||||
## @field {[]GPU} gpus - List of GPUs to attach (NVIDIA driver requires at least 4 GiB RAM).
|
||||
|
||||
## @param {map[string]NodeGroup} nodeGroups - Worker nodes configuration map.
|
||||
nodeGroups:
|
||||
md0:
|
||||
minReplicas: 0
|
||||
@@ -31,141 +44,142 @@ nodeGroups:
|
||||
roles:
|
||||
- ingress-nginx
|
||||
resources: {}
|
||||
## List of GPUs to attach (WARN: NVIDIA driver requires at least 4 GiB of RAM)
|
||||
## e.g:
|
||||
## instanceType: "u1.xlarge"
|
||||
## gpus:
|
||||
## - name: nvidia.com/AD102GL_L40S
|
||||
gpus: []
|
||||
|
||||
## @param {string} version - Kubernetes version (vMAJOR.MINOR). Supported: 1.28–1.33.
|
||||
version: "v1.33"
|
||||
|
||||
## @param {string} host - External hostname for Kubernetes cluster. Defaults to `<cluster-name>.<tenant-host>` if empty.
|
||||
host: ""
|
||||
|
||||
##
|
||||
## @section Cluster Addons
|
||||
##
|
||||
## @param addons {addons} Cluster addons configuration
|
||||
|
||||
## @typedef {struct} CertManagerAddon - cert-manager addon.
|
||||
## @field {bool} enabled - Enable cert-manager.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} CiliumAddon - Cilium CNI plugin.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} GatewayAPIAddon - Gateway API addon.
|
||||
## @field {bool} enabled - Enable Gateway API.
|
||||
|
||||
## @typedef {struct} IngressNginxAddon - Ingress-NGINX controller.
|
||||
## @field {bool} enabled - Enable the controller (requires nodes labeled `ingress-nginx`).
|
||||
## @field {string} exposeMethod - Method to expose the controller. Allowed values: `Proxied`, `LoadBalancer`.
|
||||
## @field {[]string} hosts - Domains routed to this tenant cluster when `exposeMethod` is `Proxied`.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} GPUOperatorAddon - NVIDIA GPU Operator.
|
||||
## @field {bool} enabled - Enable GPU Operator.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} FluxCDAddon - FluxCD GitOps operator.
|
||||
## @field {bool} enabled - Enable FluxCD.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} MonitoringAgentsAddon - Monitoring agents (Fluent Bit, VMAgents).
|
||||
## @field {bool} enabled - Enable monitoring agents.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} VerticalPodAutoscalerAddon - Vertical Pod Autoscaler.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} VeleroAddon - Velero backup and recovery addon.
|
||||
## @field {bool} enabled - Enable Velero.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} CoreDNSAddon - CoreDNS addon.
|
||||
## @field {object} valuesOverride - Custom Helm values overrides.
|
||||
|
||||
## @typedef {struct} Addons - Cluster addons configuration.
|
||||
## @field {CertManagerAddon} certManager - Cert-manager addon.
|
||||
## @field {CiliumAddon} cilium - Cilium CNI plugin.
|
||||
## @field {GatewayAPIAddon} gatewayAPI - Gateway API addon.
|
||||
## @field {IngressNginxAddon} ingressNginx - Ingress-NGINX controller.
|
||||
## @field {GPUOperatorAddon} gpuOperator - NVIDIA GPU Operator.
|
||||
## @field {FluxCDAddon} fluxcd - FluxCD GitOps operator.
|
||||
## @field {MonitoringAgentsAddon} monitoringAgents - Monitoring agents.
|
||||
## @field {VerticalPodAutoscalerAddon} verticalPodAutoscaler - Vertical Pod Autoscaler.
|
||||
## @field {VeleroAddon} velero - Velero backup/restore addon.
|
||||
## @field {CoreDNSAddon} coredns - CoreDNS addon.
|
||||
|
||||
## @param {Addons} addons - Cluster addons configuration.
|
||||
addons:
|
||||
## @field addons.certManager {certManager} Cert-manager: automatically creates and manages SSL/TLS certificate
|
||||
##
|
||||
certManager:
|
||||
## @field certManager.enabled {bool} Enable cert-manager, which automatically creates and manages SSL/TLS certificates.
|
||||
enabled: false
|
||||
## @field certManager.valuesOverride {object} Custom values to override
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.cilium {cilium} Cilium CNI plugin
|
||||
##
|
||||
cilium:
|
||||
## @field cilium.valuesOverride {object} Custom values to override
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.gatewayAPI {gatewayAPI} Gateway API
|
||||
##
|
||||
gatewayAPI:
|
||||
## @field gatewayAPI.enabled {bool} Enable the Gateway API
|
||||
enabled: false
|
||||
|
||||
## @field addons.ingressNginx {ingressNginx} Ingress-NGINX Controller
|
||||
##
|
||||
ingressNginx:
|
||||
## @field ingressNginx.enabled {bool} Enable the Ingress-NGINX controller (requires nodes labeled with the 'ingress-nginx' role).
|
||||
enabled: false
|
||||
## @field ingressNginx.exposeMethod {string enum:"Proxied,LoadBalancer"} Method to expose the Ingress-NGINX controller. Allowed values: `Proxied`, `LoadBalancer`.
|
||||
exposeMethod: Proxied
|
||||
## @field ingressNginx.hosts {[]string} List of domain names that the parent cluster should route to this tenant cluster. Taken into account only when `exposeMethod` is set to `Proxied`.
|
||||
## e.g:
|
||||
## hosts:
|
||||
## - example.org
|
||||
## - foo.example.net
|
||||
##
|
||||
hosts: []
|
||||
## @field ingressNginx.valuesOverride {object} Custom values to override
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.gpuOperator {gpuOperator} GPU-operator: NVIDIA GPU Operator
|
||||
##
|
||||
gpuOperator:
|
||||
## @field gpuOperator.enabled {bool} Enable the GPU-operator
|
||||
## @field gpuOperator.valuesOverride {object} Custom values to override
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.fluxcd {fluxcd} Flux CD
|
||||
##
|
||||
fluxcd:
|
||||
## @field fluxcd.enabled {bool} Enable FluxCD
|
||||
## @field fluxcd.valuesOverride {object} Custom values to override
|
||||
##
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.monitoringAgents {monitoringAgents} MonitoringAgents
|
||||
##
|
||||
monitoringAgents:
|
||||
## @field monitoringAgents.enabled {bool} Enable monitoring agents (Fluent Bit and VMAgents) to send logs and metrics. If tenant monitoring is enabled, data is sent to tenant storage; otherwise, it goes to root storage.
|
||||
## @field monitoringAgents.valuesOverride {object} Custom values to override
|
||||
##
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.verticalPodAutoscaler {verticalPodAutoscaler} VerticalPodAutoscaler
|
||||
##
|
||||
verticalPodAutoscaler:
|
||||
## @field verticalPodAutoscaler.valuesOverride {object} Custom values to override
|
||||
##
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.velero {velero} Velero
|
||||
##
|
||||
velero:
|
||||
## @field velero.enabled {bool} Enable Velero for backup and recovery of a tenant Kubernetes cluster.
|
||||
## @field velero.valuesOverride {object} Custom values to override
|
||||
##
|
||||
enabled: false
|
||||
valuesOverride: {}
|
||||
|
||||
## @field addons.coredns {coredns} Coredns
|
||||
##
|
||||
coredns:
|
||||
## @field coredns.valuesOverride {object} Custom values to override
|
||||
##
|
||||
valuesOverride: {}
|
||||
|
||||
##
|
||||
## @section Kubernetes Control Plane Configuration
|
||||
##
|
||||
## @param controlPlane {controlPlane} Control Plane Configuration
|
||||
|
||||
## @typedef {struct} APIServer - API Server configuration.
|
||||
## @field {Resources} resources - CPU and memory resources for API Server.
|
||||
## @field {ResourcesPreset} resourcesPreset="medium" - Preset if `resources` omitted.
|
||||
|
||||
## @typedef {struct} ControllerManager - Controller Manager configuration.
|
||||
## @field {Resources} resources - CPU and memory resources for Controller Manager.
|
||||
## @field {ResourcesPreset} resourcesPreset="micro" - Preset if `resources` omitted.
|
||||
|
||||
## @typedef {struct} Scheduler - Scheduler configuration.
|
||||
## @field {Resources} resources - CPU and memory resources for Scheduler.
|
||||
## @field {ResourcesPreset} resourcesPreset="micro" - Preset if `resources` omitted.
|
||||
|
||||
## @typedef {struct} KonnectivityServer - Konnectivity Server configuration.
|
||||
## @field {Resources} resources - CPU and memory resources for Konnectivity.
|
||||
## @field {ResourcesPreset} resourcesPreset="micro" - Preset if `resources` omitted.
|
||||
|
||||
## @typedef {struct} Konnectivity - Konnectivity configuration.
|
||||
## @field {KonnectivityServer} server - Konnectivity Server configuration.
|
||||
|
||||
## @typedef {struct} ControlPlane - Kubernetes control plane configuration.
|
||||
## @field {int} replicas=2 - Number of control-plane replicas.
|
||||
## @field {APIServer} apiServer - API Server configuration.
|
||||
## @field {ControllerManager} controllerManager - Controller Manager configuration.
|
||||
## @field {Scheduler} scheduler - Scheduler configuration.
|
||||
## @field {Konnectivity} konnectivity - Konnectivity configuration.
|
||||
|
||||
## @param {ControlPlane} controlPlane - Kubernetes control-plane configuration.
|
||||
controlPlane:
|
||||
## @field controlPlane.replicas {int} Number of replicas for Kubernetes control plane components.
|
||||
replicas: 2
|
||||
## @field controlPlane.apiServer {apiServer} Control plane API server configuration.
|
||||
apiServer:
|
||||
## @field apiServer.resources {resources} Explicit CPU and memory configuration for the API Server. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## e.g:
|
||||
## resources:
|
||||
## cpu: 4000m
|
||||
## memory: 4Gi
|
||||
##
|
||||
resources: {}
|
||||
## @field apiServer.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "medium"
|
||||
|
||||
## @field controlPlane.controllerManager {controllerManager} Controller Manager configuration.
|
||||
controllerManager:
|
||||
## @field controllerManager.resources {resources} Explicit CPU and memory configuration for the Controller Manager. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field controllerManager.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "micro"
|
||||
resources: {}
|
||||
|
||||
## @field controlPlane.scheduler {scheduler} Scheduler configuration.
|
||||
resourcesPreset: "micro"
|
||||
scheduler:
|
||||
## @field scheduler.resources {resources} Explicit CPU and memory configuration for the Scheduler. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field scheduler.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "micro"
|
||||
resources: {}
|
||||
|
||||
## @field controlPlane.konnectivity {konnectivity} Konnectivity configuration.
|
||||
resourcesPreset: "micro"
|
||||
konnectivity:
|
||||
## @field konnectivity.server {konnectivityServer} Konnectivity server configuration.
|
||||
server:
|
||||
## @field konnectivityServer.resources {resources} Explicit CPU and memory configuration for Konnectivity. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field konnectivityServer.resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
resourcesPreset: "micro"
|
||||
resources: {}
|
||||
resourcesPreset: "micro"
|
||||
|
||||
@@ -69,44 +69,44 @@ more details:
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of MariaDB replicas | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each MariaDB replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `replicas` | Number of MariaDB replicas. | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each MariaDB replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` |
|
||||
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------------- | --------------------------------------- | ------------------- | ------- |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `string` | `""` |
|
||||
| `users[name].maxUserConnections` | Maximum amount of connections | `int` | `0` |
|
||||
| `databases` | Databases configuration | `map[string]object` | `{...}` |
|
||||
| `databases[name].roles` | Roles for the database | `*object` | `null` |
|
||||
| `databases[name].roles.admin` | List of users with admin privileges | `[]string` | `[]` |
|
||||
| `databases[name].roles.readonly` | List of users with read-only privileges | `[]string` | `[]` |
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------------- | ---------------------------------------- | ------------------- | ----- |
|
||||
| `users` | Users configuration map. | `map[string]object` | `{}` |
|
||||
| `users[name].password` | Password for the user. | `string` | `""` |
|
||||
| `users[name].maxUserConnections` | Maximum number of connections. | `int` | `0` |
|
||||
| `databases` | Databases configuration map. | `map[string]object` | `{}` |
|
||||
| `databases[name].roles` | Roles assigned to users. | `object` | `{}` |
|
||||
| `databases[name].roles.admin` | List of users with admin privileges. | `[]string` | `[]` |
|
||||
| `databases[name].roles.readonly` | List of users with read-only privileges. | `[]string` | `[]` |
|
||||
|
||||
|
||||
### Backup parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------- | -------- | ------------------------------------------------------ |
|
||||
| `backup` | Backup configuration | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups, default is `false`. | `bool` | `false` |
|
||||
| `backup.s3Region` | AWS S3 region where backups are stored | `string` | `us-east-1` |
|
||||
| `backup.s3Bucket` | S3 bucket used for storing backups | `string` | `s3.example.org/mysql-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `string` | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | Retention strategy for cleaning up old backups | `string` | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `string` | `<your-secret-key>` |
|
||||
| `backup.resticPassword` | Password for Restic backup encryption | `string` | `<password>` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ----------------------------------------------- | -------- | ------------------------------------------------------ |
|
||||
| `backup` | Backup configuration. | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups (default: false). | `bool` | `false` |
|
||||
| `backup.s3Region` | AWS S3 region where backups are stored. | `string` | `us-east-1` |
|
||||
| `backup.s3Bucket` | S3 bucket used for storing backups. | `string` | `s3.example.org/mysql-backups` |
|
||||
| `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * *` |
|
||||
| `backup.cleanupStrategy` | Retention strategy for cleaning up old backups. | `string` | `--keep-last=3 --keep-daily=3 --keep-within-weekly=1m` |
|
||||
| `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3 authentication. | `string` | `<your-secret-key>` |
|
||||
| `backup.resticPassword` | Password for Restic backup encryption. | `string` | `<password>` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
74
packages/apps/mysql/templates/hooks/cleanup-pvc.yaml
Normal file
74
packages/apps/mysql/templates/hooks/cleanup-pvc.yaml
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-cleanup
|
||||
labels:
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
annotations:
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-weight": "10"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
policy.cozystack.io/allow-to-apiserver: "true"
|
||||
spec:
|
||||
serviceAccountName: {{ .Release.Name }}-cleanup
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: cleanup
|
||||
image: docker.io/clastix/kubectl:v1.32
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
echo "Deleting orphaned PVCs for {{ .Release.Name }}..."
|
||||
kubectl delete pvc -n {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} || true
|
||||
echo "PVC cleanup complete."
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-cleanup
|
||||
labels:
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
annotations:
|
||||
"helm.sh/hook": post-delete
|
||||
helm.sh/hook-weight: "0"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-cleanup
|
||||
labels:
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
annotations:
|
||||
"helm.sh/hook": post-delete
|
||||
"helm.sh/hook-weight": "5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["persistentvolumeclaims"]
|
||||
verbs: ["get", "list", "delete"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ .Release.Name }}-cleanup
|
||||
labels:
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
annotations:
|
||||
"helm.sh/hook": post-delete
|
||||
helm.sh/hook-weight: "5"
|
||||
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ .Release.Name }}-cleanup
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ .Release.Name }}-cleanup
|
||||
@@ -3,7 +3,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup": {
|
||||
"description": "Backup configuration",
|
||||
"description": "Backup configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -18,67 +18,67 @@
|
||||
],
|
||||
"properties": {
|
||||
"cleanupStrategy": {
|
||||
"description": "Retention strategy for cleaning up old backups",
|
||||
"description": "Retention strategy for cleaning up old backups.",
|
||||
"type": "string",
|
||||
"default": "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Enable regular backups, default is `false`.",
|
||||
"description": "Enable regular backups (default: false).",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"resticPassword": {
|
||||
"description": "Password for Restic backup encryption",
|
||||
"description": "Password for Restic backup encryption.",
|
||||
"type": "string",
|
||||
"default": "\u003cpassword\u003e"
|
||||
},
|
||||
"s3AccessKey": {
|
||||
"description": "Access key for S3, used for authentication",
|
||||
"description": "Access key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-access-key\u003e"
|
||||
},
|
||||
"s3Bucket": {
|
||||
"description": "S3 bucket used for storing backups",
|
||||
"description": "S3 bucket used for storing backups.",
|
||||
"type": "string",
|
||||
"default": "s3.example.org/mysql-backups"
|
||||
},
|
||||
"s3Region": {
|
||||
"description": "AWS S3 region where backups are stored",
|
||||
"description": "AWS S3 region where backups are stored.",
|
||||
"type": "string",
|
||||
"default": "us-east-1"
|
||||
},
|
||||
"s3SecretKey": {
|
||||
"description": "Secret key for S3, used for authentication",
|
||||
"description": "Secret key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-secret-key\u003e"
|
||||
},
|
||||
"schedule": {
|
||||
"description": "Cron schedule for automated backups",
|
||||
"description": "Cron schedule for automated backups.",
|
||||
"type": "string",
|
||||
"default": "0 2 * * *"
|
||||
}
|
||||
}
|
||||
},
|
||||
"databases": {
|
||||
"description": "Databases configuration",
|
||||
"description": "Databases configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"roles": {
|
||||
"description": "Roles for the database",
|
||||
"description": "Roles assigned to users.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin": {
|
||||
"description": "List of users with admin privileges",
|
||||
"description": "List of users with admin privileges.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"readonly": {
|
||||
"description": "List of users with read-only privileges",
|
||||
"description": "List of users with read-only privileges.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
@@ -90,22 +90,22 @@
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of MariaDB replicas",
|
||||
"description": "Number of MariaDB replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each MariaDB replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each MariaDB replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -118,7 +118,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -133,7 +133,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
@@ -147,7 +147,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -161,11 +161,12 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"description": "Users configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
@@ -176,11 +177,11 @@
|
||||
],
|
||||
"properties": {
|
||||
"maxUserConnections": {
|
||||
"description": "Maximum amount of connections",
|
||||
"description": "Maximum number of connections.",
|
||||
"type": "integer"
|
||||
},
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"description": "Password for the user.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,48 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of MariaDB replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each MariaDB replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of MariaDB replicas.
|
||||
replicas: 2
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each MariaDB replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each MariaDB replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
|
||||
## @param {ResourcesPreset} resourcesPreset="nano" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "nano"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
|
||||
## @param {quantity} size - Persistent Volume Claim size available for application data.
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {string} Password for the user
|
||||
## @field user.maxUserConnections {int} Maximum amount of connections
|
||||
|
||||
## @typedef {struct} User - User configuration.
|
||||
## @field {string} password - Password for the user.
|
||||
## @field {int} maxUserConnections - Maximum number of connections.
|
||||
|
||||
## @param {map[string]User} users - Users configuration map.
|
||||
users: {}
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
@@ -31,15 +51,16 @@ external: false
|
||||
## user2:
|
||||
## maxUserConnections: 1000
|
||||
## password: hackme
|
||||
##
|
||||
users: {}
|
||||
|
||||
## @typedef {struct} DatabaseRoles - Role assignments for a database.
|
||||
## @field {[]string} [admin] - List of users with admin privileges.
|
||||
## @field {[]string} [readonly] - List of users with read-only privileges.
|
||||
|
||||
## @param databases {map[string]database} Databases configuration
|
||||
## @field database.roles {*databaseRoles} Roles for the database
|
||||
## @field databaseRoles.admin {[]string} List of users with admin privileges
|
||||
## @field databaseRoles.readonly {[]string} List of users with read-only privileges
|
||||
##
|
||||
## @typedef {struct} Database - Database configuration.
|
||||
## @field {DatabaseRoles} [roles] - Roles assigned to users.
|
||||
|
||||
## @param {map[string]Database} databases - Databases configuration map.
|
||||
databases: {}
|
||||
## Example:
|
||||
## databases:
|
||||
## myapp1:
|
||||
@@ -48,19 +69,22 @@ users: {}
|
||||
## - user1
|
||||
## readonly:
|
||||
## - user2
|
||||
databases: {}
|
||||
|
||||
##
|
||||
## @section Backup parameters
|
||||
##
|
||||
## @param backup {backup} Backup configuration
|
||||
## @field backup.enabled {bool} Enable regular backups, default is `false`.
|
||||
## @field backup.s3Region {string} AWS S3 region where backups are stored
|
||||
## @field backup.s3Bucket {string} S3 bucket used for storing backups
|
||||
## @field backup.schedule {string} Cron schedule for automated backups
|
||||
## @field backup.cleanupStrategy {string} Retention strategy for cleaning up old backups
|
||||
## @field backup.s3AccessKey {string} Access key for S3, used for authentication
|
||||
## @field backup.s3SecretKey {string} Secret key for S3, used for authentication
|
||||
## @field backup.resticPassword {string} Password for Restic backup encryption
|
||||
|
||||
## @typedef {struct} Backup - Backup configuration.
|
||||
## @field {bool} enabled - Enable regular backups (default: false).
|
||||
## @field {string} s3Region - AWS S3 region where backups are stored.
|
||||
## @field {string} s3Bucket - S3 bucket used for storing backups.
|
||||
## @field {string} schedule - Cron schedule for automated backups.
|
||||
## @field {string} cleanupStrategy - Retention strategy for cleaning up old backups.
|
||||
## @field {string} s3AccessKey - Access key for S3 authentication.
|
||||
## @field {string} s3SecretKey - Secret key for S3 authentication.
|
||||
## @field {string} resticPassword - Password for Restic backup encryption.
|
||||
|
||||
## @param {Backup} backup - Backup configuration.
|
||||
backup:
|
||||
enabled: false
|
||||
s3Region: us-east-1
|
||||
@@ -70,4 +94,3 @@ backup:
|
||||
s3AccessKey: "<your-access-key>"
|
||||
s3SecretKey: "<your-secret-key>"
|
||||
resticPassword: "<password>"
|
||||
|
||||
|
||||
@@ -7,29 +7,29 @@ It provides a data layer for cloud native applications, IoT messaging, and micro
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of replicas | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each NATS replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------- |
|
||||
| `replicas` | Number of replicas. | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each NATS replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------- | ------- |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| `jetstream` | Jetstream configuration | `object` | `{}` |
|
||||
| `jetstream.enabled` | Enable or disable Jetstream. Set to `true` (default) to enable Jetstream for persistent messaging in NATS. | `bool` | `true` |
|
||||
| `jetstream.size` | Jetstream persistent storage size. Specifies the size of the persistent storage for Jetstream (message store). | `quantity` | `10Gi` |
|
||||
| `config` | NATS configuration | `object` | `{}` |
|
||||
| `config.merge` | Additional configuration to merge into NATS config (see example) | `*object` | `{}` |
|
||||
| `config.resolver` | Additional resolver configuration to merge into NATS config (see example) | `*object` | `{}` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------------- | ------------------------------------------------------------- | ------------------- | ------ |
|
||||
| `users` | Users configuration map. | `map[string]object` | `{}` |
|
||||
| `users[name].password` | Password for the user. | `string` | `""` |
|
||||
| `jetstream` | Jetstream configuration. | `object` | `{}` |
|
||||
| `jetstream.enabled` | Enable or disable Jetstream for persistent messaging in NATS. | `bool` | `true` |
|
||||
| `jetstream.size` | Jetstream persistent storage size. | `quantity` | `10Gi` |
|
||||
| `config` | NATS configuration. | `object` | `{}` |
|
||||
| `config.merge` | Additional configuration to merge into NATS config. | `*object` | `{}` |
|
||||
| `config.resolver` | Additional resolver configuration to merge into NATS config. | `*object` | `{}` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
{{- $cozyConfig := lookup "v1" "ConfigMap" "cozy-system" "cozystack" }}
|
||||
{{- $clusterDomain := (index $cozyConfig.data "cluster-domain") | default "cozy.local" }}
|
||||
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }}
|
||||
{{- $passwords := dict }}
|
||||
|
||||
{{- with (dig "data" (dict) $existingSecret) }}
|
||||
{{- range $k, $v := . }}
|
||||
{{- $_ := set $passwords $k (b64dec $v) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $user, $u := .Values.users }}
|
||||
{{- if $u.password }}
|
||||
{{- $_ := set $passwords $user $u.password }}
|
||||
@@ -47,18 +55,14 @@ spec:
|
||||
retries: -1
|
||||
values:
|
||||
nats:
|
||||
podTemplate:
|
||||
container:
|
||||
merge:
|
||||
spec:
|
||||
containers:
|
||||
- name: nats
|
||||
image: nats:2.10.17-alpine
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 22 }}
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 12 }}
|
||||
fullnameOverride: {{ .Release.Name }}
|
||||
config:
|
||||
{{- if or (gt (len $passwords) 0) (gt (len .Values.config.merge) 0) }}
|
||||
{{- if or $passwords .Values.config.merge }}
|
||||
merge:
|
||||
{{- if gt (len $passwords) 0 }}
|
||||
{{- if $passwords }}
|
||||
accounts:
|
||||
A:
|
||||
users:
|
||||
@@ -67,13 +71,13 @@ spec:
|
||||
password: "{{ $password }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and .Values.config (hasKey .Values.config "merge") }}
|
||||
{{ toYaml .Values.config.merge | nindent 12 }}
|
||||
{{- with .Values.config.merge }}
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and .Values.config (hasKey .Values.config "resolver") }}
|
||||
{{- with .Values.config.resolver }}
|
||||
resolver:
|
||||
{{ toYaml .Values.config.resolver | nindent 12 }}
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
cluster:
|
||||
enabled: true
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {
|
||||
"description": "NATS configuration",
|
||||
"description": "NATS configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"merge": {
|
||||
"description": "Additional configuration to merge into NATS config (see example)",
|
||||
"description": "Additional configuration to merge into NATS config.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
},
|
||||
"resolver": {
|
||||
"description": "Additional resolver configuration to merge into NATS config (see example)",
|
||||
"description": "Additional resolver configuration to merge into NATS config.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"x-kubernetes-preserve-unknown-fields": true
|
||||
@@ -22,12 +22,12 @@
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"jetstream": {
|
||||
"description": "Jetstream configuration",
|
||||
"description": "Jetstream configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -36,12 +36,12 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable or disable Jetstream. Set to `true` (default) to enable Jetstream for persistent messaging in NATS.",
|
||||
"description": "Enable or disable Jetstream for persistent messaging in NATS.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"size": {
|
||||
"description": "Jetstream persistent storage size. Specifies the size of the persistent storage for Jetstream (message store).",
|
||||
"description": "Jetstream persistent storage size.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -57,17 +57,17 @@
|
||||
}
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of replicas",
|
||||
"description": "Number of replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each NATS replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each NATS replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -80,7 +80,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -95,7 +95,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
@@ -109,18 +109,19 @@
|
||||
]
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"description": "Users configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"description": "Password for the user.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +1,64 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each NATS replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of replicas.
|
||||
replicas: 2
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each NATS replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each NATS replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
|
||||
## @param {ResourcesPreset} resourcesPreset="nano" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "nano"
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {*string} Password for the user
|
||||
|
||||
## @typedef {struct} User - User configuration.
|
||||
## @field {string} [password] - Password for the user.
|
||||
|
||||
## @param {map[string]User} users - Users configuration map.
|
||||
users: {}
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
## password: strongpassword
|
||||
## user2: {}
|
||||
users: {}
|
||||
|
||||
## @param jetstream {jetstream} Jetstream configuration
|
||||
## @typedef {struct} Jetstream - Jetstream configuration.
|
||||
## @field {bool} enabled=true - Enable or disable Jetstream for persistent messaging in NATS.
|
||||
## @field {quantity} size - Jetstream persistent storage size.
|
||||
|
||||
## @param {Jetstream} jetstream - Jetstream configuration.
|
||||
jetstream:
|
||||
## @field jetstream.enabled {bool} Enable or disable Jetstream. Set to `true` (default) to enable Jetstream for persistent messaging in NATS.
|
||||
##
|
||||
## Default: true
|
||||
enabled: true
|
||||
## @field jetstream.size {quantity} Jetstream persistent storage size. Specifies the size of the persistent storage for Jetstream (message store).
|
||||
##
|
||||
size: 10Gi
|
||||
|
||||
## @param config {config} NATS configuration
|
||||
config:
|
||||
## @field config.merge {*object} Additional configuration to merge into NATS config (see example)
|
||||
## Allows you to customize NATS server settings by merging additional configurations.
|
||||
## For example, you can add extra parameters, configure authentication, or set custom settings.
|
||||
## Default: {}
|
||||
## example:
|
||||
##
|
||||
## merge:
|
||||
## $include: ./my-config.conf
|
||||
## zzz$include: ./my-config-last.conf
|
||||
## server_name: nats
|
||||
## authorization:
|
||||
## token: << $TOKEN >>
|
||||
## jetstream:
|
||||
## max_memory_store: << 1GB >>
|
||||
##
|
||||
## will yield the config:
|
||||
## {
|
||||
## include ./my-config.conf;
|
||||
## "authorization": {
|
||||
## "token": $TOKEN
|
||||
## },
|
||||
## "jetstream": {
|
||||
## "max_memory_store": 1GB
|
||||
## },
|
||||
## "server_name": "nats",
|
||||
## include ./my-config-last.conf;
|
||||
## }
|
||||
merge: {}
|
||||
## @field config.resolver {*object} Additional resolver configuration to merge into NATS config (see example)
|
||||
## Allows you to customize NATS server settings by merging resolver configurations.
|
||||
## Default: {}
|
||||
## Example: https://github.com/nats-io/k8s/blob/94414664c254b0bbac3a07fc9693f6c4f8f88709/helm/charts/nats/values.yaml#L248-L270
|
||||
resolver: {}
|
||||
## @typedef {struct} Config - NATS configuration.
|
||||
## @field {*object} [merge] - Additional configuration to merge into NATS config.
|
||||
## @field {*object} [resolver] - Additional resolver configuration to merge into NATS config.
|
||||
|
||||
## @param {Config} config - NATS configuration.
|
||||
config:
|
||||
merge: {}
|
||||
resolver: {}
|
||||
|
||||
@@ -66,60 +66,78 @@ See:
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of Postgres replicas | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each PostgreSQL replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `micro` |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------- |
|
||||
| `replicas` | Number of Postgres replicas. | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each PostgreSQL replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `micro` |
|
||||
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------- | ------- |
|
||||
| `postgresql` | PostgreSQL server configuration | `object` | `{}` |
|
||||
| `postgresql.parameters` | PostgreSQL server parameters | `object` | `{}` |
|
||||
| `postgresql.parameters.max_connections` | Determines the maximum number of concurrent connections to the database server. The default is typically 100 connections | `int` | `100` |
|
||||
| `quorum` | Quorum configuration for synchronous replication | `object` | `{}` |
|
||||
| `quorum.minSyncReplicas` | Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed. | `int` | `0` |
|
||||
| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the number of instances). | `int` | `0` |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| `users[name].replication` | Whether the user has replication privileges | `*bool` | `null` |
|
||||
| `databases` | Databases configuration | `map[string]object` | `{...}` |
|
||||
| `databases[name].roles` | Roles for the database | `*object` | `null` |
|
||||
| `databases[name].roles.admin` | List of users with admin privileges | `[]string` | `[]` |
|
||||
| `databases[name].roles.readonly` | List of users with read-only privileges | `[]string` | `[]` |
|
||||
| `databases[name].extensions` | Extensions enabled for the database | `[]string` | `[]` |
|
||||
| Name | Description | Type | Value |
|
||||
| --------------------------------------- | ---------------------------------------------------------------- | -------- | ----- |
|
||||
| `postgresql` | PostgreSQL server configuration. | `object` | `{}` |
|
||||
| `postgresql.parameters` | PostgreSQL server parameters. | `object` | `{}` |
|
||||
| `postgresql.parameters.max_connections` | Maximum number of concurrent connections to the database server. | `int` | `100` |
|
||||
|
||||
|
||||
### Quorum-based synchronous replication
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------------------------------------------- | -------- | ----- |
|
||||
| `quorum` | Quorum configuration for synchronous replication. | `object` | `{}` |
|
||||
| `quorum.minSyncReplicas` | Minimum number of synchronous replicas required for commit. | `int` | `0` |
|
||||
| `quorum.maxSyncReplicas` | Maximum number of synchronous replicas allowed (must be less than total replicas). | `int` | `0` |
|
||||
|
||||
|
||||
### Users configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------- | -------------------------------------------- | ------------------- | ------- |
|
||||
| `users` | Users configuration map. | `map[string]object` | `{}` |
|
||||
| `users[name].password` | Password for the user. | `string` | `""` |
|
||||
| `users[name].replication` | Whether the user has replication privileges. | `bool` | `false` |
|
||||
|
||||
|
||||
### Databases configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------------- | ---------------------------------------- | ------------------- | ----- |
|
||||
| `databases` | Databases configuration map. | `map[string]object` | `{}` |
|
||||
| `databases[name].roles` | Roles assigned to users. | `object` | `{}` |
|
||||
| `databases[name].roles.admin` | List of users with admin privileges. | `[]string` | `[]` |
|
||||
| `databases[name].roles.readonly` | List of users with read-only privileges. | `[]string` | `[]` |
|
||||
| `databases[name].extensions` | List of enabled PostgreSQL extensions. | `[]string` | `[]` |
|
||||
|
||||
|
||||
### Backup parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ---------------------------------------------------------- | --------- | ----------------------------------- |
|
||||
| `backup` | Backup configuration | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups | `*bool` | `false` |
|
||||
| `backup.schedule` | Cron schedule for automated backups | `*string` | `0 2 * * * *` |
|
||||
| `backup.retentionPolicy` | Retention policy | `*string` | `30d` |
|
||||
| `backup.destinationPath` | Path to store the backup (i.e. s3://bucket/path/to/folder) | `*string` | `s3://bucket/path/to/folder/` |
|
||||
| `backup.endpointURL` | S3 Endpoint used to upload data to the cloud | `*string` | `http://minio-gateway-service:9000` |
|
||||
| `backup.s3AccessKey` | Access key for S3, used for authentication | `*string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3, used for authentication | `*string` | `<your-secret-key>` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ------------------------------------------------------ | -------- | ----------------------------------- |
|
||||
| `backup` | Backup configuration. | `object` | `{}` |
|
||||
| `backup.enabled` | Enable regular backups. | `bool` | `false` |
|
||||
| `backup.schedule` | Cron schedule for automated backups. | `string` | `0 2 * * * *` |
|
||||
| `backup.retentionPolicy` | Retention policy (e.g. "30d"). | `string` | `30d` |
|
||||
| `backup.destinationPath` | Destination path for backups (e.g. s3://bucket/path/). | `string` | `s3://bucket/path/to/folder/` |
|
||||
| `backup.endpointURL` | S3 endpoint URL for uploads. | `string` | `http://minio-gateway-service:9000` |
|
||||
| `backup.s3AccessKey` | Access key for S3 authentication. | `string` | `<your-access-key>` |
|
||||
| `backup.s3SecretKey` | Secret key for S3 authentication. | `string` | `<your-secret-key>` |
|
||||
|
||||
|
||||
### Bootstrap (recovery) parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
|
||||
| `bootstrap` | Bootstrap configuration | `object` | `{}` |
|
||||
| `bootstrap.enabled` | Restore database cluster from a backup | `bool` | `false` |
|
||||
| `bootstrap.recoveryTime` | Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest | `*string` | `""` |
|
||||
| `bootstrap.oldName` | Name of database cluster before deleting | `string` | `""` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------------ | ------------------------------------------------------------------- | -------- | ------- |
|
||||
| `bootstrap` | Bootstrap configuration. | `object` | `{}` |
|
||||
| `bootstrap.enabled` | Whether to restore from a backup. | `bool` | `false` |
|
||||
| `bootstrap.recoveryTime` | Timestamp (RFC3339) for point-in-time recovery; empty means latest. | `string` | `""` |
|
||||
| `bootstrap.oldName` | Previous cluster name before deletion. | `string` | `""` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -3,49 +3,52 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backup": {
|
||||
"description": "Backup configuration",
|
||||
"description": "Backup configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"properties": {
|
||||
"destinationPath": {
|
||||
"description": "Path to store the backup (i.e. s3://bucket/path/to/folder)",
|
||||
"description": "Destination path for backups (e.g. s3://bucket/path/).",
|
||||
"type": "string",
|
||||
"default": "s3://bucket/path/to/folder/"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Enable regular backups",
|
||||
"description": "Enable regular backups.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"endpointURL": {
|
||||
"description": "S3 Endpoint used to upload data to the cloud",
|
||||
"description": "S3 endpoint URL for uploads.",
|
||||
"type": "string",
|
||||
"default": "http://minio-gateway-service:9000"
|
||||
},
|
||||
"retentionPolicy": {
|
||||
"description": "Retention policy",
|
||||
"description": "Retention policy (e.g. \"30d\").",
|
||||
"type": "string",
|
||||
"default": "30d"
|
||||
},
|
||||
"s3AccessKey": {
|
||||
"description": "Access key for S3, used for authentication",
|
||||
"description": "Access key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-access-key\u003e"
|
||||
},
|
||||
"s3SecretKey": {
|
||||
"description": "Secret key for S3, used for authentication",
|
||||
"description": "Secret key for S3 authentication.",
|
||||
"type": "string",
|
||||
"default": "\u003cyour-secret-key\u003e"
|
||||
},
|
||||
"schedule": {
|
||||
"description": "Cron schedule for automated backups",
|
||||
"description": "Cron schedule for automated backups.",
|
||||
"type": "string",
|
||||
"default": "0 2 * * * *"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bootstrap": {
|
||||
"description": "Bootstrap configuration",
|
||||
"description": "Bootstrap configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -54,47 +57,49 @@
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Restore database cluster from a backup",
|
||||
"description": "Whether to restore from a backup.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"oldName": {
|
||||
"description": "Name of database cluster before deleting",
|
||||
"type": "string"
|
||||
"description": "Previous cluster name before deletion.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"recoveryTime": {
|
||||
"description": "Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest",
|
||||
"type": "string"
|
||||
"description": "Timestamp (RFC3339) for point-in-time recovery; empty means latest.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"databases": {
|
||||
"description": "Databases configuration",
|
||||
"description": "Databases configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"extensions": {
|
||||
"description": "Extensions enabled for the database",
|
||||
"description": "List of enabled PostgreSQL extensions.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"description": "Roles for the database",
|
||||
"description": "Roles assigned to users.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin": {
|
||||
"description": "List of users with admin privileges",
|
||||
"description": "List of users with admin privileges.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"readonly": {
|
||||
"description": "List of users with read-only privileges",
|
||||
"description": "List of users with read-only privileges.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
@@ -106,28 +111,22 @@
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"postgresql": {
|
||||
"description": "PostgreSQL server configuration",
|
||||
"description": "PostgreSQL server configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"parameters"
|
||||
],
|
||||
"properties": {
|
||||
"parameters": {
|
||||
"description": "PostgreSQL server parameters",
|
||||
"description": "PostgreSQL server parameters.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"max_connections"
|
||||
],
|
||||
"properties": {
|
||||
"max_connections": {
|
||||
"description": "Determines the maximum number of concurrent connections to the database server. The default is typically 100 connections",
|
||||
"description": "Maximum number of concurrent connections to the database server.",
|
||||
"type": "integer",
|
||||
"default": 100
|
||||
}
|
||||
@@ -136,7 +135,7 @@
|
||||
}
|
||||
},
|
||||
"quorum": {
|
||||
"description": "Quorum configuration for synchronous replication",
|
||||
"description": "Quorum configuration for synchronous replication.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -145,29 +144,29 @@
|
||||
],
|
||||
"properties": {
|
||||
"maxSyncReplicas": {
|
||||
"description": "Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the number of instances).",
|
||||
"description": "Maximum number of synchronous replicas allowed (must be less than total replicas).",
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"minSyncReplicas": {
|
||||
"description": "Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed.",
|
||||
"description": "Minimum number of synchronous replicas required for commit.",
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of Postgres replicas",
|
||||
"description": "Number of Postgres replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each PostgreSQL replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each PostgreSQL replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -180,7 +179,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -195,7 +194,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "micro",
|
||||
"enum": [
|
||||
@@ -209,7 +208,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -223,22 +222,23 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"description": "Users configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"description": "Password for the user.",
|
||||
"type": "string"
|
||||
},
|
||||
"replication": {
|
||||
"description": "Whether the user has replication privileges",
|
||||
"description": "Whether the user has replication privileges.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,76 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of Postgres replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each PostgreSQL replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of Postgres replicas.
|
||||
replicas: 2
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each PostgreSQL replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each PostgreSQL replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
|
||||
## @param {ResourcesPreset} resourcesPreset="micro" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "micro"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
|
||||
## @param {quantity} size - Persistent Volume Claim size available for application data.
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
## @section Application-specific parameters
|
||||
## @param postgresql {postgresql} PostgreSQL server configuration
|
||||
## @field postgresql.parameters {postgresqlParameters} PostgreSQL server parameters
|
||||
## @field postgresqlParameters.max_connections {int} Determines the maximum number of concurrent connections to the database server. The default is typically 100 connections
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
|
||||
## @typedef {struct} PostgreSQLParameters - PostgreSQL server parameters.
|
||||
## @field {int} [max_connections] - Maximum number of concurrent connections to the database server.
|
||||
|
||||
## @typedef {struct} PostgreSQL - PostgreSQL server configuration.
|
||||
## @field {PostgreSQLParameters} [parameters] - PostgreSQL server parameters.
|
||||
|
||||
## @param {PostgreSQL} postgresql - PostgreSQL server configuration.
|
||||
postgresql:
|
||||
parameters:
|
||||
max_connections: 100
|
||||
|
||||
## Configuration for the quorum-based synchronous replication
|
||||
## @param quorum {quorum} Quorum configuration for synchronous replication
|
||||
## @field quorum.minSyncReplicas {int} Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed.
|
||||
## @field quorum.maxSyncReplicas {int} Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the number of instances).
|
||||
##
|
||||
## @section Quorum-based synchronous replication
|
||||
##
|
||||
|
||||
## @typedef {struct} Quorum - Quorum configuration for synchronous replication.
|
||||
## @field {int} minSyncReplicas - Minimum number of synchronous replicas required for commit.
|
||||
## @field {int} maxSyncReplicas - Maximum number of synchronous replicas allowed (must be less than total replicas).
|
||||
|
||||
## @param {Quorum} quorum - Quorum configuration for synchronous replication.
|
||||
quorum:
|
||||
minSyncReplicas: 0
|
||||
maxSyncReplicas: 0
|
||||
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {*string} Password for the user
|
||||
## @field user.replication {*bool} Whether the user has replication privileges
|
||||
##
|
||||
## @section Users configuration
|
||||
##
|
||||
|
||||
## @typedef {struct} User - User configuration.
|
||||
## @field {string} [password] - Password for the user.
|
||||
## @field {bool} [replication] - Whether the user has replication privileges.
|
||||
|
||||
## @param {map[string]User} users - Users configuration map.
|
||||
users: {}
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
@@ -49,15 +81,21 @@ quorum:
|
||||
## password: qwerty123
|
||||
## debezium:
|
||||
## replication: true
|
||||
##
|
||||
users: {}
|
||||
|
||||
## @param databases {map[string]database} Databases configuration
|
||||
## @field database.roles {*databaseRoles} Roles for the database
|
||||
## @field databaseRoles.admin {[]string} List of users with admin privileges
|
||||
## @field databaseRoles.readonly {[]string} List of users with read-only privileges
|
||||
## @field database.extensions {[]string} Extensions enabled for the database
|
||||
##
|
||||
## @section Databases configuration
|
||||
##
|
||||
|
||||
## @typedef {struct} DatabaseRoles - Role assignments for a database.
|
||||
## @field {[]string} [admin] - List of users with admin privileges.
|
||||
## @field {[]string} [readonly] - List of users with read-only privileges.
|
||||
|
||||
## @typedef {struct} Database - Database configuration.
|
||||
## @field {DatabaseRoles} [roles] - Roles assigned to users.
|
||||
## @field {[]string} [extensions] - List of enabled PostgreSQL extensions.
|
||||
|
||||
## @param {map[string]Database} databases - Databases configuration map.
|
||||
databases: {}
|
||||
## Example:
|
||||
## databases:
|
||||
## myapp:
|
||||
@@ -73,18 +111,21 @@ users: {}
|
||||
## - airflow
|
||||
## extensions:
|
||||
## - hstore
|
||||
databases: {}
|
||||
|
||||
##
|
||||
## @section Backup parameters
|
||||
##
|
||||
|
||||
## @param backup {backup} Backup configuration
|
||||
## @field backup.enabled {*bool} Enable regular backups
|
||||
## @field backup.schedule {*string} Cron schedule for automated backups
|
||||
## @field backup.retentionPolicy {*string} Retention policy
|
||||
## @field backup.destinationPath {*string} Path to store the backup (i.e. s3://bucket/path/to/folder)
|
||||
## @field backup.endpointURL {*string} S3 Endpoint used to upload data to the cloud
|
||||
## @field backup.s3AccessKey {*string} Access key for S3, used for authentication
|
||||
## @field backup.s3SecretKey {*string} Secret key for S3, used for authentication
|
||||
## @typedef {struct} Backup - Backup configuration.
|
||||
## @field {bool} enabled - Enable regular backups.
|
||||
## @field {string} [schedule] - Cron schedule for automated backups.
|
||||
## @field {string} [retentionPolicy] - Retention policy (e.g. "30d").
|
||||
## @field {string} [destinationPath] - Destination path for backups (e.g. s3://bucket/path/).
|
||||
## @field {string} [endpointURL] - S3 endpoint URL for uploads.
|
||||
## @field {string} [s3AccessKey] - Access key for S3 authentication.
|
||||
## @field {string} [s3SecretKey] - Secret key for S3 authentication.
|
||||
|
||||
## @param {Backup} backup - Backup configuration.
|
||||
backup:
|
||||
enabled: false
|
||||
retentionPolicy: 30d
|
||||
@@ -94,16 +135,18 @@ backup:
|
||||
s3AccessKey: "<your-access-key>"
|
||||
s3SecretKey: "<your-secret-key>"
|
||||
|
||||
## @section Bootstrap (recovery) parameters
|
||||
|
||||
## @param bootstrap {bootstrap} Bootstrap configuration
|
||||
## @field bootstrap.enabled {bool} Restore database cluster from a backup
|
||||
## @field bootstrap.recoveryTime {*string} Timestamp (PITR) up to which recovery will proceed, expressed in RFC 3339 format. If left empty, will restore latest
|
||||
## @field bootstrap.oldName {string} Name of database cluster before deleting
|
||||
##
|
||||
## @section Bootstrap (recovery) parameters
|
||||
##
|
||||
|
||||
## @typedef {struct} Bootstrap - Bootstrap configuration for restoring a database cluster from a backup.
|
||||
## @field {bool} enabled - Whether to restore from a backup.
|
||||
## @field {string} [recoveryTime] - Timestamp (RFC3339) for point-in-time recovery; empty means latest.
|
||||
## @field {string} oldName - Previous cluster name before deletion.
|
||||
|
||||
## @param {Bootstrap} bootstrap - Bootstrap configuration.
|
||||
bootstrap:
|
||||
enabled: false
|
||||
# example: 2020-11-26 15:22:00.00000+00
|
||||
recoveryTime: ""
|
||||
oldName: ""
|
||||
|
||||
|
||||
@@ -13,28 +13,28 @@ The service utilizes official RabbitMQ operator. This ensures the reliability an
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of RabbitMQ replicas | `int` | `3` |
|
||||
| `resources` | Explicit CPU and memory configuration for each RabbitMQ replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `replicas` | Number of RabbitMQ replicas. | `int` | `3` |
|
||||
| `resources` | Explicit CPU and memory configuration for each RabbitMQ replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` |
|
||||
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `10Gi` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ----------------------------- | --------------------------- | ------------------- | ------- |
|
||||
| `users` | Users configuration | `map[string]object` | `{...}` |
|
||||
| `users[name].password` | Password for the user | `*string` | `null` |
|
||||
| `vhosts` | Virtual Hosts configuration | `map[string]object` | `{...}` |
|
||||
| `vhosts[name].roles` | Virtual host roles list | `object` | `{}` |
|
||||
| `vhosts[name].roles.admin` | List of admin users | `[]string` | `[]` |
|
||||
| `vhosts[name].roles.readonly` | List of readonly users | `[]string` | `[]` |
|
||||
| Name | Description | Type | Value |
|
||||
| ----------------------------- | -------------------------------- | ------------------- | ----- |
|
||||
| `users` | Users configuration map. | `map[string]object` | `{}` |
|
||||
| `users[name].password` | Password for the user. | `string` | `""` |
|
||||
| `vhosts` | Virtual hosts configuration map. | `map[string]object` | `{}` |
|
||||
| `vhosts[name].roles` | Virtual host roles list. | `object` | `{}` |
|
||||
| `vhosts[name].roles.admin` | List of admin users. | `[]string` | `[]` |
|
||||
| `vhosts[name].roles.readonly` | List of readonly users. | `[]string` | `[]` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of RabbitMQ replicas",
|
||||
"description": "Number of RabbitMQ replicas.",
|
||||
"type": "integer",
|
||||
"default": 3
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each RabbitMQ replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each RabbitMQ replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -31,7 +31,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -46,7 +46,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
@@ -60,7 +60,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "10Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -74,25 +74,26 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"users": {
|
||||
"description": "Users configuration",
|
||||
"description": "Users configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"description": "Password for the user",
|
||||
"description": "Password for the user.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vhosts": {
|
||||
"description": "Virtual Hosts configuration",
|
||||
"description": "Virtual hosts configuration map.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
@@ -102,18 +103,18 @@
|
||||
],
|
||||
"properties": {
|
||||
"roles": {
|
||||
"description": "Virtual host roles list",
|
||||
"description": "Virtual host roles list.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin": {
|
||||
"description": "List of admin users",
|
||||
"description": "List of admin users.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"readonly": {
|
||||
"description": "List of readonly users",
|
||||
"description": "List of readonly users.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
|
||||
@@ -1,29 +1,47 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of RabbitMQ replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each RabbitMQ replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of RabbitMQ replicas.
|
||||
replicas: 3
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each RabbitMQ replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each RabbitMQ replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
## @param {ResourcesPreset} resourcesPreset="nano" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "nano"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
|
||||
## @param {quantity} size - Persistent Volume Claim size available for application data.
|
||||
size: 10Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param users {map[string]user} Users configuration
|
||||
## @field user.password {*string} Password for the user
|
||||
|
||||
## @typedef {struct} User - User configuration.
|
||||
## @field {string} [password] - Password for the user.
|
||||
|
||||
## @param {map[string]User} users - Users configuration map.
|
||||
users: {}
|
||||
## Example:
|
||||
## users:
|
||||
## user1:
|
||||
@@ -32,14 +50,16 @@ external: false
|
||||
## password: hackme
|
||||
## user3:
|
||||
## password: testtest
|
||||
##
|
||||
users: {}
|
||||
|
||||
## @param vhosts {map[string]vhost} Virtual Hosts configuration
|
||||
## @field vhost.roles {roles} Virtual host roles list
|
||||
## @field roles.admin {[]string} List of admin users
|
||||
## @field roles.readonly {[]string} List of readonly users
|
||||
##
|
||||
## @typedef {struct} Roles - Virtual host roles.
|
||||
## @field {[]string} [admin] - List of admin users.
|
||||
## @field {[]string} [readonly] - List of readonly users.
|
||||
|
||||
## @typedef {struct} Vhost - Virtual host configuration.
|
||||
## @field {Roles} roles - Virtual host roles list.
|
||||
|
||||
## @param {map[string]Vhost} vhosts - Virtual hosts configuration map.
|
||||
vhosts: {}
|
||||
## Example:
|
||||
## vhosts:
|
||||
## myapp:
|
||||
@@ -53,5 +73,3 @@ users: {}
|
||||
## roles:
|
||||
## admin:
|
||||
## - user3
|
||||
vhosts: {}
|
||||
|
||||
|
||||
@@ -13,23 +13,23 @@ Service utilizes the Spotahome Redis Operator for efficient management and orche
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- |
|
||||
| `replicas` | Number of Redis replicas | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each Redis replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| `size` | Persistent Volume Claim size, available for application data | `quantity` | `1Gi` |
|
||||
| `storageClass` | StorageClass used to store the data | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `replicas` | Number of Redis replicas. | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each Redis replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` |
|
||||
| `size` | Persistent Volume Claim size available for application data. | `quantity` | `1Gi` |
|
||||
| `storageClass` | StorageClass used to store the data. | `string` | `""` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------- | -------------------------- | ------ | ------ |
|
||||
| `authEnabled` | Enable password generation | `bool` | `true` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------- | --------------------------- | ------ | ------ |
|
||||
| `authEnabled` | Enable password generation. | `bool` | `true` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -27,6 +27,7 @@ spec:
|
||||
replicas: 3
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 6 }}
|
||||
redis:
|
||||
image: "redis:8.2.0"
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) | nindent 6 }}
|
||||
replicas: {{ .Values.replicas }}
|
||||
{{- with .Values.size }}
|
||||
|
||||
@@ -3,27 +3,27 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"authEnabled": {
|
||||
"description": "Enable password generation",
|
||||
"description": "Enable password generation.",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of Redis replicas",
|
||||
"description": "Number of Redis replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each Redis replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each Redis replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -36,7 +36,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -51,7 +51,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
@@ -65,7 +65,7 @@
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"description": "Persistent Volume Claim size, available for application data",
|
||||
"description": "Persistent Volume Claim size available for application data.",
|
||||
"default": "1Gi",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
@@ -79,8 +79,9 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"storageClass": {
|
||||
"description": "StorageClass used to store the data",
|
||||
"type": "string"
|
||||
"description": "StorageClass used to store the data.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,41 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of Redis replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each Redis replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of Redis replicas.
|
||||
replicas: 2
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each Redis replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each Redis replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
|
||||
## @param {ResourcesPreset} resourcesPreset="nano" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "nano"
|
||||
## @param size {quantity} Persistent Volume Claim size, available for application data
|
||||
|
||||
## @param {quantity} size - Persistent Volume Claim size available for application data.
|
||||
size: 1Gi
|
||||
## @param storageClass {string} StorageClass used to store the data
|
||||
|
||||
## @param {string} storageClass - StorageClass used to store the data.
|
||||
storageClass: ""
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param authEnabled {bool} Enable password generation
|
||||
|
||||
## @param {bool} authEnabled - Enable password generation.
|
||||
authEnabled: true
|
||||
|
||||
@@ -12,28 +12,28 @@ Managed TCP Load Balancer Service efficiently utilizes HAProxy for load balancin
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------- |
|
||||
| `replicas` | Number of HAProxy replicas | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each TCP Balancer replica. When left empty, the preset defined in `resourcesPreset` is applied. | `*object` | `null` |
|
||||
| `resources.cpu` | CPU available to each replica | `*quantity` | `null` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica | `*quantity` | `null` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`. | `string` | `nano` |
|
||||
| `external` | Enable external access from outside the cluster | `bool` | `false` |
|
||||
| Name | Description | Type | Value |
|
||||
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `replicas` | Number of HAProxy replicas. | `int` | `2` |
|
||||
| `resources` | Explicit CPU and memory configuration for each TCP Balancer replica. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
|
||||
| `resources.cpu` | CPU available to each replica. | `quantity` | `""` |
|
||||
| `resources.memory` | Memory (RAM) available to each replica. | `quantity` | `""` |
|
||||
| `resourcesPreset` | Default sizing preset used when `resources` is omitted. | `string` | `nano` |
|
||||
| `external` | Enable external access from outside the cluster. | `bool` | `false` |
|
||||
|
||||
|
||||
### Application-specific parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------------- | ---------------------------------------------------------------- | ---------- | ------- |
|
||||
| `httpAndHttps` | HTTP and HTTPS configuration | `object` | `{}` |
|
||||
| `httpAndHttps.mode` | Mode for balancer. Allowed values: `tcp` and `tcp-with-proxy` | `string` | `tcp` |
|
||||
| `httpAndHttps.targetPorts` | Target ports configuration | `object` | `{}` |
|
||||
| `httpAndHttps.targetPorts.http` | HTTP port number. | `int` | `80` |
|
||||
| `httpAndHttps.targetPorts.https` | HTTPS port number. | `int` | `443` |
|
||||
| `httpAndHttps.endpoints` | Endpoint addresses list | `[]string` | `[]` |
|
||||
| `whitelistHTTP` | Secure HTTP by whitelisting client networks, `false` by default. | `bool` | `false` |
|
||||
| `whitelist` | List of allowed client networks | `[]string` | `[]` |
|
||||
| Name | Description | Type | Value |
|
||||
| -------------------------------- | ------------------------------------------------------------- | ---------- | ------- |
|
||||
| `httpAndHttps` | HTTP and HTTPS configuration. | `object` | `{}` |
|
||||
| `httpAndHttps.mode` | Mode for balancer. | `string` | `tcp` |
|
||||
| `httpAndHttps.targetPorts` | Target ports configuration. | `object` | `{}` |
|
||||
| `httpAndHttps.targetPorts.http` | HTTP port number. | `int` | `80` |
|
||||
| `httpAndHttps.targetPorts.https` | HTTPS port number. | `int` | `443` |
|
||||
| `httpAndHttps.endpoints` | Endpoint addresses list. | `[]string` | `[]` |
|
||||
| `whitelistHTTP` | Secure HTTP by whitelisting client networks (default: false). | `bool` | `false` |
|
||||
| `whitelist` | List of allowed client networks. | `[]string` | `[]` |
|
||||
|
||||
|
||||
## Parameter examples and reference
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"external": {
|
||||
"description": "Enable external access from outside the cluster",
|
||||
"description": "Enable external access from outside the cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"httpAndHttps": {
|
||||
"description": "HTTP and HTTPS configuration",
|
||||
"description": "HTTP and HTTPS configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -17,7 +17,7 @@
|
||||
],
|
||||
"properties": {
|
||||
"endpoints": {
|
||||
"description": "Endpoint addresses list",
|
||||
"description": "Endpoint addresses list.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
@@ -25,7 +25,7 @@
|
||||
}
|
||||
},
|
||||
"mode": {
|
||||
"description": "Mode for balancer. Allowed values: `tcp` and `tcp-with-proxy`",
|
||||
"description": "Mode for balancer.",
|
||||
"type": "string",
|
||||
"default": "tcp",
|
||||
"enum": [
|
||||
@@ -34,7 +34,7 @@
|
||||
]
|
||||
},
|
||||
"targetPorts": {
|
||||
"description": "Target ports configuration",
|
||||
"description": "Target ports configuration.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
@@ -57,16 +57,17 @@
|
||||
}
|
||||
},
|
||||
"replicas": {
|
||||
"description": "Number of HAProxy replicas",
|
||||
"description": "Number of HAProxy replicas.",
|
||||
"type": "integer",
|
||||
"default": 2
|
||||
},
|
||||
"resources": {
|
||||
"description": "Explicit CPU and memory configuration for each TCP Balancer replica. When left empty, the preset defined in `resourcesPreset` is applied.",
|
||||
"description": "Explicit CPU and memory configuration for each TCP Balancer replica. When omitted, the preset defined in `resourcesPreset` is applied.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"description": "CPU available to each replica",
|
||||
"description": "CPU available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -79,7 +80,7 @@
|
||||
"x-kubernetes-int-or-string": true
|
||||
},
|
||||
"memory": {
|
||||
"description": "Memory (RAM) available to each replica",
|
||||
"description": "Memory (RAM) available to each replica.",
|
||||
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -94,7 +95,7 @@
|
||||
}
|
||||
},
|
||||
"resourcesPreset": {
|
||||
"description": "Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.",
|
||||
"description": "Default sizing preset used when `resources` is omitted.",
|
||||
"type": "string",
|
||||
"default": "nano",
|
||||
"enum": [
|
||||
@@ -108,7 +109,7 @@
|
||||
]
|
||||
},
|
||||
"whitelist": {
|
||||
"description": "List of allowed client networks",
|
||||
"description": "List of allowed client networks.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
@@ -116,7 +117,7 @@
|
||||
}
|
||||
},
|
||||
"whitelistHTTP": {
|
||||
"description": "Secure HTTP by whitelisting client networks, `false` by default.",
|
||||
"description": "Secure HTTP by whitelisting client networks (default: false).",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
|
||||
@@ -1,44 +1,50 @@
|
||||
##
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param replicas {int} Number of HAProxy replicas
|
||||
|
||||
## @typedef {struct} Resources - Explicit CPU and memory configuration for each TCP Balancer replica.
|
||||
## @field {quantity} [cpu] - CPU available to each replica.
|
||||
## @field {quantity} [memory] - Memory (RAM) available to each replica.
|
||||
|
||||
## @enum {string} ResourcesPreset - Default sizing preset.
|
||||
## @value nano
|
||||
## @value micro
|
||||
## @value small
|
||||
## @value medium
|
||||
## @value large
|
||||
## @value xlarge
|
||||
## @value 2xlarge
|
||||
|
||||
## @param {int} replicas - Number of HAProxy replicas.
|
||||
replicas: 2
|
||||
## @param resources {*resources} Explicit CPU and memory configuration for each TCP Balancer replica. When left empty, the preset defined in `resourcesPreset` is applied.
|
||||
## @field resources.cpu {*quantity} CPU available to each replica
|
||||
## @field resources.memory {*quantity} Memory (RAM) available to each replica
|
||||
#resources: {}
|
||||
# resources:
|
||||
# cpu: 4000m
|
||||
# memory: 4Gi
|
||||
## @param resourcesPreset {string enum:"nano,micro,small,medium,large,xlarge,2xlarge"} Default sizing preset used when `resources` is omitted. Allowed values: `nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`.
|
||||
|
||||
## @param {Resources} [resources] - Explicit CPU and memory configuration for each TCP Balancer replica. When omitted, the preset defined in `resourcesPreset` is applied.
|
||||
resources: {}
|
||||
|
||||
## @param {ResourcesPreset} resourcesPreset="nano" - Default sizing preset used when `resources` is omitted.
|
||||
resourcesPreset: "nano"
|
||||
##
|
||||
## @param external {bool} Enable external access from outside the cluster
|
||||
|
||||
## @param {bool} external - Enable external access from outside the cluster.
|
||||
external: false
|
||||
|
||||
|
||||
##
|
||||
## @section Application-specific parameters
|
||||
##
|
||||
## @param httpAndHttps {httpAndHttps} HTTP and HTTPS configuration
|
||||
## @field httpAndHttps.mode {string enum:"tcp,tcp-with-proxy"} Mode for balancer. Allowed values: `tcp` and `tcp-with-proxy`
|
||||
## @field httpAndHttps.targetPorts {targetPorts} Target ports configuration
|
||||
## @field targetPorts.http {int} HTTP port number.
|
||||
## @field targetPorts.https {int} HTTPS port number.
|
||||
## @field httpAndHttps.endpoints {[]string} Endpoint addresses list
|
||||
## Example:
|
||||
##
|
||||
## httpAndHttps:
|
||||
## mode: tcp
|
||||
## targetPorts:
|
||||
## http: 80
|
||||
## https: 443
|
||||
## endpoints:
|
||||
## - 10.100.3.1
|
||||
## - 10.100.3.11
|
||||
## - 10.100.3.2
|
||||
## - 10.100.3.12
|
||||
## - 10.100.3.3
|
||||
## - 10.100.3.13
|
||||
|
||||
## @enum {string} Mode - Mode for balancer.
|
||||
## @value tcp
|
||||
## @value tcp-with-proxy
|
||||
|
||||
## @typedef {struct} TargetPorts - Target ports configuration.
|
||||
## @field {int} http - HTTP port number.
|
||||
## @field {int} https - HTTPS port number.
|
||||
|
||||
## @typedef {struct} HttpAndHttps - HTTP and HTTPS configuration.
|
||||
## @field {Mode} mode - Mode for balancer.
|
||||
## @field {TargetPorts} targetPorts - Target ports configuration.
|
||||
## @field {[]string} endpoints - Endpoint addresses list.
|
||||
|
||||
## @param {HttpAndHttps} httpAndHttps - HTTP and HTTPS configuration.
|
||||
httpAndHttps:
|
||||
mode: tcp
|
||||
targetPorts:
|
||||
@@ -46,14 +52,14 @@ httpAndHttps:
|
||||
https: 443
|
||||
endpoints: []
|
||||
|
||||
## @param whitelistHTTP {bool} Secure HTTP by whitelisting client networks, `false` by default.
|
||||
## @param whitelist {[]string} List of allowed client networks
|
||||
## @param {bool} whitelistHTTP - Secure HTTP by whitelisting client networks (default: false).
|
||||
whitelistHTTP: false
|
||||
## Example:
|
||||
## whitelistHTTP: true
|
||||
## whitelist:
|
||||
## - "1.2.3.4"
|
||||
## - "10.100.0.0/16"
|
||||
##
|
||||
whitelistHTTP: false
|
||||
whitelist: []
|
||||
|
||||
## @param {[]string} whitelist - List of allowed client networks.
|
||||
whitelist: []
|
||||
|
||||
@@ -69,13 +69,13 @@ tenant-u1
|
||||
|
||||
### Common parameters
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------- | ------- |
|
||||
| `host` | The hostname used to access tenant services (defaults to using the tenant name as a subdomain for it's parent tenant host). | `*string` | `""` |
|
||||
| `etcd` | Deploy own Etcd cluster | `bool` | `false` |
|
||||
| `monitoring` | Deploy own Monitoring Stack | `bool` | `false` |
|
||||
| `ingress` | Deploy own Ingress Controller | `bool` | `false` |
|
||||
| `seaweedfs` | Deploy own SeaweedFS | `bool` | `false` |
|
||||
| `isolated` | Enforce tenant namespace with network policies, `true` by default | `bool` | `true` |
|
||||
| `resourceQuotas` | Define resource quotas for the tenant | `map[string]quantity` | `{}` |
|
||||
| Name | Description | Type | Value |
|
||||
| ---------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------- | ------- |
|
||||
| `host` | The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host). | `string` | `""` |
|
||||
| `etcd` | Deploy own Etcd cluster. | `bool` | `false` |
|
||||
| `monitoring` | Deploy own Monitoring Stack. | `bool` | `false` |
|
||||
| `ingress` | Deploy own Ingress Controller. | `bool` | `false` |
|
||||
| `seaweedfs` | Deploy own SeaweedFS. | `bool` | `false` |
|
||||
| `isolated` | Enforce tenant namespace with network policies (default: true). | `bool` | `true` |
|
||||
| `resourceQuotas` | Define resource quotas for the tenant. | `map[string]quantity` | `{}` |
|
||||
|
||||
|
||||
@@ -20,11 +20,7 @@ metadata:
|
||||
name: allow-external-communication
|
||||
namespace: {{ include "tenant.name" . }}
|
||||
spec:
|
||||
endpointSelector:
|
||||
matchExpressions:
|
||||
- key: policy.cozystack.io/allow-external-communication
|
||||
operator: NotIn
|
||||
values: ["false"]
|
||||
endpointSelector: {}
|
||||
ingress:
|
||||
- fromEntities:
|
||||
- world
|
||||
|
||||
@@ -28,13 +28,13 @@ rules:
|
||||
- cozystack.io
|
||||
resources:
|
||||
- workloadmonitors
|
||||
- workloads
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups:
|
||||
- core.cozystack.io
|
||||
resources:
|
||||
- tenantmodules
|
||||
- tenantsecrets
|
||||
- tenantsecretstables
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
@@ -113,6 +113,7 @@ rules:
|
||||
- cozystack.io
|
||||
resources:
|
||||
- workloadmonitors
|
||||
- workloads
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
kind: RoleBinding
|
||||
@@ -184,13 +185,13 @@ rules:
|
||||
- cozystack.io
|
||||
resources:
|
||||
- workloadmonitors
|
||||
- workloads
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups:
|
||||
- core.cozystack.io
|
||||
resources:
|
||||
- tenantmodules
|
||||
- tenantsecrets
|
||||
- tenantsecretstables
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
kind: RoleBinding
|
||||
@@ -270,6 +271,7 @@ rules:
|
||||
- vmdisks
|
||||
- vminstances
|
||||
- infos
|
||||
- virtualprivateclouds
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
@@ -282,13 +284,13 @@ rules:
|
||||
- cozystack.io
|
||||
resources:
|
||||
- workloadmonitors
|
||||
- workloads
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups:
|
||||
- core.cozystack.io
|
||||
resources:
|
||||
- tenantmodules
|
||||
- tenantsecrets
|
||||
- tenantsecretstables
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
kind: RoleBinding
|
||||
@@ -356,13 +358,13 @@ rules:
|
||||
- cozystack.io
|
||||
resources:
|
||||
- workloadmonitors
|
||||
- workloads
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups:
|
||||
- core.cozystack.io
|
||||
resources:
|
||||
- tenantmodules
|
||||
- tenantsecrets
|
||||
- tenantsecretstables
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
kind: RoleBinding
|
||||
|
||||
@@ -3,31 +3,32 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"etcd": {
|
||||
"description": "Deploy own Etcd cluster",
|
||||
"description": "Deploy own Etcd cluster.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"host": {
|
||||
"description": "The hostname used to access tenant services (defaults to using the tenant name as a subdomain for it's parent tenant host).",
|
||||
"type": "string"
|
||||
"description": "The hostname used to access tenant services (defaults to using the tenant name as a subdomain for its parent tenant host).",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"ingress": {
|
||||
"description": "Deploy own Ingress Controller",
|
||||
"description": "Deploy own Ingress Controller.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"isolated": {
|
||||
"description": "Enforce tenant namespace with network policies, `true` by default",
|
||||
"description": "Enforce tenant namespace with network policies (default: true).",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"monitoring": {
|
||||
"description": "Deploy own Monitoring Stack",
|
||||
"description": "Deploy own Monitoring Stack.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"resourceQuotas": {
|
||||
"description": "Define resource quotas for the tenant",
|
||||
"description": "Define resource quotas for the tenant.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"additionalProperties": {
|
||||
@@ -44,7 +45,7 @@
|
||||
}
|
||||
},
|
||||
"seaweedfs": {
|
||||
"description": "Deploy own SeaweedFS",
|
||||
"description": "Deploy own SeaweedFS.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user