Skip to content

fix(apps): keep Job and CronJob names within the Kubernetes limits - #4945

Merged
Aleksei Sviridkin (lexfrei) merged 2 commits into
cozystack:mainfrom
yankawai:fix/app-job-names-63
Nov 13, 2026
Merged

Aleksei Sviridkin (lexfrei) merged 2 commits into
cozystack:mainfrom
yankawai:fix/app-job-names-63

Conversation

@yankawai

@yankawai europrinter (yankawai) commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

The apps API admits release names of up to 53 characters, the release prefix included (less for Kafka and Kubernetes, which cap their own names). Kubernetes copies a Job name into the job-name label of its pods, and a label value takes at most 63 characters, so the apiserver refuses a Job with a longer name. A CronJob name is refused over 52 characters, because the controller names each Job it starts <cronjob>-<timestamp>. I rendered every Job and CronJob in packages/apps and packages/extra with the longest release name each application admits, and eight of them go over.

Application Object Name Longest on main After
bucket post-delete Job <release>-cleanup-acme 66 63
qdrant post-delete Job <release>-qdrant-cleanup 68 63
kafka pre-install and pre-upgrade Job <release>-kafka-migration 66 (release capped at 50) 63
vm-disk resize Job, rendered when the disk grows <release>-volume-resize-hook 72 63
vm-instance update Job and the app label of its pod <release>-update-hook 65 63
mariadb backup CronJob <release>-backup 60 52
clickhouse legacy backup CronJob <release>-backup 60 52
tenant pre-delete Job in cozy-system <tenant namespace>-cleanup 71 (nested namespace of 63) 63

Counted in characters of the application name, a Kafka of 42 to 44 cannot be installed today, a VMDisk of 37 or more cannot grow, and a VMInstance of 40 or 41 cannot take an instance type, profile or external change. Deleting a Bucket of 44 or more or a Qdrant of 42 or more fails in the post-delete hook. With the backup CronJob enabled, a MariaDB of 38 or more and a ClickHouse of 35 or more fail the whole release. A nested tenant whose namespace is longer than 55 characters cannot be deleted.

The Jobs of bucket, qdrant, kafka, vm-disk and vm-instance are now named printf "%s-<suffix>" .Release.Name | trunc 63 | trimSuffix "-", and vm-instance uses the same value for the pod label. A release name is never longer than 53, so only the fixed suffix is cut, and a brute-force check over every pair of release name lengths found no two release names that render the same Job name.

A plain cut to 52 would reach into the release name of a CronJob, and two 53-character names that differ in the last character would share one. So a CronJob name that does not fit becomes the release name cut to 38 characters, the first six hex characters of its sha256 and -backup, the shape #4133 gave the ClickHouse Keeper name. The tenant cleanup Job takes the same form with the namespace cut to 48, because it runs in cozy-system next to the cleanup Job of every other tenant. There a plain cut gives a parent and a child named clea the same name, and the child's before-hook-creation would delete the parent's Job while it runs.

Names that fit render exactly as before. The hook documents rendered from main and from this branch with the short release names the tests use are identical in all eight charts. A name that did not fit never produced an object, so nothing is renamed on upgrade. The ServiceAccounts, Roles and RoleBindings of these hooks keep their names, since they have no such limit, so the ones a pre-install hook left behind are replaced rather than orphaned. Helm runs the delete hooks stored with a release, so an existing Bucket, Qdrant or tenant picks up the fix with its next upgrade.

Every other Job and CronJob fits at the longest name. The cleanup Jobs of clickhouse, harbor, mariadb and opensearch and the Kafka pre-delete Job reach 61, the Postgres init Job 62, and the Kubernetes and KubernetesNodes Jobs either stay under 63 or already cut their names. The etcd and monitoring modules require their chart name as the release name, and the gateway and seaweedfs cleanup Jobs reach 61.

