Files
cozystack/packages/apps/mongodb/values.schema.json
Andrey Kolkov 46a8bd7363 fix(mongodb): apply the storage once per job, and pin the terms that decide ownership
The system-bucket storage was applied on every reconcile of a job, not
once per job: with the operator CR already minted nothing returned before
the apply, so a streaming dump saw an SSA patch every poll for up to a
day, and the only thing keeping that patch off a cluster that had
re-acquired the chart's tasks and pitr since the mint was a predicate
term no test held. The storage a CR names is fixed for its dump, so the
apply now runs only before the CR exists; the legacy-render hold covers
that window, and a test pins that an existing CR is never injected over.

The other predicate that decides whether a Backup owns an archive
compared the live entry's bucket and credentialsSecret against the
strategy, and only the bucket half had a fixture. The credential is what
tells a tenant's entry from the platform's when a bucket name collides,
so a case varying only that term joins the foreign-bucket one. The
cleanup shortcut's snapshot-kind term and the 24h running ceiling are
pinned the same way, the latter as an absolute boundary pair.

The generated field description said the schema rejects useSystemBucket
without backup.enabled. The aggregated apiserver does not evaluate CEL on
application schemas yet, so the render-time refusal is the one that
holds; the description and the runbook now say so. The runbook's restore
paragraph still described the unconditional credential swap this branch
narrowed, exempted MariaDB from a retention warning its shipped strategy
does not earn, and pointed at a Plan retention field that does not
exist; the example README and a dispatcher test's comment still carried
the pre-branch claim that the driver never injects and never deletes.

Assisted-by: LLM
Signed-off-by: Andrey Kolkov <androndo@gmail.com>
2026-09-29 10:14:44 +04:00

356 lines
11 KiB
JSON

