Declarative validation for ActorTemplate - #1303
Declarative validation for ActorTemplate#1303Julian Gutierrez Oschmann (juli4n) merged 20 commits into
Conversation
| Selector worker_selector = 2; | ||
|
|
||
| // +k8s:required # at least one container | ||
| // +k8s:listType=atomic |
There was a problem hiding this comment.
We should probably set a max number of containers (+k8s:maxItems).
We should also give this repeated field map semantics, and designate the container name field as key. Something like +k8s:listType=map and +k8s:listMapKey=name
| repeated string args = 4; | ||
|
|
||
| // +k8s:optional | ||
| // +k8s:listType=atomic |
There was a problem hiding this comment.
Set a limit? Also question: do we want env to have map semantics and keyed on EnvVar.name?
| // name may be any printable ASCII character except '='. | ||
| // | ||
| // +k8s:required | ||
| // TODO: validate the printable-ASCII-except-'=' rule |
There was a problem hiding this comment.
Any reason to not add this in this PR?
There was a problem hiding this comment.
There is another TODO validation that needs to be in the .go files - https://github.com/agent-substrate/substrate/pull/1303/changes#diff-54487cd2c9a8b26ec0ca05b934fd914a6c261a8c068b2b9f00e7f95e2b970c6cR66
Since the PR was already big, thought of doing a follow up.
But I guess for this, I can add in this PR itself. Will add it. Thanks.
| // | ||
| // +k8s:optional | ||
| // +k8s:maxItems=2 | ||
| // +k8s:listType=atomic |
There was a problem hiding this comment.
Use listType=map, then I dont think you need k8s:unique.
| // the default capability set. | ||
| // | ||
| // +k8s:optional | ||
| SecurityContext security_context = 8; |
There was a problem hiding this comment.
Can we also copy over the validation for SecurityContext field here
There was a problem hiding this comment.
done. thanks!
There was a problem hiding this comment.
I don't think the DV framework will understand those annotations.
There was a problem hiding this comment.
added a custom validation method to check this - https://github.com/agent-substrate/substrate/pull/1303/changes#diff-54487cd2c9a8b26ec0ca05b934fd914a6c261a8c068b2b9f00e7f95e2b970c6cR319-R324
| // +k8s:maxItems=32 | ||
| // +k8s:listType=map # a volume may be mounted at several paths, so the | ||
| // path, not the name, is the key | ||
| // +k8s:listMapKey=mount_path |
There was a problem hiding this comment.
Shouldn't this be name? That's what defines the ID of the volume, right? We can add a validation that mount paths don't clash, but the key of the map seems to be the name.
There was a problem hiding this comment.
k8s VolumeMounts are keyed by mountPath - https://github.com/kubernetes/api/blob/master/core/v1/types.go#L3239-L3243
However, for simplicity, we keying by volume name. But, this incorrectly validates the case when volume names are the different but the mount_path are the same. Added a TODO for the same - 43fc468#diff-f29aa971d0e861ade55215208c2d5e2eaa7d9f743969517826128207b1e4095eR842-R845
Michelle Au (@msau42) could you please confirm this behavior?
There was a problem hiding this comment.
Yeah for now lets keep it simple with one mount per volume. I vaguely recall that in Kubernetes there were some drivers/scenarios where having multiple mount paths on the same volume didn't work.
43fc468 to
688dbf3
Compare
688dbf3 to
5863cea
Compare
|
This PR is getting large and it adds a significant set of validations. I would say let's merge and iterate. If we find (we will :) ) missing validations, we can add them in follow up PRs. |
159de80
into
agent-substrate:main
Tim Hockin (thockin)
left a comment
There was a problem hiding this comment.
I have a few comments I will send as a followup PR. Some questions about API direction for Julian Gutierrez Oschmann (@juli4n) :)
| } | ||
|
|
||
| // ValidateCustom_ActorTemplate_SnapshotsConfig mirrors the ActorTemplate | ||
| // CRD's CEL rule: on_commit must be a subset of on_pause. UNSPECIFIED means |
There was a problem hiding this comment.
Why are we allowing UNSPECIFIED to mean full - why not demand a value?
| // +k8s:listType=map | ||
| // +k8s:listMapKey=name | ||
| // +k8s:customValidation # names, quantity parse/positivity, cpu bound | ||
| repeated Limits limits = 1; |
There was a problem hiding this comment.
This is more about API design than validation, but:
K8s did this because we allow 3rd party resources. It seems possible that we will ALSO allow those (e.g. GPU) -- is "map of string to quantity" what we want?
Alternative #1: map[string]string where keys are validated and values are quantities.
Alternative #2: message Limits { cpu string=1; memory string=2}
|
|
||
| message SnapshotsConfig { | ||
| // on_pause selects what is captured during pause actor. | ||
| // on_pause selects what is captured during pause actor. UNSPECIFIED is |
There was a problem hiding this comment.
Why do we need to allow UNSPECIFIED? We don't really have a compat problem yet.
| // +k8s:optional | ||
| // +k8s:maxItems=32 | ||
| // +k8s:listType=map # each variable is set at most once | ||
| // +k8s:listMapKey=name |
There was a problem hiding this comment.
Julian Gutierrez Oschmann (@juli4n) should we use actual maps for things that are fundamentally map-like ?
| HTTPGetAction http_get = 1; | ||
|
|
||
| // timeout_seconds bounds how long to poll http_get before failing the | ||
| // actor start. 0 means the server-applied default (30s). |
There was a problem hiding this comment.
Julian Gutierrez Oschmann (@juli4n) I asked elsewhere in a different PR - do you think we should keep this semantic or should we reify default values when they are stored? If we do not, then we can never really change a default.
| // type discriminates the source union: "DurableDir", | ||
| // "ExternalVolumeTemplate", "Image" or "SystemInfo". | ||
| // | ||
| // +k8s:optional |
There was a problem hiding this comment.
Julian Gutierrez Oschmann (@juli4n) We discussed this one - I thought we agreed to not use discriminators - did I misremember? Optional discrims are weird
Continues the declarative-validation (DV) migration from #1215, covering the
ActorTemplateresource, its full spec tree, the create path, and read/delete verbs.Key Changes
ActorTemplatespec (Metadata,SandboxConfig,SnapshotsConfig,Container,Volume,Resources).CreateActorTemplate. Custom rules (e.g.,on_commit ⊆ on_pause) are now handled via custom hooks.Get,List, andDeleterequests to use DV.atepgmetadata setters to update in-place.Deliberate Behavior Changes
The gRPC path now strictly enforces CRD rules. Specific tightenings include:
worker_selectoris now rejected.EnvVar.nameis strictly required.minimum=1).page_tokenis capped at 256 characters (matching other list requests).Deliberately Not Done
ActorTemplatesare immutable to clients. The reconciler updates the status directly against the store, so tagging the status subtree or adding update validation isn't necessary right now.config_namematchingsandbox_class: Enforcing this requires calling SandboxConfigLister (ServiceImpl), so it's left as a TODO.Testing
TestCreateActorTemplate*,TestUpdateActorTemplateMetadata, and theatepgsuite) verified against real Postgres via testcontainers.