Each of the eight charts gets a new helm-unittest suite. It pins a short name, a name that lands exactly on the limit and the longest admitted name, a cut that would end in a dash wherever one can happen, and for the hooks the unchanged ServiceAccount and RBAC names. The CronJob suites also pin two 53-character names that differ in the last character, and the tenant suite pins the parent and child pair. Against the templates on main, 18 of the 41 new cases fail, every one with a name over the limit. With the hash forms replaced by a plain cut, the tenant parent and child both render tenant-abcdefghijklmnopqrstuvwxyz-0123456789abcdefghijklmn-clea and the two MariaDB names both render mariadb-abcdefghijklmnopqrstuvwxyz0123456789abcdefgh. hack/helm-unit-tests.sh passes over all 106 packages with tests. The Bats files that exercise these hooks and charts (app-cleanup-hooks_test, kafka-migration-hook, kafka-pre-delete-hook, tenant-pre-delete-hook, check-hook-request-timeout, pod-label-census_test, mariadb-first-boot-waits, check-render-matrix) give 96 ok on main and on this branch. make generate with cozyvalues-gen v1.7.0 in the eight packages changes nothing. A local kube-apiserver v1.35.0 refuses the longest name each chart renders on main, with must be no more than 63 bytes on the job-name label or must be no more than 52 characters on the CronJob, and creates the name from this branch. For vm-disk and vm-instance, whose hooks render only after a live lookup, that check used a Job with the same name and labels.

This is related to #4875 but does not depend on it. #4875 adds a cozy-lib cleanup Job and cuts its name to 63 the same way, while this PR covers the Jobs already on main. Neither needs the other, and the two merge cleanly.

Screenshots

Not a UI change.

Downstream repositories

Templates and tests only. No values, schema, README, defaults, ApplicationDefinition, Secret or Service name changes, and none of the changed Job or CronJob names appears in the website, the Terraform provider, the Ansible collection or the other repositories on the list.

Release note

fix(apps): Job and CronJob names now fit the Kubernetes limits for the longest application names. A Kafka with a name of 42 to 44 characters can now be installed, long VMDisk and VMInstance names no longer fail a resize or an instance type change, long Bucket and Qdrant names and long nested tenant namespaces no longer fail deletion, and long MariaDB and ClickHouse names no longer fail the release with the backup CronJob enabled.

Summary by CodeRabbit

  • Bug Fixes
    • Cleanup, migration, resize, and update Jobs now use names that fit Kubernetes naming limits, including for long release or tenant names.
    • ClickHouse and MariaDB backup CronJobs now use names within Kubernetes’ length limit. Longer names are shortened with a hash suffix to help distinguish them.
    • Short names and names at the supported limit retain their existing naming format.

The apps API admits release names of up to 53 characters, and several
charts name a Job <release>-<suffix>. Kubernetes copies a Job name into
the job-name label of its pods, and a label value takes at most 63
characters, so the apiserver refused these Jobs for the longest names. A
Kafka whose name has 42 to 44 characters could not be installed, a
VMDisk of 37 or more could not grow, a VMInstance of 40 or 41 could not
take an instance type, profile or external change, and a Bucket of 44 or
more or a Qdrant of 42 or more failed its post-delete hook. Those Job
names, and the pod label vm-instance copies from one, are now cut to 63
characters. A release name is never longer than 53, so only the fixed
suffix is cut and two releases still get two Jobs.

A CronJob name is refused over 52 characters, because the controller
names each Job it starts <cronjob>-<timestamp>. With the backup CronJob
on, a MariaDB whose name has 38 characters or more and a ClickHouse of
35 or more failed the whole release. A cut there reaches into the
release name and could give two releases one CronJob, so a name that
does not fit becomes the release name cut to 38 characters, a hash of
the full release name and -backup, the way the ClickHouse Keeper name
is already shortened.

The tenant cleanup Job is named after the tenant namespace, which a
nested tenant can fill to 63 characters by itself. The Job runs in
cozy-system next to that of every other tenant, where a plain cut could
give a parent and its child one name and let the child's
before-hook-creation delete the parent's Job while it runs, so it is
shortened with a hash of the namespace the same way.

Names that fit render exactly as before, and a name that did not fit
never produced an object, so nothing is renamed on upgrade. The hook
ServiceAccounts, Roles and RoleBindings have no such limit and keep
their names.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <[email protected]>
@github-actions github-actions Bot added size/XL This PR changes 500-999 lines, ignoring generated files area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review kind/bug Categorizes issue or PR as related to a bug labels Oct 18, 2026
@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration

Commits

Reviewing files that changed from the base of the PR and between a2c9c07 and b5543d8.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review

No actionable comments were generated in the recent review.

Walkthrough

Several Helm templates now limit generated Job names or shorten over-budget CronJob names. The changes add tests for name boundaries, shortened names, hash suffixes, matching labels, and related ServiceAccount and RBAC names.

Changes: Resource name limits