{
"title": "Chart Values",
"type": "object",
"properties": {
"replicas": {
"description": "Number of MongoDB replicas in replica set.",
"type": "integer",
"default": 3
},
"resources": {
"description": "Explicit CPU and memory configuration for each MongoDB replica. When omitted, the preset defined in `resourcesPreset` is applied.",
"type": "object",
"default": {},
"properties": {
"cpu": {
"description": "CPU available to each replica.",
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"x-kubernetes-int-or-string": true
},
"memory": {
"description": "Memory (RAM) available to each replica.",
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"x-kubernetes-int-or-string": true
}
}
},
"resourcesPreset": {
"description": "Default sizing preset used when `resources` is omitted.",
"type": "string",
"default": "t1.small",
"enum": [
"t1.nano",
"t1.micro",
"t1.small",
"t1.medium",
"t1.large",
"t1.xlarge",
"t1.2xlarge",
"t1.4xlarge",
"c1.nano",
"c1.micro",
"c1.small",
"c1.medium",
"c1.large",
"c1.xlarge",
"c1.2xlarge",
"c1.4xlarge",
"s1.nano",
"s1.micro",
"s1.small",
"s1.medium",
"s1.large",
"s1.xlarge",
"s1.2xlarge",
"s1.4xlarge",
"u1.nano",
"u1.micro",
"u1.small",
"u1.medium",
"u1.large",
"u1.xlarge",
"u1.2xlarge",
"u1.4xlarge",
"m1.nano",
"m1.micro",
"m1.small",
"m1.medium",
"m1.large",
"m1.xlarge",
"m1.2xlarge",
"m1.4xlarge",
"nano",
"micro",
"small",
"medium",
"large",
"xlarge",
"2xlarge"
]
},
"size": {
"description": "Persistent Volume Claim size available for application data.",
"default": "10Gi",
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"x-kubernetes-int-or-string": true
},
"storageClass": {
"description": "StorageClass used to store the data.",
"type": "string",
"default": "",
"x-kubernetes-validations": [
{
"rule": "self == oldSelf",
"message": "storageClass is immutable"
}
],
"x-cozystack-options": {
"source": "storageclass"
}
},
"external": {
"description": "Enable external access from outside the cluster.",
"type": "boolean",
"default": false
},
"version": {
"description": "MongoDB major version to deploy.",
"type": "string",
"default": "v8",
"enum": [
"v8",
"v7",
"v6"
]
},
"sharding": {
"description": "Enable sharded cluster mode. When disabled, deploys a replica set.",
"type": "boolean",
"default": false
},
"shardingConfig": {
"description": "Configuration for sharded cluster mode.",
"type": "object",
"default": {},
"required": [
"configServerSize",
"configServers",
"mongos"
],
"properties": {
"configServerSize": {
"description": "PVC size for config servers.",
"default": "3Gi",
"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
},
"configServers": {
"description": "Number of config server replicas.",
"type": "integer",
"default": 3
},
"mongos": {
"description": "Number of mongos router replicas.",
"type": "integer",
"default": 2
},
"shards": {
"description": "List of shard configurations.",
"type": "array",
"default": [
{
"name": "rs0",
"replicas": 3,
"size": "10Gi"
}
],
"items": {
"type": "object",
"required": [
"name",
"replicas",
"size"
],
"properties": {
"name": {
"description": "Shard name.",
"type": "string"
},
"replicas": {
"description": "Number of replicas in this shard.",
"type": "integer"
},
"size": {
"description": "PVC size for this shard.",
"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
}
}
}
}
}
},
"users": {
"description": "Users configuration map.",
"type": "object",
"default": {},
"additionalProperties": {
"type": "object",
"properties": {
"password": {
"description": "Password for the user (auto-generated if omitted).",
"type": "string"
}
}
}
},
"databases": {
"description": "Databases configuration map.",
"type": "object",
"default": {},
"additionalProperties": {
"type": "object",
"properties": {
"roles": {
"description": "Roles assigned to users.",
"type": "object",
"properties": {
"admin": {
"description": "List of users with admin privileges (readWrite + dbAdmin).",
"type": "array",
"items": {
"type": "string"
}
},
"readonly": {
"description": "List of users with read-only privileges.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"backup": {
"description": "Backup configuration.",
"type": "object",
"default": {},
"required": [
"enabled"
],
"properties": {
"destinationPath": {
"description": "Destination path for backups (e.g. s3://bucket/path/). Ignored when useSystemBucket is true (the driver injects the platform bucket).",
"type": "string",
"default": "s3://bucket/path/to/folder/"
},
"enabled": {
"description": "Enable regular backups.",
"type": "boolean",
"default": false
},
"endpointURL": {
"description": "S3 endpoint URL for uploads. Ignored when useSystemBucket is true (the strategy supplies the platform endpoint).",
"type": "string",
"default": "http://minio-gateway-service:9000"
},
"insecureSkipTLSVerify": {
"description": "Skip TLS verification for the S3 endpoint (self-signed, e.g. in-cluster seaweedfs). Ignored when useSystemBucket is true (the platform backupStorage knob applies instead).",
"type": "boolean",
"default": false
},
"retentionPolicy": {
"description": "Retention policy (e.g. \"30d\"). Ignored when useSystemBucket is true (no engine-side retention on that flow).",
"type": "string",
"default": "30d"
},
"s3AccessKey": {
"description": "Access key for S3 authentication. Ignored when useSystemBucket is true (credentials come from the projected cozy-backups-creds).",
"type": "string",
"default": ""
},
"s3SecretKey": {
"description": "Secret key for S3 authentication. Ignored when useSystemBucket is true (credentials come from the projected cozy-backups-creds).",
"type": "string",
"default": ""
},
"schedule": {
"description": "Cron schedule for automated backups. Ignored when useSystemBucket is true (scheduling moves to the BackupClass Plan).",
"type": "string",
"default": "0 2 * * *"
},
"useSystemBucket": {
"description": "Opt-in: back up to the platform system bucket without supplying S3 credentials. The cozy-default MongoDB BackupClass injects the storage at BackupJob time; tenants do not set s3AccessKey/s3SecretKey/destinationPath/endpointURL, and backups scope to `\u003cnamespace\u003e/\u003capplication\u003e`. Scheduling moves to a BackupClass Plan; `schedule`, `retentionPolicy` and PITR are ignored while this is on, and this flow has no retention yet (see docs/operations/backup-classes.md). Requires `backup.enabled: true` (the pbm agents run on that flag); the chart refuses the combination with `enabled: false` at render time; the schema carries the same rule as a marker for the UI and for the day the apiserver enforces CEL on application schemas (cozystack/cozystack#2657), which it does not yet. A release that has not yet rendered this flag (its cluster still carries the chart's scheduled tasks and PITR) holds a BackupJob until it does, so the tenant's own storage is never injected over.",
"type": "boolean",
"default": false
}
},
"x-kubernetes-validations": [
{
"message": "backup.useSystemBucket requires backup.enabled: the percona-backup-mongodb agents only run when backups are enabled",
"rule": "!(has(self.useSystemBucket) \u0026\u0026 self.useSystemBucket) || (has(self.enabled) \u0026\u0026 self.enabled)"
}
]
},
"bootstrap": {
"description": "Bootstrap configuration.",
"type": "object",
"default": {},
"required": [
"backupName",
"enabled"
],
"properties": {
"backupName": {
"description": "Name of backup to restore from.",
"type": "string",
"default": ""
},
"enabled": {
"description": "Whether to restore from a backup.",
"type": "boolean",
"default": false
},
"recoveryTime": {
"description": "Timestamp for point-in-time recovery; empty means latest.",
"type": "string",
"default": ""
}
}
}
}
}