Commit a3871bf
feat: Deployment workload profile, multi-replica preconditions, scale subresource (#81)
* feat(api): spec.workload field selecting the server workload kind
Adds spec.workload (StatefulSet | Deployment | auto, default StatefulSet)
to InstanceSpec. Deployment is intended for stateless multi-replica
instances (external/managed database + object storage, persistence
disabled); auto picks Deployment when persistence is disabled and the
database mode is not embedded. Includes regenerated CRD and synced Helm
chart CRD template.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(resources): extract shared server pod template
Mechanically moves the pod template construction out of BuildStatefulSet
into BuildServerPodTemplate (internal/resources/podtemplate.go) so a
Deployment workload builder can share it. Renames StatefulSetReplicas to
WorkloadReplicas since it will serve both workload kinds (no other
callers, so no deprecated alias).
The built StatefulSet is byte-identical: golden JSON dumps of eight
instance variants (persistence on/off, multi-replica heartbeat,
tailscale, platform-admin, k8s execution, object storage, suspended)
match exactly before and after the extraction, and all existing builder
tests pass unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(resources): Deployment workload builder
Adds BuildDeployment, sharing BuildServerPodTemplate, the workload name
(DeploymentName == StatefulSetName), labels, selector, and replica
handling (WorkloadReplicas, incl. suspend scale-to-zero) with the
StatefulSet builder so the Service keeps selecting the server pods by
label across workload kinds. Rollouts surge (maxSurge=1,
maxUnavailable=0) so capacity never drops during updates.
Also adds UseDeploymentWorkload resolving spec.workload, including the
auto rule (no persistence AND non-embedded database). Covered by builder
tests plus a truth-table test for the workload resolution.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(controller): workload-kind reconcile with safe kind migration
Reconcile the server workload as a Deployment when
spec.workload selects it (explicitly or via auto) and delete the stale
counterpart kind afterwards (Normal event WorkloadKindMigrated), so a
spec.workload flip migrates cleanly. reconcileDeployment mirrors
reconcileStatefulSet including HPA replica preservation and suspend
scale-to-zero, and maintains a DeploymentReady condition (the
counterpart kind's readiness condition is removed to avoid stale gating).
PVC-safety override: spec.workload=Deployment with persistence enabled
keeps the StatefulSet and reports the advisory WorkloadProfileValid=False
(reason PersistenceRequiresStatefulSet, Warning event) instead of
attaching the RWO data PVC to surging Deployment pods. The HPA
scaleTargetRef follows the effective workload kind via the new
resources.EffectiveWorkloadIsDeployment helper.
Fix a round-trip bug that blocked stateless profiles entirely:
PersistenceSpec.Enabled was a plain bool with omitempty, so
enabled=false was dropped on marshal and re-defaulted to true by the
API server on every controller update of the CR (e.g. adding the
finalizer). It is now *bool (generated CRD schema is unchanged) read
through resources.PersistenceEnabled.
Adds apps/deployments RBAC (marker, role.yaml, Helm chart) and the
Deployment to the controller's Owns watches.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(controller): multi-replica precondition and PDB warnings
Before the workload step, maintain the advisory
MultiReplicaPreconditions condition whenever effective replicas > 1:
False (Warning event, once per transition) when the embedded database
is selected (it cannot be shared between replicas) or objectStorage is
unset (required for shared file state), True when both prerequisites
are met. At replicas <= 1 the condition is removed entirely so
single-replica instances carry no stale noise. Advisory conditions are
excluded from the Ready aggregation.
Also emit a Warning event PDBMayBlockDrains (event only, no condition)
when podDisruptionBudget.minAvailable >= autoScaling.minReplicas, since
disruptionsAllowed is then 0 at minimum scale and node drains can
stall.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(api): scale subresource and managedResources.deployment tracking
Adds the scale subresource to the Instance CRD
(specpath=.spec.availability.replicas, statuspath=.status.replicas,
selectorpath=.status.selector) so kubectl scale and KEDA/HPA-style
tooling can drive replicas through /scale. updateStatus populates
status.replicas and status.selector from the active server workload
(Deployment or StatefulSet; names and selectors are identical by
construction, so the selector string is stable across kind migrations).
kubectl scale writes spec.availability.replicas, which the reconcilers
already ignore while autoScaling is enabled (HPA replica preservation),
so scaling via /scale is a documented no-op under HPA and there is no
controller/autoscaler fight.
Also adds status.managedResources.deployment, set in reconcileDeployment
and cleared in the StatefulSet path (and vice versa), closing the Task 2
leftover where a kind migration left no record of the active workload.
Covered by an envtest case that GETs /scale, scales 1 -> 3 through the
subresource, and asserts the Deployment spec, status.replicas, and
status.selector follow.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: workload profiles, scale subresource, and PDB guidance in scaling section
Rewrites the README Scaling section: workload profile table
(StatefulSet default vs Deployment for stateless multi-replica, auto),
multi-replica preconditions and the MultiReplicaPreconditions condition,
the PVC-safety rule behind WorkloadProfileValid, kubectl scale / KEDA
scaleTargetRef usage of the new scale subresource (and that it is a
no-op under HPA), and PDB drain guidance (minAvailable strictly below
autoScaling.minReplicas, unhealthyPodEvictionPolicy: AlwaysAllow
example).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: regenerate API reference for workload, scale, and condition fields
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent c3e4468 commit a3871bf
19 files changed
Lines changed: 1233 additions & 160 deletions
File tree
- api/v1alpha1
- charts/paperclip-operator/templates
- crds
- config
- crd/bases
- rbac
- docs
- internal
- controller
- resources
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
595 | 595 | | |
596 | 596 | | |
597 | 597 | | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
598 | 615 | | |
599 | 616 | | |
600 | 617 | | |
| |||
603 | 620 | | |
604 | 621 | | |
605 | 622 | | |
606 | | - | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
607 | 639 | | |
608 | 640 | | |
609 | 641 | | |
| |||
618 | 650 | | |
619 | 651 | | |
620 | 652 | | |
621 | | - | |
| 653 | + | |
622 | 654 | | |
623 | 655 | | |
624 | 656 | | |
| |||
631 | 663 | | |
632 | 664 | | |
633 | 665 | | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
634 | 683 | | |
635 | 684 | | |
636 | 685 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
124 | 124 | | |
125 | 125 | | |
126 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
127 | 141 | | |
128 | 142 | | |
129 | 143 | | |
| |||
445 | 459 | | |
446 | 460 | | |
447 | 461 | | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
448 | 466 | | |
449 | 467 | | |
450 | 468 | | |
451 | | - | |
| 469 | + | |
452 | 470 | | |
453 | 471 | | |
454 | 472 | | |
| |||
1065 | 1083 | | |
1066 | 1084 | | |
1067 | 1085 | | |
1068 | | - | |
1069 | | - | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
1070 | 1090 | | |
1071 | 1091 | | |
1072 | 1092 | | |
| |||
1298 | 1318 | | |
1299 | 1319 | | |
1300 | 1320 | | |
| 1321 | + | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
1301 | 1329 | | |
1302 | 1330 | | |
1303 | 1331 | | |
1304 | 1332 | | |
1305 | 1333 | | |
1306 | 1334 | | |
1307 | 1335 | | |
| 1336 | + | |
| 1337 | + | |
1308 | 1338 | | |
1309 | 1339 | | |
1310 | 1340 | | |
| |||
1375 | 1405 | | |
1376 | 1406 | | |
1377 | 1407 | | |
| 1408 | + | |
1378 | 1409 | | |
1379 | 1410 | | |
1380 | 1411 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 36 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1589 | 1589 | | |
1590 | 1590 | | |
1591 | 1591 | | |
1592 | | - | |
1593 | | - | |
| 1592 | + | |
| 1593 | + | |
| 1594 | + | |
| 1595 | + | |
1594 | 1596 | | |
1595 | 1597 | | |
1596 | 1598 | | |
| |||
8269 | 8271 | | |
8270 | 8272 | | |
8271 | 8273 | | |
| 8274 | + | |
| 8275 | + | |
| 8276 | + | |
| 8277 | + | |
| 8278 | + | |
| 8279 | + | |
| 8280 | + | |
| 8281 | + | |
| 8282 | + | |
| 8283 | + | |
| 8284 | + | |
| 8285 | + | |
| 8286 | + | |
| 8287 | + | |
| 8288 | + | |
| 8289 | + | |
| 8290 | + | |
8272 | 8291 | | |
8273 | 8292 | | |
8274 | 8293 | | |
| |||
8381 | 8400 | | |
8382 | 8401 | | |
8383 | 8402 | | |
| 8403 | + | |
| 8404 | + | |
8384 | 8405 | | |
8385 | 8406 | | |
8386 | 8407 | | |
| |||
8421 | 8442 | | |
8422 | 8443 | | |
8423 | 8444 | | |
| 8445 | + | |
| 8446 | + | |
| 8447 | + | |
| 8448 | + | |
| 8449 | + | |
8424 | 8450 | | |
8425 | 8451 | | |
8426 | 8452 | | |
| |||
8432 | 8458 | | |
8433 | 8459 | | |
8434 | 8460 | | |
| 8461 | + | |
| 8462 | + | |
| 8463 | + | |
| 8464 | + | |
8435 | 8465 | | |
8436 | 8466 | | |
8437 | 8467 | | |
8438 | 8468 | | |
8439 | 8469 | | |
| 8470 | + | |
| 8471 | + | |
| 8472 | + | |
| 8473 | + | |
8440 | 8474 | | |
8441 | 8475 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | | - | |
| 73 | + | |
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1583 | 1583 | | |
1584 | 1584 | | |
1585 | 1585 | | |
1586 | | - | |
1587 | | - | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
1588 | 1590 | | |
1589 | 1591 | | |
1590 | 1592 | | |
| |||
8263 | 8265 | | |
8264 | 8266 | | |
8265 | 8267 | | |
| 8268 | + | |
| 8269 | + | |
| 8270 | + | |
| 8271 | + | |
| 8272 | + | |
| 8273 | + | |
| 8274 | + | |
| 8275 | + | |
| 8276 | + | |
| 8277 | + | |
| 8278 | + | |
| 8279 | + | |
| 8280 | + | |
| 8281 | + | |
| 8282 | + | |
| 8283 | + | |
| 8284 | + | |
8266 | 8285 | | |
8267 | 8286 | | |
8268 | 8287 | | |
| |||
8375 | 8394 | | |
8376 | 8395 | | |
8377 | 8396 | | |
| 8397 | + | |
| 8398 | + | |
8378 | 8399 | | |
8379 | 8400 | | |
8380 | 8401 | | |
| |||
8415 | 8436 | | |
8416 | 8437 | | |
8417 | 8438 | | |
| 8439 | + | |
| 8440 | + | |
| 8441 | + | |
| 8442 | + | |
| 8443 | + | |
8418 | 8444 | | |
8419 | 8445 | | |
8420 | 8446 | | |
| |||
8426 | 8452 | | |
8427 | 8453 | | |
8428 | 8454 | | |
| 8455 | + | |
| 8456 | + | |
| 8457 | + | |
| 8458 | + | |
8429 | 8459 | | |
8430 | 8460 | | |
8431 | 8461 | | |
8432 | 8462 | | |
8433 | 8463 | | |
| 8464 | + | |
| 8465 | + | |
| 8466 | + | |
| 8467 | + | |
8434 | 8468 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
| 86 | + | |
86 | 87 | | |
87 | 88 | | |
88 | 89 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
208 | 208 | | |
209 | 209 | | |
210 | 210 | | |
211 | | - | |
| 211 | + | |
212 | 212 | | |
213 | 213 | | |
214 | 214 | | |
| |||
601 | 601 | | |
602 | 602 | | |
603 | 603 | | |
| 604 | + | |
604 | 605 | | |
605 | 606 | | |
606 | 607 | | |
| |||
0 commit comments