Layer / File(s) Summary
63-character hook Job names
packages/apps/bucket/..., packages/apps/kafka/..., packages/apps/qdrant/..., packages/apps/vm-disk/..., packages/apps/vm-instance/...
Hook and cleanup Job names are limited to 63 characters and have a trailing hyphen removed. The VM update hook uses the computed name for the Job and its pod app label. Tests cover short, boundary, and longer names, plus related resource names that retain their full names.
Hashed backup CronJob names
packages/apps/clickhouse/..., packages/apps/mariadb/...
Backup CronJob names retain the <release>-backup form within the 52-character limit. Longer names use a trimmed release prefix, a six-character hash of the full release name, and the -backup suffix. Tests cover boundaries, hash differences, and dash trimming.
Tenant cleanup Job name
packages/apps/tenant/templates/cleanup-job.yaml, packages/apps/tenant/tests/job_name_budget_test.yaml
The cleanup Job uses its computed name for both the Job and pod template. Names over 63 characters use a trimmed tenant prefix, a six-character hash, and the cleanup suffix. Tests also check parent-child names and full namespace and release names in RBAC resources.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Merge Risk: Minimal · previous review a2c9c

This change shortens over-long Job and CronJob names so they can be created, and names that already fit are unchanged. No merge-blocking risk was found.

Pre-merge checks: Passed 5

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: keeping Job and CronJob names within Kubernetes length limits across application charts.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (16 skipped: 16 unsupported.)

Finishing Touches

🧪 Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

ℹ️ Recent review info

⚙️ Run configuration

  • Configuration used: Repository: cozystack/cozystack/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4c125c4c-232c-4192-b2d8-f8edcdf1a498
📥 Commits

Reviewing files that changed from the base of the PR and between aed7fa8 and a2c9c07.

📒 Files selected for processing: 16

  • packages/apps/bucket/templates/hooks/cleanup-acme.yaml
  • packages/apps/bucket/tests/job_name_budget_test.yaml
  • packages/apps/clickhouse/templates/backup-cronjob.yaml
  • packages/apps/clickhouse/tests/cronjob_name_budget_test.yaml
  • packages/apps/kafka/templates/migration-hook.yaml
  • packages/apps/kafka/tests/job_name_budget_test.yaml
  • packages/apps/mariadb/templates/backup-cronjob.yaml
  • packages/apps/mariadb/tests/cronjob_name_budget_test.yaml
  • packages/apps/qdrant/templates/hooks/cleanup-pvc.yaml
  • packages/apps/qdrant/tests/job_name_budget_test.yaml
  • packages/apps/tenant/templates/cleanup-job.yaml
  • packages/apps/tenant/tests/job_name_budget_test.yaml
  • packages/apps/vm-disk/templates/pvc-resize-hook.yaml
  • packages/apps/vm-disk/tests/job_name_budget_test.yaml
  • packages/apps/vm-instance/templates/vm-update-hook.yaml
  • packages/apps/vm-instance/tests/job_name_budget_test.yaml

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Traced the 53-char release-name cap to its enforcement (pkg/registry/apps/application/rest.go:1525), so Pattern A (trunc 63) never cuts into the release name and cannot collide; Pattern B (trunc + sha256[:6]) is used exactly where a naive cut would collide (CronJobs, and the tenant parent/child pair that share cozy-system), and the renders produce distinct names. RBAC objects keep full names, so the bindings are unaffected. Built helm-unittest 1.1.2 and ran all 8 charts (718 tests, 0 failures). No blocking issues.

Non-blocking:

  • Three mechanical checks flagged unbounded cleanup Jobs (qdrant, tenant) and a hook-succeeded delete policy (bucket), but all are on pre-existing lines this PR does not touch. Possible separate follow-up, out of scope here.
  • clickhouse/templates/backup-cronjob.yaml:20: $image := .Files.Get "images/backup.json" looks like dead code (the real image comes from the .tag file). Pre-existing.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <[email protected]>
@lexfrei

Copy link
Copy Markdown
Contributor

europrinter (@yankawai) I merged main into your branch (b5543d8) so CI runs against the current base. Your commits are unchanged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

europrinter (@yankawai) LGTM, CI and E2E are green on this head.

@lexfrei
Aleksei Sviridkin (lexfrei) merged commit ea4968c into cozystack:main Nov 13, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/uncategorized PR auto-labeler could not map title scope to a known area/*; please review kind/bug Categorizes issue or PR as related to a bug size/XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants