From 2a468d18e12f4696e1a0d98eea350ffb34dbea75 Mon Sep 17 00:00:00 2001 From: Elijah Rodriguez Date: Tue, 8 Sep 2026 18:31:08 -0700 Subject: [PATCH] csi: add publishContext to actor volumes Some CSI drivers require attachment metadata (e.g. device path) for publishing a volume. This PR adds a publishContext to actor volumes and persists it during a volume's lifecycle. --- benchmarking/locust/common/ateapi_pb2.py | 432 ++++++++--------- .../controlapi/functionaltest/actor_test.go | 24 +- cmd/ateapi/internal/controlapi/volumes.go | 11 +- .../internal/controlapi/workflow_delete.go | 2 +- .../internal/controlapi/workflow_pause.go | 2 +- .../internal/controlapi/workflow_resume.go | 53 ++- .../controlapi/workflow_resume_test.go | 87 +++- .../internal/controlapi/workflow_suspend.go | 2 +- .../internal/controlapi/workload_spec.go | 11 +- .../internal/controlapi/workload_spec_test.go | 75 +-- .../controlapi/zz_generated.validation.go | 75 +++ cmd/atelet/volumes.go | 7 +- cmd/atelet/volumes_test.go | 2 +- internal/proto/ateletpb/atelet.pb.go | 130 ++--- internal/proto/ateletpb/atelet.proto | 4 + internal/volume/csi/plugin.go | 74 ++- internal/volume/csi/plugin_test.go | 43 +- internal/volume/mock.go | 33 +- internal/volume/plugin.go | 55 ++- pkg/proto/ateapipb/ateapi.pb.go | 450 ++++++++++-------- pkg/proto/ateapipb/ateapi.proto | 21 + 21 files changed, 989 insertions(+), 604 deletions(-) diff --git a/benchmarking/locust/common/ateapi_pb2.py b/benchmarking/locust/common/ateapi_pb2.py index 65dcf3909a..66913173bc 100644 --- a/benchmarking/locust/common/ateapi_pb2.py +++ b/benchmarking/locust/common/ateapi_pb2.py @@ -40,7 +40,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x61teapi.proto\x12\x06\x61teapi\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"]\n\x10\x45xternalSnapshot\x12\x14\n\x0csnapshot_uri\x18\x01 \x01(\t\x12\x33\n\rcontent_scope\x18\x02 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\"\x86\x01\n\x11LocalSnapshotInfo\x12\x15\n\rsnapshot_name\x18\x01 \x01(\t\x12%\n\x1dnode_vms_with_local_snapshots\x18\x02 \x03(\t\x12\x33\n\rcontent_scope\x18\x03 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\"w\n\x08Selector\x12\x37\n\x0cmatch_labels\x18\x01 \x03(\x0b\x32!.ateapi.Selector.MatchLabelsEntry\x1a\x32\n\x10MatchLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xb2\x01\n\x10ResourceMetadata\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0b\n\x03uid\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xdc\x02\n\x0e\x45xternalVolume\x12\x13\n\x0bvolume_name\x18\x01 \x01(\t\x12\x19\n\x11storage_volume_id\x18\x02 \x01(\t\x12\x13\n\x0bvolume_type\x18\x03 \x01(\t\x12-\n\x06status\x18\x04 \x01(\x0e\x32\x1d.ateapi.ExternalVolume.Status\x12\x41\n\x0evolume_context\x18\x05 \x03(\x0b\x32).ateapi.ExternalVolume.VolumeContextEntry\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"]\n\x06Status\x12\x16\n\x12STATUS_UNSPECIFIED\x10\x00\x12\x12\n\x0eSTATUS_PENDING\x10\x01\x12\x12\n\x0eSTATUS_CREATED\x10\x02\x12\x13\n\x0fSTATUS_DELETING\x10\x03\"\xd5\x01\n\x05\x41\x63tor\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12)\n\x0e\x61\x63tor_template\x18\x04 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12)\n\x0fworker_selector\x18\x05 \x01(\x0b\x32\x10.ateapi.Selector\x12%\n\nsource_tag\x18\x06 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12#\n\x06status\x18\x07 \x01(\x0b\x32\x13.ateapi.ActorStatus\"]\n\x0c\x45gressPolicy\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12!\n\x05rules\x18\x02 \x03(\x0b\x32\x12.ateapi.EgressRule\"{\n\nEgressRule\x12\'\n\thostnames\x18\x01 \x01(\x0b\x32\x14.ateapi.HostnameRule\x12\x1f\n\x05\x63idrs\x18\x02 \x01(\x0b\x32\x10.ateapi.CIDRRule\x12#\n\x03\x61ll\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Empty\"L\n\x0cHostnameRule\x12\x10\n\x08patterns\x18\x01 \x03(\t\x12*\n\x07\x65\x66\x66\x65\x63ts\x18\x02 \x01(\x0b\x32\x19.ateapi.EgressRuleEffects\"\x19\n\x08\x43IDRRule\x12\r\n\x05\x63idrs\x18\x01 \x03(\t\"U\n\x11\x45gressRuleEffects\x12@\n\x15inject_static_headers\x18\x01 \x03(\x0b\x32!.ateapi.CredentialHeaderInjection\"S\n\x19\x43redentialHeaderInjection\x12\x0e\n\x06header\x18\x01 \x01(\t\x12\x0e\n\x06prefix\x18\x02 \x01(\t\x12\x16\n\x0e\x63redential_uri\x18\x03 \x01(\t\"\xf0\x02\n\x0b\x41\x63torStatus\x12!\n\x05state\x18\x01 \x01(\x0e\x32\x12.ateapi.ActorState\x12\x33\n\x11worker_assignment\x18\x02 \x01(\x0b\x32\x18.ateapi.WorkerAssignment\x12 \n\x18in_progress_snapshot_uri\x18\x03 \x01(\t\x12\x33\n\x11\x65xternal_snapshot\x18\x04 \x01(\x0b\x32\x18.ateapi.ExternalSnapshot\x12\x36\n\x13local_snapshot_info\x18\x05 \x01(\x0b\x32\x19.ateapi.LocalSnapshotInfo\x12-\n\ractor_volumes\x18\x07 \x03(\x0b\x32\x16.ateapi.ExternalVolume\x12\'\n\x1fin_progress_local_snapshot_name\x18\x08 \x01(\t\x12\"\n\x1a\x63urrent_actor_template_uid\x18\x0b \x01(\t\"\xba\x01\n\x10WorkerAssignment\x12!\n\x06worker\x18\x06 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x18\n\x10worker_namespace\x18\x01 \x01(\t\x12\x13\n\x0bworker_pool\x18\x02 \x01(\t\x12\x12\n\nworker_pod\x18\x03 \x01(\t\x12\x16\n\x0eworker_pod_uid\x18\x04 \x01(\t\x12\x15\n\rworker_pod_ip\x18\x05 \x01(\t\x12\x11\n\tnode_name\x18\x07 \x01(\t\"\x87\x01\n\tTagStatus\x12*\n\x08snapshot\x18\x01 \x01(\x0b\x32\x18.ateapi.ExternalSnapshot\x12\x1a\n\x12\x61\x63tor_template_uid\x18\x02 \x01(\t\x12\x18\n\x10storage_location\x18\x03 \x01(\t\x12\x18\n\x10source_actor_uid\x18\x04 \x01(\t\"\x9e\x01\n\x03Tag\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12!\n\x06status\x18\x02 \x01(\x0b\x32\x11.ateapi.TagStatus\x12\x1f\n\x05scope\x18\x03 \x01(\x0e\x32\x10.ateapi.TagScope\x12\'\n\x0csource_actor\x18\x04 \x01(\x0b\x32\x11.ateapi.ObjectRef\"6\n\x08\x41tespace\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\"+\n\tObjectRef\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"\xe3\x02\n\rActorTemplate\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12)\n\x0fworker_selector\x18\x02 \x01(\x0b\x32\x10.ateapi.Selector\x12%\n\ncontainers\x18\x03 \x03(\x0b\x32\x11.ateapi.Container\x12\x1f\n\x07volumes\x18\x04 \x03(\x0b\x32\x0e.ateapi.Volume\x12\x31\n\x10snapshots_config\x18\x05 \x01(\x0b\x32\x17.ateapi.SnapshotsConfig\x12-\n\x0esandbox_config\x18\x06 \x01(\x0b\x32\x15.ateapi.SandboxConfig\x12$\n\tresources\x18\x07 \x01(\x0b\x32\x11.ateapi.Resources\x12+\n\x06status\x18\x08 \x01(\x0b\x32\x1b.ateapi.ActorTemplateStatus\"+\n\tResources\x12\x1e\n\x06limits\x18\x01 \x03(\x0b\x32\x0e.ateapi.Limits\"(\n\x06Limits\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08quantity\x18\x02 \x01(\t\"\x91\x01\n\x14GoldenSnapshotStatus\x12%\n\ngolden_tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12;\n\x17take_golden_snapshot_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rerror_message\x18\x03 \x01(\t\"S\n\x13\x41\x63torTemplateStatus\x12<\n\x16golden_snapshot_status\x18\x01 \x01(\x0b\x32\x1c.ateapi.GoldenSnapshotStatus\"Q\n\rSandboxConfig\x12+\n\rsandbox_class\x18\x01 \x01(\x0e\x32\x14.ateapi.SandboxClass\x12\x13\n\x0b\x63onfig_name\x18\x02 \x01(\t\"\xb7\x01\n\x0fSnapshotsConfig\x12.\n\x08on_pause\x18\x01 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\x12/\n\ton_commit\x18\x02 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\x12)\n\ton_resume\x18\x03 \x01(\x0b\x32\x16.ateapi.OnResumeConfig\x12\x18\n\x10storage_location\x18\x04 \x01(\t\"9\n\x0eOnResumeConfig\x12\'\n\tfrom_data\x18\x01 \x01(\x0e\x32\x14.ateapi.ResumeSource\"\x9d\x02\n\tContainer\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05image\x18\x02 \x01(\t\x12\x0f\n\x07\x63ommand\x18\x03 \x03(\t\x12\x0c\n\x04\x61rgs\x18\x04 \x03(\t\x12\x1b\n\x03\x65nv\x18\x05 \x03(\x0b\x32\x0e.ateapi.EnvVar\x12\x32\n\x0cwakeup_probe\x18\x06 \x01(\x0b\x32\x1c.ateapi.ContainerWakeupProbe\x12*\n\rvolume_mounts\x18\x07 \x03(\x0b\x32\x13.ateapi.VolumeMount\x12\x31\n\x10security_context\x18\x08 \x01(\x0b\x32\x17.ateapi.SecurityContext\x12$\n\tresources\x18\t \x01(\x0b\x32\x11.ateapi.Resources\"=\n\x0fSecurityContext\x12*\n\x0c\x63\x61pabilities\x18\x01 \x01(\x0b\x32\x14.ateapi.Capabilities\")\n\x0c\x43\x61pabilities\x12\x0b\n\x03\x61\x64\x64\x18\x01 \x03(\t\x12\x0c\n\x04\x64rop\x18\x02 \x03(\t\"*\n\x06\x45nvVar\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\x05value\x18\x02 \x01(\tB\x03\x80\x01\x01\"X\n\x14\x43ontainerWakeupProbe\x12\'\n\x08http_get\x18\x01 \x01(\x0b\x32\x15.ateapi.HTTPGetAction\x12\x17\n\x0ftimeout_seconds\x18\x02 \x01(\x05\"+\n\rHTTPGetAction\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\x05\"\xec\x01\n\x06Volume\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x33\n\x0b\x64urable_dir\x18\x02 \x01(\x0b\x32\x1e.ateapi.DurableDirVolumeSource\x12@\n\x18\x65xternal_volume_template\x18\x03 \x01(\x0b\x32\x1e.ateapi.ExternalVolumeTemplate\x12\x33\n\x0bsystem_info\x18\x05 \x01(\x0b\x32\x1e.ateapi.SystemInfoVolumeSource\x12(\n\x05image\x18\x06 \x01(\x0b\x32\x19.ateapi.ImageVolumeSource\"&\n\x11ImageVolumeSource\x12\x11\n\treference\x18\x01 \x01(\t\"\x18\n\x16\x44urableDirVolumeSource\"F\n\x16\x45xternalVolumeTemplate\x12\x10\n\x08\x63\x61pacity\x18\x01 \x01(\t\x12\x1a\n\x12storage_class_name\x18\x02 \x01(\t\"L\n\x16SystemInfoVolumeSource\x12\x32\n\x0c\x64\x61ta_sources\x18\x01 \x03(\x0b\x32\x1c.ateapi.SystemInfoDataSource\"\x84\x01\n\x14SystemInfoDataSource\x12\x37\n\x0e\x61\x63tor_metadata\x18\x01 \x01(\x0b\x32\x1f.ateapi.ActorMetadataDataSource\x12\x33\n\x0ctrust_bundle\x18\x02 \x01(\x0b\x32\x1d.ateapi.TrustBundleDataSource\"C\n\x17\x41\x63torMetadataDataSource\x12(\n\x05items\x18\x01 \x03(\x0b\x32\x19.ateapi.ActorMetadataItem\"L\n\x11\x41\x63torMetadataItem\x12)\n\x05\x66ield\x18\x01 \x01(\x0e\x32\x1a.ateapi.ActorMetadataField\x12\x0c\n\x04path\x18\x02 \x01(\t\"3\n\x15TrustBundleDataSource\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\"/\n\x0bVolumeMount\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nmount_path\x18\x02 \x01(\t\";\n\x15\x43reateAtespaceRequest\x12\"\n\x08\x61tespace\x18\x01 \x01(\x0b\x32\x10.ateapi.Atespace\"9\n\x12GetAtespaceRequest\x12#\n\x08\x61tespace\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"=\n\x14ListAtespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\"U\n\x15ListAtespacesResponse\x12#\n\tatespaces\x18\x01 \x03(\x0b\x32\x10.ateapi.Atespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"<\n\x15\x44\x65leteAtespaceRequest\x12#\n\x08\x61tespace\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"K\n\x1a\x43reateActorTemplateRequest\x12-\n\x0e\x61\x63tor_template\x18\x01 \x01(\x0b\x32\x15.ateapi.ActorTemplate\"D\n\x17GetActorTemplateRequest\x12)\n\x0e\x61\x63tor_template\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"T\n\x19ListActorTemplatesRequest\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"e\n\x1aListActorTemplatesResponse\x12.\n\x0f\x61\x63tor_templates\x18\x01 \x03(\x0b\x32\x15.ateapi.ActorTemplate\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"G\n\x1a\x44\x65leteActorTemplateRequest\x12)\n\x0e\x61\x63tor_template\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"3\n\x0fGetActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"2\n\x12\x43reateActorRequest\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"2\n\x12UpdateActorRequest\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"7\n\x13SuspendActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"4\n\x14SuspendActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"5\n\x11PauseActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"2\n\x12PauseActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"6\n\x12ResumeActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"D\n\x13ResumeActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\x12\x0f\n\x07resumed\x18\x02 \x01(\x08\"6\n\x12RevertActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"3\n\x13RevertActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"I\n\x12\x44\x65leteActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tany_state\x18\x02 \x01(\x08\"?\n\x1bGetActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"o\n\x1e\x43reateActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12+\n\regress_policy\x18\x02 \x01(\x0b\x32\x14.ateapi.EgressPolicy\"o\n\x1eUpdateActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12+\n\regress_policy\x18\x02 \x01(\x0b\x32\x14.ateapi.EgressPolicy\"B\n\x1e\x44\x65leteActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"/\n\rGetTagRequest\x12\x1e\n\x03tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"\\\n\x13MintActorJWTRequest\x12 \n\x05\x61\x63tor\x18\x05 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tactor_uid\x18\x07 \x01(\t\x12\x10\n\x08\x61udience\x18\x01 \x03(\t\".\n\x14MintActorJWTResponse\x12\x16\n\tactor_jwt\x18\x01 \x01(\tB\x03\x80\x01\x01\"\xa9\x01\n\x1bMintActorCertificateRequest\x12 \n\x05\x61\x63tor\x18\x06 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tactor_uid\x18\x07 \x01(\t\x12#\n\x1b\x63\x65rtificate_signing_request\x18\x02 \x01(\x0c\x12\x30\n\x07purpose\x18\x04 \x01(\x0e\x32\x1f.ateapi.ActorCertificatePurpose\":\n\x1cMintActorCertificateResponse\x12\x1a\n\x12\x61\x63tor_certificates\x18\x01 \x03(\x0c\"D\n\x17GetActorSnapshotRequest\x12)\n\x0e\x61\x63tor_snapshot\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"K\n\x1aGetActorSnapshotTagRequest\x12-\n\x12\x61\x63tor_snapshot_tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"J\n\x0fListTagsRequest\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"F\n\x10ListTagsResponse\x12\x19\n\x04tags\x18\x01 \x03(\x0b\x32\x0b.ateapi.Tag\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\",\n\x10\x43reateTagRequest\x12\x18\n\x03tag\x18\x01 \x01(\x0b\x32\x0b.ateapi.Tag\",\n\x10UpdateTagRequest\x12\x18\n\x03tag\x18\x01 \x01(\x0b\x32\x0b.ateapi.Tag\"2\n\x10\x44\x65leteTagRequest\x12\x1e\n\x03tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"-\n\rDeleteOptions\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\x0b\n\x03uid\x18\x02 \x01(\t\"m\n!ListWorkerActorAssignmentsRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"q\n\"ListWorkerActorAssignmentsResponse\x12\x32\n\x11\x61\x63tor_assignments\x18\x01 \x03(\x0b\x32\x17.ateapi.ActorAssignment\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\";\n\x12ListWorkersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\"O\n\x13ListWorkersResponse\x12\x1f\n\x07workers\x18\x01 \x03(\x0b\x32\x0e.ateapi.Worker\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"5\n\x10GetWorkerRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"5\n\x13\x43reateWorkerRequest\x12\x1e\n\x06worker\x18\x01 \x01(\x0b\x32\x0e.ateapi.Worker\"5\n\x13UpdateWorkerRequest\x12\x1e\n\x06worker\x18\x01 \x01(\x0b\x32\x0e.ateapi.Worker\"`\n\x13\x44\x65leteWorkerRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12&\n\x07options\x18\x02 \x01(\x0b\x32\x15.ateapi.DeleteOptions\"7\n\x12\x44rainWorkerRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"L\n\x11ListActorsRequest\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"L\n\x12ListActorsResponse\x12\x1d\n\x06\x61\x63tors\x18\x01 \x03(\x0b\x32\r.ateapi.Actor\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xc6\x02\n\x06Worker\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12\x18\n\x10worker_namespace\x18\x02 \x01(\t\x12\x13\n\x0bworker_pool\x18\x03 \x01(\t\x12\x12\n\nworker_pod\x18\x04 \x01(\t\x12\x16\n\x0eworker_pod_uid\x18\x05 \x01(\t\x12\x11\n\tnode_name\x18\x06 \x01(\t\x12\n\n\x02ip\x18\x07 \x01(\t\x12\x15\n\rsandbox_class\x18\x08 \x01(\t\x12*\n\x06labels\x18\t \x03(\x0b\x32\x1a.ateapi.Worker.LabelsEntry\x12$\n\x06status\x18\x0b \x01(\x0b\x32\x14.ateapi.WorkerStatus\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x89\x01\n\x0cWorkerStatus\x12\"\n\x05state\x18\x01 \x01(\x0e\x32\x13.ateapi.WorkerState\x12)\n\x08\x63\x61pacity\x18\x02 \x01(\x0b\x32\x17.ateapi.WorkerResources\x12*\n\tallocated\x18\x03 \x01(\x0b\x32\x17.ateapi.WorkerResources\"G\n\x0fWorkerResources\x12$\n\tresources\x18\x01 \x01(\x0b\x32\x11.ateapi.Resources\x12\x0e\n\x06\x61\x63tors\x18\x02 \x01(\x05\"\xc7\x01\n\x0f\x41\x63torAssignment\x12*\n\x08metadata\x18\x06 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12 \n\x05\x61\x63tor\x18\x02 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tactor_uid\x18\x03 \x01(\t\x12-\n\x12\x61\x63tor_template_ref\x18\x04 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12$\n\tresources\x18\x05 \x01(\x0b\x32\x11.ateapi.Resources\"h\n\x18SetWorkerCapacityRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12)\n\x08\x63\x61pacity\x18\x02 \x01(\x0b\x32\x17.ateapi.WorkerResources\";\n\x19SetWorkerCapacityResponse\x12\x1e\n\x06worker\x18\x01 \x01(\x0b\x32\x0e.ateapi.Worker*\x80\x01\n\x14SnapshotContentScope\x12&\n\"SNAPSHOT_CONTENT_SCOPE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bSNAPSHOT_CONTENT_SCOPE_FULL\x10\x01\x12\x1f\n\x1bSNAPSHOT_CONTENT_SCOPE_DATA\x10\x02*V\n\x08TagScope\x12\x19\n\x15TAG_SCOPE_UNSPECIFIED\x10\x00\x12\x16\n\x12TAG_SCOPE_ATESPACE\x10\x01\x12\x17\n\x13TAG_SCOPE_PUBLISHED\x10\x02*\x92\x02\n\nActorState\x12\x1b\n\x17\x41\x43TOR_STATE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41\x43TOR_STATE_RESUMING\x10\x01\x12\x17\n\x13\x41\x43TOR_STATE_RUNNING\x10\x02\x12\x1a\n\x16\x41\x43TOR_STATE_SUSPENDING\x10\x03\x12\x19\n\x15\x41\x43TOR_STATE_SUSPENDED\x10\x04\x12\x17\n\x13\x41\x43TOR_STATE_PAUSING\x10\x05\x12\x16\n\x12\x41\x43TOR_STATE_PAUSED\x10\x06\x12\x17\n\x13\x41\x43TOR_STATE_CRASHED\x10\x07\x12\x18\n\x14\x41\x43TOR_STATE_DELETING\x10\x08\x12\x19\n\x15\x41\x43TOR_STATE_REVERTING\x10\t*b\n\x0cSandboxClass\x12\x1d\n\x19SANDBOX_CLASS_UNSPECIFIED\x10\x00\x12\x18\n\x14SANDBOX_CLASS_GVISOR\x10\x01\x12\x19\n\x15SANDBOX_CLASS_MICROVM\x10\x02*d\n\x0cResumeSource\x12\x1d\n\x19RESUME_SOURCE_UNSPECIFIED\x10\x00\x12\x1b\n\x17RESUME_SOURCE_COLD_BOOT\x10\x01\x12\x18\n\x14RESUME_SOURCE_GOLDEN\x10\x02*\x9a\x01\n\x12\x41\x63torMetadataField\x12$\n ACTOR_METADATA_FIELD_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x41\x43TOR_METADATA_FIELD_NAME\x10\x01\x12!\n\x1d\x41\x43TOR_METADATA_FIELD_ATESPACE\x10\x02\x12\x1c\n\x18\x41\x43TOR_METADATA_FIELD_UID\x10\x03*k\n\x17\x41\x63torCertificatePurpose\x12)\n%ACTOR_CERTIFICATE_PURPOSE_UNSPECIFIED\x10\x00\x12%\n!ACTOR_CERTIFICATE_PURPOSE_ATUNNEL\x10\x01*_\n\x0bWorkerState\x12\x1c\n\x18WORKER_STATE_UNSPECIFIED\x10\x00\x12\x17\n\x13WORKER_STATE_ACTIVE\x10\x01\x12\x19\n\x15WORKER_STATE_DRAINING\x10\x02\x32\xef\x13\n\x07\x43ontrol\x12\x34\n\x08GetActor\x12\x17.ateapi.GetActorRequest\x1a\r.ateapi.Actor\"\x00\x12:\n\x0b\x43reateActor\x12\x1a.ateapi.CreateActorRequest\x1a\r.ateapi.Actor\"\x00\x12:\n\x0bUpdateActor\x12\x1a.ateapi.UpdateActorRequest\x1a\r.ateapi.Actor\"\x00\x12K\n\x0cSuspendActor\x12\x1b.ateapi.SuspendActorRequest\x1a\x1c.ateapi.SuspendActorResponse\"\x00\x12\x45\n\nPauseActor\x12\x19.ateapi.PauseActorRequest\x1a\x1a.ateapi.PauseActorResponse\"\x00\x12H\n\x0bResumeActor\x12\x1a.ateapi.ResumeActorRequest\x1a\x1b.ateapi.ResumeActorResponse\"\x00\x12H\n\x0bRevertActor\x12\x1a.ateapi.RevertActorRequest\x1a\x1b.ateapi.RevertActorResponse\"\x00\x12:\n\x0b\x44\x65leteActor\x12\x1a.ateapi.DeleteActorRequest\x1a\r.ateapi.Actor\"\x00\x12S\n\x14GetActorEgressPolicy\x12#.ateapi.GetActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12Y\n\x17\x43reateActorEgressPolicy\x12&.ateapi.CreateActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12Y\n\x17UpdateActorEgressPolicy\x12&.ateapi.UpdateActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12Y\n\x17\x44\x65leteActorEgressPolicy\x12&.ateapi.DeleteActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12K\n\x0cMintActorJWT\x12\x1b.ateapi.MintActorJWTRequest\x1a\x1c.ateapi.MintActorJWTResponse\"\x00\x12\x63\n\x14MintActorCertificate\x12#.ateapi.MintActorCertificateRequest\x1a$.ateapi.MintActorCertificateResponse\"\x00\x12\x34\n\tCreateTag\x12\x18.ateapi.CreateTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12.\n\x06GetTag\x12\x15.ateapi.GetTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12?\n\x08ListTags\x12\x17.ateapi.ListTagsRequest\x1a\x18.ateapi.ListTagsResponse\"\x00\x12\x34\n\tUpdateTag\x12\x18.ateapi.UpdateTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12\x34\n\tDeleteTag\x12\x18.ateapi.DeleteTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12H\n\x0bListWorkers\x12\x1a.ateapi.ListWorkersRequest\x1a\x1b.ateapi.ListWorkersResponse\"\x00\x12\x37\n\tGetWorker\x12\x18.ateapi.GetWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12=\n\x0c\x43reateWorker\x12\x1b.ateapi.CreateWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12=\n\x0cUpdateWorker\x12\x1b.ateapi.UpdateWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12=\n\x0c\x44\x65leteWorker\x12\x1b.ateapi.DeleteWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12;\n\x0b\x44rainWorker\x12\x1a.ateapi.DrainWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12u\n\x1aListWorkerActorAssignments\x12).ateapi.ListWorkerActorAssignmentsRequest\x1a*.ateapi.ListWorkerActorAssignmentsResponse\"\x00\x12\x45\n\nListActors\x12\x19.ateapi.ListActorsRequest\x1a\x1a.ateapi.ListActorsResponse\"\x00\x12\x43\n\x0e\x43reateAtespace\x12\x1d.ateapi.CreateAtespaceRequest\x1a\x10.ateapi.Atespace\"\x00\x12=\n\x0bGetAtespace\x12\x1a.ateapi.GetAtespaceRequest\x1a\x10.ateapi.Atespace\"\x00\x12N\n\rListAtespaces\x12\x1c.ateapi.ListAtespacesRequest\x1a\x1d.ateapi.ListAtespacesResponse\"\x00\x12\x43\n\x0e\x44\x65leteAtespace\x12\x1d.ateapi.DeleteAtespaceRequest\x1a\x10.ateapi.Atespace\"\x00\x12R\n\x13\x43reateActorTemplate\x12\".ateapi.CreateActorTemplateRequest\x1a\x15.ateapi.ActorTemplate\"\x00\x12L\n\x10GetActorTemplate\x12\x1f.ateapi.GetActorTemplateRequest\x1a\x15.ateapi.ActorTemplate\"\x00\x12]\n\x12ListActorTemplates\x12!.ateapi.ListActorTemplatesRequest\x1a\".ateapi.ListActorTemplatesResponse\"\x00\x12R\n\x13\x44\x65leteActorTemplate\x12\".ateapi.DeleteActorTemplateRequest\x1a\x15.ateapi.ActorTemplate\"\x00\x32i\n\rWorkerService\x12X\n\x11SetWorkerCapacity\x12 .ateapi.SetWorkerCapacityRequest\x1a!.ateapi.SetWorkerCapacityResponseB9Z7github.com/agent-substrate/substrate/pkg/proto/ateapipbb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0c\x61teapi.proto\x12\x06\x61teapi\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"]\n\x10\x45xternalSnapshot\x12\x14\n\x0csnapshot_uri\x18\x01 \x01(\t\x12\x33\n\rcontent_scope\x18\x02 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\"\x86\x01\n\x11LocalSnapshotInfo\x12\x15\n\rsnapshot_name\x18\x01 \x01(\t\x12%\n\x1dnode_vms_with_local_snapshots\x18\x02 \x03(\t\x12\x33\n\rcontent_scope\x18\x03 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\"w\n\x08Selector\x12\x37\n\x0cmatch_labels\x18\x01 \x03(\x0b\x32!.ateapi.Selector.MatchLabelsEntry\x1a\x32\n\x10MatchLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xb2\x01\n\x10ResourceMetadata\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0b\n\x03uid\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\x03\x12/\n\x0b\x63reate_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xf6\x03\n\x0e\x45xternalVolume\x12\x13\n\x0bvolume_name\x18\x01 \x01(\t\x12\x19\n\x11storage_volume_id\x18\x02 \x01(\t\x12\x13\n\x0bvolume_type\x18\x03 \x01(\t\x12-\n\x06status\x18\x04 \x01(\x0e\x32\x1d.ateapi.ExternalVolume.Status\x12\x41\n\x0evolume_context\x18\x05 \x03(\x0b\x32).ateapi.ExternalVolume.VolumeContextEntry\x12\x43\n\x0fpublish_context\x18\x06 \x03(\x0b\x32*.ateapi.ExternalVolume.PublishContextEntry\x12\x1c\n\x14publish_context_node\x18\x07 \x01(\t\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x35\n\x13PublishContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"]\n\x06Status\x12\x16\n\x12STATUS_UNSPECIFIED\x10\x00\x12\x12\n\x0eSTATUS_PENDING\x10\x01\x12\x12\n\x0eSTATUS_CREATED\x10\x02\x12\x13\n\x0fSTATUS_DELETING\x10\x03\"\xd5\x01\n\x05\x41\x63tor\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12)\n\x0e\x61\x63tor_template\x18\x04 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12)\n\x0fworker_selector\x18\x05 \x01(\x0b\x32\x10.ateapi.Selector\x12%\n\nsource_tag\x18\x06 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12#\n\x06status\x18\x07 \x01(\x0b\x32\x13.ateapi.ActorStatus\"]\n\x0c\x45gressPolicy\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12!\n\x05rules\x18\x02 \x03(\x0b\x32\x12.ateapi.EgressRule\"{\n\nEgressRule\x12\'\n\thostnames\x18\x01 \x01(\x0b\x32\x14.ateapi.HostnameRule\x12\x1f\n\x05\x63idrs\x18\x02 \x01(\x0b\x32\x10.ateapi.CIDRRule\x12#\n\x03\x61ll\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Empty\"L\n\x0cHostnameRule\x12\x10\n\x08patterns\x18\x01 \x03(\t\x12*\n\x07\x65\x66\x66\x65\x63ts\x18\x02 \x01(\x0b\x32\x19.ateapi.EgressRuleEffects\"\x19\n\x08\x43IDRRule\x12\r\n\x05\x63idrs\x18\x01 \x03(\t\"U\n\x11\x45gressRuleEffects\x12@\n\x15inject_static_headers\x18\x01 \x03(\x0b\x32!.ateapi.CredentialHeaderInjection\"S\n\x19\x43redentialHeaderInjection\x12\x0e\n\x06header\x18\x01 \x01(\t\x12\x0e\n\x06prefix\x18\x02 \x01(\t\x12\x16\n\x0e\x63redential_uri\x18\x03 \x01(\t\"\xf0\x02\n\x0b\x41\x63torStatus\x12!\n\x05state\x18\x01 \x01(\x0e\x32\x12.ateapi.ActorState\x12\x33\n\x11worker_assignment\x18\x02 \x01(\x0b\x32\x18.ateapi.WorkerAssignment\x12 \n\x18in_progress_snapshot_uri\x18\x03 \x01(\t\x12\x33\n\x11\x65xternal_snapshot\x18\x04 \x01(\x0b\x32\x18.ateapi.ExternalSnapshot\x12\x36\n\x13local_snapshot_info\x18\x05 \x01(\x0b\x32\x19.ateapi.LocalSnapshotInfo\x12-\n\ractor_volumes\x18\x07 \x03(\x0b\x32\x16.ateapi.ExternalVolume\x12\'\n\x1fin_progress_local_snapshot_name\x18\x08 \x01(\t\x12\"\n\x1a\x63urrent_actor_template_uid\x18\x0b \x01(\t\"\xba\x01\n\x10WorkerAssignment\x12!\n\x06worker\x18\x06 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x18\n\x10worker_namespace\x18\x01 \x01(\t\x12\x13\n\x0bworker_pool\x18\x02 \x01(\t\x12\x12\n\nworker_pod\x18\x03 \x01(\t\x12\x16\n\x0eworker_pod_uid\x18\x04 \x01(\t\x12\x15\n\rworker_pod_ip\x18\x05 \x01(\t\x12\x11\n\tnode_name\x18\x07 \x01(\t\"\x87\x01\n\tTagStatus\x12*\n\x08snapshot\x18\x01 \x01(\x0b\x32\x18.ateapi.ExternalSnapshot\x12\x1a\n\x12\x61\x63tor_template_uid\x18\x02 \x01(\t\x12\x18\n\x10storage_location\x18\x03 \x01(\t\x12\x18\n\x10source_actor_uid\x18\x04 \x01(\t\"\x9e\x01\n\x03Tag\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12!\n\x06status\x18\x02 \x01(\x0b\x32\x11.ateapi.TagStatus\x12\x1f\n\x05scope\x18\x03 \x01(\x0e\x32\x10.ateapi.TagScope\x12\'\n\x0csource_actor\x18\x04 \x01(\x0b\x32\x11.ateapi.ObjectRef\"6\n\x08\x41tespace\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\"+\n\tObjectRef\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"\xe3\x02\n\rActorTemplate\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12)\n\x0fworker_selector\x18\x02 \x01(\x0b\x32\x10.ateapi.Selector\x12%\n\ncontainers\x18\x03 \x03(\x0b\x32\x11.ateapi.Container\x12\x1f\n\x07volumes\x18\x04 \x03(\x0b\x32\x0e.ateapi.Volume\x12\x31\n\x10snapshots_config\x18\x05 \x01(\x0b\x32\x17.ateapi.SnapshotsConfig\x12-\n\x0esandbox_config\x18\x06 \x01(\x0b\x32\x15.ateapi.SandboxConfig\x12$\n\tresources\x18\x07 \x01(\x0b\x32\x11.ateapi.Resources\x12+\n\x06status\x18\x08 \x01(\x0b\x32\x1b.ateapi.ActorTemplateStatus\"+\n\tResources\x12\x1e\n\x06limits\x18\x01 \x03(\x0b\x32\x0e.ateapi.Limits\"(\n\x06Limits\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08quantity\x18\x02 \x01(\t\"\x91\x01\n\x14GoldenSnapshotStatus\x12%\n\ngolden_tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12;\n\x17take_golden_snapshot_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x15\n\rerror_message\x18\x03 \x01(\t\"S\n\x13\x41\x63torTemplateStatus\x12<\n\x16golden_snapshot_status\x18\x01 \x01(\x0b\x32\x1c.ateapi.GoldenSnapshotStatus\"Q\n\rSandboxConfig\x12+\n\rsandbox_class\x18\x01 \x01(\x0e\x32\x14.ateapi.SandboxClass\x12\x13\n\x0b\x63onfig_name\x18\x02 \x01(\t\"\xb7\x01\n\x0fSnapshotsConfig\x12.\n\x08on_pause\x18\x01 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\x12/\n\ton_commit\x18\x02 \x01(\x0e\x32\x1c.ateapi.SnapshotContentScope\x12)\n\ton_resume\x18\x03 \x01(\x0b\x32\x16.ateapi.OnResumeConfig\x12\x18\n\x10storage_location\x18\x04 \x01(\t\"9\n\x0eOnResumeConfig\x12\'\n\tfrom_data\x18\x01 \x01(\x0e\x32\x14.ateapi.ResumeSource\"\x9d\x02\n\tContainer\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05image\x18\x02 \x01(\t\x12\x0f\n\x07\x63ommand\x18\x03 \x03(\t\x12\x0c\n\x04\x61rgs\x18\x04 \x03(\t\x12\x1b\n\x03\x65nv\x18\x05 \x03(\x0b\x32\x0e.ateapi.EnvVar\x12\x32\n\x0cwakeup_probe\x18\x06 \x01(\x0b\x32\x1c.ateapi.ContainerWakeupProbe\x12*\n\rvolume_mounts\x18\x07 \x03(\x0b\x32\x13.ateapi.VolumeMount\x12\x31\n\x10security_context\x18\x08 \x01(\x0b\x32\x17.ateapi.SecurityContext\x12$\n\tresources\x18\t \x01(\x0b\x32\x11.ateapi.Resources\"=\n\x0fSecurityContext\x12*\n\x0c\x63\x61pabilities\x18\x01 \x01(\x0b\x32\x14.ateapi.Capabilities\")\n\x0c\x43\x61pabilities\x12\x0b\n\x03\x61\x64\x64\x18\x01 \x03(\t\x12\x0c\n\x04\x64rop\x18\x02 \x03(\t\"*\n\x06\x45nvVar\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\x05value\x18\x02 \x01(\tB\x03\x80\x01\x01\"X\n\x14\x43ontainerWakeupProbe\x12\'\n\x08http_get\x18\x01 \x01(\x0b\x32\x15.ateapi.HTTPGetAction\x12\x17\n\x0ftimeout_seconds\x18\x02 \x01(\x05\"+\n\rHTTPGetAction\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\x05\"\xec\x01\n\x06Volume\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x33\n\x0b\x64urable_dir\x18\x02 \x01(\x0b\x32\x1e.ateapi.DurableDirVolumeSource\x12@\n\x18\x65xternal_volume_template\x18\x03 \x01(\x0b\x32\x1e.ateapi.ExternalVolumeTemplate\x12\x33\n\x0bsystem_info\x18\x05 \x01(\x0b\x32\x1e.ateapi.SystemInfoVolumeSource\x12(\n\x05image\x18\x06 \x01(\x0b\x32\x19.ateapi.ImageVolumeSource\"&\n\x11ImageVolumeSource\x12\x11\n\treference\x18\x01 \x01(\t\"\x18\n\x16\x44urableDirVolumeSource\"F\n\x16\x45xternalVolumeTemplate\x12\x10\n\x08\x63\x61pacity\x18\x01 \x01(\t\x12\x1a\n\x12storage_class_name\x18\x02 \x01(\t\"L\n\x16SystemInfoVolumeSource\x12\x32\n\x0c\x64\x61ta_sources\x18\x01 \x03(\x0b\x32\x1c.ateapi.SystemInfoDataSource\"\x84\x01\n\x14SystemInfoDataSource\x12\x37\n\x0e\x61\x63tor_metadata\x18\x01 \x01(\x0b\x32\x1f.ateapi.ActorMetadataDataSource\x12\x33\n\x0ctrust_bundle\x18\x02 \x01(\x0b\x32\x1d.ateapi.TrustBundleDataSource\"C\n\x17\x41\x63torMetadataDataSource\x12(\n\x05items\x18\x01 \x03(\x0b\x32\x19.ateapi.ActorMetadataItem\"L\n\x11\x41\x63torMetadataItem\x12)\n\x05\x66ield\x18\x01 \x01(\x0e\x32\x1a.ateapi.ActorMetadataField\x12\x0c\n\x04path\x18\x02 \x01(\t\"3\n\x15TrustBundleDataSource\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\"/\n\x0bVolumeMount\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nmount_path\x18\x02 \x01(\t\";\n\x15\x43reateAtespaceRequest\x12\"\n\x08\x61tespace\x18\x01 \x01(\x0b\x32\x10.ateapi.Atespace\"9\n\x12GetAtespaceRequest\x12#\n\x08\x61tespace\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"=\n\x14ListAtespacesRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\"U\n\x15ListAtespacesResponse\x12#\n\tatespaces\x18\x01 \x03(\x0b\x32\x10.ateapi.Atespace\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"<\n\x15\x44\x65leteAtespaceRequest\x12#\n\x08\x61tespace\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"K\n\x1a\x43reateActorTemplateRequest\x12-\n\x0e\x61\x63tor_template\x18\x01 \x01(\x0b\x32\x15.ateapi.ActorTemplate\"D\n\x17GetActorTemplateRequest\x12)\n\x0e\x61\x63tor_template\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"T\n\x19ListActorTemplatesRequest\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"e\n\x1aListActorTemplatesResponse\x12.\n\x0f\x61\x63tor_templates\x18\x01 \x03(\x0b\x32\x15.ateapi.ActorTemplate\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"G\n\x1a\x44\x65leteActorTemplateRequest\x12)\n\x0e\x61\x63tor_template\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"3\n\x0fGetActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"2\n\x12\x43reateActorRequest\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"2\n\x12UpdateActorRequest\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"7\n\x13SuspendActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"4\n\x14SuspendActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"5\n\x11PauseActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"2\n\x12PauseActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"6\n\x12ResumeActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"D\n\x13ResumeActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\x12\x0f\n\x07resumed\x18\x02 \x01(\x08\"6\n\x12RevertActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"3\n\x13RevertActorResponse\x12\x1c\n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\r.ateapi.Actor\"I\n\x12\x44\x65leteActorRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tany_state\x18\x02 \x01(\x08\"?\n\x1bGetActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"o\n\x1e\x43reateActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12+\n\regress_policy\x18\x02 \x01(\x0b\x32\x14.ateapi.EgressPolicy\"o\n\x1eUpdateActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12+\n\regress_policy\x18\x02 \x01(\x0b\x32\x14.ateapi.EgressPolicy\"B\n\x1e\x44\x65leteActorEgressPolicyRequest\x12 \n\x05\x61\x63tor\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"/\n\rGetTagRequest\x12\x1e\n\x03tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"\\\n\x13MintActorJWTRequest\x12 \n\x05\x61\x63tor\x18\x05 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tactor_uid\x18\x07 \x01(\t\x12\x10\n\x08\x61udience\x18\x01 \x03(\t\".\n\x14MintActorJWTResponse\x12\x16\n\tactor_jwt\x18\x01 \x01(\tB\x03\x80\x01\x01\"\xa9\x01\n\x1bMintActorCertificateRequest\x12 \n\x05\x61\x63tor\x18\x06 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tactor_uid\x18\x07 \x01(\t\x12#\n\x1b\x63\x65rtificate_signing_request\x18\x02 \x01(\x0c\x12\x30\n\x07purpose\x18\x04 \x01(\x0e\x32\x1f.ateapi.ActorCertificatePurpose\":\n\x1cMintActorCertificateResponse\x12\x1a\n\x12\x61\x63tor_certificates\x18\x01 \x03(\x0c\"D\n\x17GetActorSnapshotRequest\x12)\n\x0e\x61\x63tor_snapshot\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"K\n\x1aGetActorSnapshotTagRequest\x12-\n\x12\x61\x63tor_snapshot_tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"J\n\x0fListTagsRequest\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"F\n\x10ListTagsResponse\x12\x19\n\x04tags\x18\x01 \x03(\x0b\x32\x0b.ateapi.Tag\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\",\n\x10\x43reateTagRequest\x12\x18\n\x03tag\x18\x01 \x01(\x0b\x32\x0b.ateapi.Tag\",\n\x10UpdateTagRequest\x12\x18\n\x03tag\x18\x01 \x01(\x0b\x32\x0b.ateapi.Tag\"2\n\x10\x44\x65leteTagRequest\x12\x1e\n\x03tag\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"-\n\rDeleteOptions\x12\x0f\n\x07version\x18\x01 \x01(\x03\x12\x0b\n\x03uid\x18\x02 \x01(\t\"m\n!ListWorkerActorAssignmentsRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"q\n\"ListWorkerActorAssignmentsResponse\x12\x32\n\x11\x61\x63tor_assignments\x18\x01 \x03(\x0b\x32\x17.ateapi.ActorAssignment\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\";\n\x12ListWorkersRequest\x12\x11\n\tpage_size\x18\x01 \x01(\x05\x12\x12\n\npage_token\x18\x02 \x01(\t\"O\n\x13ListWorkersResponse\x12\x1f\n\x07workers\x18\x01 \x03(\x0b\x32\x0e.ateapi.Worker\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"5\n\x10GetWorkerRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"5\n\x13\x43reateWorkerRequest\x12\x1e\n\x06worker\x18\x01 \x01(\x0b\x32\x0e.ateapi.Worker\"5\n\x13UpdateWorkerRequest\x12\x1e\n\x06worker\x18\x01 \x01(\x0b\x32\x0e.ateapi.Worker\"`\n\x13\x44\x65leteWorkerRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12&\n\x07options\x18\x02 \x01(\x0b\x32\x15.ateapi.DeleteOptions\"7\n\x12\x44rainWorkerRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\"L\n\x11ListActorsRequest\x12\x10\n\x08\x61tespace\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t\"L\n\x12ListActorsResponse\x12\x1d\n\x06\x61\x63tors\x18\x01 \x03(\x0b\x32\r.ateapi.Actor\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t\"\xc6\x02\n\x06Worker\x12*\n\x08metadata\x18\x01 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12\x18\n\x10worker_namespace\x18\x02 \x01(\t\x12\x13\n\x0bworker_pool\x18\x03 \x01(\t\x12\x12\n\nworker_pod\x18\x04 \x01(\t\x12\x16\n\x0eworker_pod_uid\x18\x05 \x01(\t\x12\x11\n\tnode_name\x18\x06 \x01(\t\x12\n\n\x02ip\x18\x07 \x01(\t\x12\x15\n\rsandbox_class\x18\x08 \x01(\t\x12*\n\x06labels\x18\t \x03(\x0b\x32\x1a.ateapi.Worker.LabelsEntry\x12$\n\x06status\x18\x0b \x01(\x0b\x32\x14.ateapi.WorkerStatus\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x89\x01\n\x0cWorkerStatus\x12\"\n\x05state\x18\x01 \x01(\x0e\x32\x13.ateapi.WorkerState\x12)\n\x08\x63\x61pacity\x18\x02 \x01(\x0b\x32\x17.ateapi.WorkerResources\x12*\n\tallocated\x18\x03 \x01(\x0b\x32\x17.ateapi.WorkerResources\"G\n\x0fWorkerResources\x12$\n\tresources\x18\x01 \x01(\x0b\x32\x11.ateapi.Resources\x12\x0e\n\x06\x61\x63tors\x18\x02 \x01(\x05\"\xc7\x01\n\x0f\x41\x63torAssignment\x12*\n\x08metadata\x18\x06 \x01(\x0b\x32\x18.ateapi.ResourceMetadata\x12 \n\x05\x61\x63tor\x18\x02 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12\x11\n\tactor_uid\x18\x03 \x01(\t\x12-\n\x12\x61\x63tor_template_ref\x18\x04 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12$\n\tresources\x18\x05 \x01(\x0b\x32\x11.ateapi.Resources\"h\n\x18SetWorkerCapacityRequest\x12!\n\x06worker\x18\x01 \x01(\x0b\x32\x11.ateapi.ObjectRef\x12)\n\x08\x63\x61pacity\x18\x02 \x01(\x0b\x32\x17.ateapi.WorkerResources\";\n\x19SetWorkerCapacityResponse\x12\x1e\n\x06worker\x18\x01 \x01(\x0b\x32\x0e.ateapi.Worker*\x80\x01\n\x14SnapshotContentScope\x12&\n\"SNAPSHOT_CONTENT_SCOPE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bSNAPSHOT_CONTENT_SCOPE_FULL\x10\x01\x12\x1f\n\x1bSNAPSHOT_CONTENT_SCOPE_DATA\x10\x02*V\n\x08TagScope\x12\x19\n\x15TAG_SCOPE_UNSPECIFIED\x10\x00\x12\x16\n\x12TAG_SCOPE_ATESPACE\x10\x01\x12\x17\n\x13TAG_SCOPE_PUBLISHED\x10\x02*\x92\x02\n\nActorState\x12\x1b\n\x17\x41\x43TOR_STATE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41\x43TOR_STATE_RESUMING\x10\x01\x12\x17\n\x13\x41\x43TOR_STATE_RUNNING\x10\x02\x12\x1a\n\x16\x41\x43TOR_STATE_SUSPENDING\x10\x03\x12\x19\n\x15\x41\x43TOR_STATE_SUSPENDED\x10\x04\x12\x17\n\x13\x41\x43TOR_STATE_PAUSING\x10\x05\x12\x16\n\x12\x41\x43TOR_STATE_PAUSED\x10\x06\x12\x17\n\x13\x41\x43TOR_STATE_CRASHED\x10\x07\x12\x18\n\x14\x41\x43TOR_STATE_DELETING\x10\x08\x12\x19\n\x15\x41\x43TOR_STATE_REVERTING\x10\t*b\n\x0cSandboxClass\x12\x1d\n\x19SANDBOX_CLASS_UNSPECIFIED\x10\x00\x12\x18\n\x14SANDBOX_CLASS_GVISOR\x10\x01\x12\x19\n\x15SANDBOX_CLASS_MICROVM\x10\x02*d\n\x0cResumeSource\x12\x1d\n\x19RESUME_SOURCE_UNSPECIFIED\x10\x00\x12\x1b\n\x17RESUME_SOURCE_COLD_BOOT\x10\x01\x12\x18\n\x14RESUME_SOURCE_GOLDEN\x10\x02*\x9a\x01\n\x12\x41\x63torMetadataField\x12$\n ACTOR_METADATA_FIELD_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x41\x43TOR_METADATA_FIELD_NAME\x10\x01\x12!\n\x1d\x41\x43TOR_METADATA_FIELD_ATESPACE\x10\x02\x12\x1c\n\x18\x41\x43TOR_METADATA_FIELD_UID\x10\x03*k\n\x17\x41\x63torCertificatePurpose\x12)\n%ACTOR_CERTIFICATE_PURPOSE_UNSPECIFIED\x10\x00\x12%\n!ACTOR_CERTIFICATE_PURPOSE_ATUNNEL\x10\x01*_\n\x0bWorkerState\x12\x1c\n\x18WORKER_STATE_UNSPECIFIED\x10\x00\x12\x17\n\x13WORKER_STATE_ACTIVE\x10\x01\x12\x19\n\x15WORKER_STATE_DRAINING\x10\x02\x32\xef\x13\n\x07\x43ontrol\x12\x34\n\x08GetActor\x12\x17.ateapi.GetActorRequest\x1a\r.ateapi.Actor\"\x00\x12:\n\x0b\x43reateActor\x12\x1a.ateapi.CreateActorRequest\x1a\r.ateapi.Actor\"\x00\x12:\n\x0bUpdateActor\x12\x1a.ateapi.UpdateActorRequest\x1a\r.ateapi.Actor\"\x00\x12K\n\x0cSuspendActor\x12\x1b.ateapi.SuspendActorRequest\x1a\x1c.ateapi.SuspendActorResponse\"\x00\x12\x45\n\nPauseActor\x12\x19.ateapi.PauseActorRequest\x1a\x1a.ateapi.PauseActorResponse\"\x00\x12H\n\x0bResumeActor\x12\x1a.ateapi.ResumeActorRequest\x1a\x1b.ateapi.ResumeActorResponse\"\x00\x12H\n\x0bRevertActor\x12\x1a.ateapi.RevertActorRequest\x1a\x1b.ateapi.RevertActorResponse\"\x00\x12:\n\x0b\x44\x65leteActor\x12\x1a.ateapi.DeleteActorRequest\x1a\r.ateapi.Actor\"\x00\x12S\n\x14GetActorEgressPolicy\x12#.ateapi.GetActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12Y\n\x17\x43reateActorEgressPolicy\x12&.ateapi.CreateActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12Y\n\x17UpdateActorEgressPolicy\x12&.ateapi.UpdateActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12Y\n\x17\x44\x65leteActorEgressPolicy\x12&.ateapi.DeleteActorEgressPolicyRequest\x1a\x14.ateapi.EgressPolicy\"\x00\x12K\n\x0cMintActorJWT\x12\x1b.ateapi.MintActorJWTRequest\x1a\x1c.ateapi.MintActorJWTResponse\"\x00\x12\x63\n\x14MintActorCertificate\x12#.ateapi.MintActorCertificateRequest\x1a$.ateapi.MintActorCertificateResponse\"\x00\x12\x34\n\tCreateTag\x12\x18.ateapi.CreateTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12.\n\x06GetTag\x12\x15.ateapi.GetTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12?\n\x08ListTags\x12\x17.ateapi.ListTagsRequest\x1a\x18.ateapi.ListTagsResponse\"\x00\x12\x34\n\tUpdateTag\x12\x18.ateapi.UpdateTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12\x34\n\tDeleteTag\x12\x18.ateapi.DeleteTagRequest\x1a\x0b.ateapi.Tag\"\x00\x12H\n\x0bListWorkers\x12\x1a.ateapi.ListWorkersRequest\x1a\x1b.ateapi.ListWorkersResponse\"\x00\x12\x37\n\tGetWorker\x12\x18.ateapi.GetWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12=\n\x0c\x43reateWorker\x12\x1b.ateapi.CreateWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12=\n\x0cUpdateWorker\x12\x1b.ateapi.UpdateWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12=\n\x0c\x44\x65leteWorker\x12\x1b.ateapi.DeleteWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12;\n\x0b\x44rainWorker\x12\x1a.ateapi.DrainWorkerRequest\x1a\x0e.ateapi.Worker\"\x00\x12u\n\x1aListWorkerActorAssignments\x12).ateapi.ListWorkerActorAssignmentsRequest\x1a*.ateapi.ListWorkerActorAssignmentsResponse\"\x00\x12\x45\n\nListActors\x12\x19.ateapi.ListActorsRequest\x1a\x1a.ateapi.ListActorsResponse\"\x00\x12\x43\n\x0e\x43reateAtespace\x12\x1d.ateapi.CreateAtespaceRequest\x1a\x10.ateapi.Atespace\"\x00\x12=\n\x0bGetAtespace\x12\x1a.ateapi.GetAtespaceRequest\x1a\x10.ateapi.Atespace\"\x00\x12N\n\rListAtespaces\x12\x1c.ateapi.ListAtespacesRequest\x1a\x1d.ateapi.ListAtespacesResponse\"\x00\x12\x43\n\x0e\x44\x65leteAtespace\x12\x1d.ateapi.DeleteAtespaceRequest\x1a\x10.ateapi.Atespace\"\x00\x12R\n\x13\x43reateActorTemplate\x12\".ateapi.CreateActorTemplateRequest\x1a\x15.ateapi.ActorTemplate\"\x00\x12L\n\x10GetActorTemplate\x12\x1f.ateapi.GetActorTemplateRequest\x1a\x15.ateapi.ActorTemplate\"\x00\x12]\n\x12ListActorTemplates\x12!.ateapi.ListActorTemplatesRequest\x1a\".ateapi.ListActorTemplatesResponse\"\x00\x12R\n\x13\x44\x65leteActorTemplate\x12\".ateapi.DeleteActorTemplateRequest\x1a\x15.ateapi.ActorTemplate\"\x00\x32i\n\rWorkerService\x12X\n\x11SetWorkerCapacity\x12 .ateapi.SetWorkerCapacityRequest\x1a!.ateapi.SetWorkerCapacityResponseB9Z7github.com/agent-substrate/substrate/pkg/proto/ateapipbb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -52,28 +52,30 @@ _globals['_SELECTOR_MATCHLABELSENTRY']._serialized_options = b'8\001' _globals['_EXTERNALVOLUME_VOLUMECONTEXTENTRY']._loaded_options = None _globals['_EXTERNALVOLUME_VOLUMECONTEXTENTRY']._serialized_options = b'8\001' + _globals['_EXTERNALVOLUME_PUBLISHCONTEXTENTRY']._loaded_options = None + _globals['_EXTERNALVOLUME_PUBLISHCONTEXTENTRY']._serialized_options = b'8\001' _globals['_ENVVAR'].fields_by_name['value']._loaded_options = None _globals['_ENVVAR'].fields_by_name['value']._serialized_options = b'\200\001\001' _globals['_MINTACTORJWTRESPONSE'].fields_by_name['actor_jwt']._loaded_options = None _globals['_MINTACTORJWTRESPONSE'].fields_by_name['actor_jwt']._serialized_options = b'\200\001\001' _globals['_WORKER_LABELSENTRY']._loaded_options = None _globals['_WORKER_LABELSENTRY']._serialized_options = b'8\001' - _globals['_SNAPSHOTCONTENTSCOPE']._serialized_start=9512 - _globals['_SNAPSHOTCONTENTSCOPE']._serialized_end=9640 - _globals['_TAGSCOPE']._serialized_start=9642 - _globals['_TAGSCOPE']._serialized_end=9728 - _globals['_ACTORSTATE']._serialized_start=9731 - _globals['_ACTORSTATE']._serialized_end=10005 - _globals['_SANDBOXCLASS']._serialized_start=10007 - _globals['_SANDBOXCLASS']._serialized_end=10105 - _globals['_RESUMESOURCE']._serialized_start=10107 - _globals['_RESUMESOURCE']._serialized_end=10207 - _globals['_ACTORMETADATAFIELD']._serialized_start=10210 - _globals['_ACTORMETADATAFIELD']._serialized_end=10364 - _globals['_ACTORCERTIFICATEPURPOSE']._serialized_start=10366 - _globals['_ACTORCERTIFICATEPURPOSE']._serialized_end=10473 - _globals['_WORKERSTATE']._serialized_start=10475 - _globals['_WORKERSTATE']._serialized_end=10570 + _globals['_SNAPSHOTCONTENTSCOPE']._serialized_start=9666 + _globals['_SNAPSHOTCONTENTSCOPE']._serialized_end=9794 + _globals['_TAGSCOPE']._serialized_start=9796 + _globals['_TAGSCOPE']._serialized_end=9882 + _globals['_ACTORSTATE']._serialized_start=9885 + _globals['_ACTORSTATE']._serialized_end=10159 + _globals['_SANDBOXCLASS']._serialized_start=10161 + _globals['_SANDBOXCLASS']._serialized_end=10259 + _globals['_RESUMESOURCE']._serialized_start=10261 + _globals['_RESUMESOURCE']._serialized_end=10361 + _globals['_ACTORMETADATAFIELD']._serialized_start=10364 + _globals['_ACTORMETADATAFIELD']._serialized_end=10518 + _globals['_ACTORCERTIFICATEPURPOSE']._serialized_start=10520 + _globals['_ACTORCERTIFICATEPURPOSE']._serialized_end=10627 + _globals['_WORKERSTATE']._serialized_start=10629 + _globals['_WORKERSTATE']._serialized_end=10724 _globals['_EXTERNALSNAPSHOT']._serialized_start=86 _globals['_EXTERNALSNAPSHOT']._serialized_end=179 _globals['_LOCALSNAPSHOTINFO']._serialized_start=182 @@ -85,201 +87,203 @@ _globals['_RESOURCEMETADATA']._serialized_start=440 _globals['_RESOURCEMETADATA']._serialized_end=618 _globals['_EXTERNALVOLUME']._serialized_start=621 - _globals['_EXTERNALVOLUME']._serialized_end=969 - _globals['_EXTERNALVOLUME_VOLUMECONTEXTENTRY']._serialized_start=822 - _globals['_EXTERNALVOLUME_VOLUMECONTEXTENTRY']._serialized_end=874 - _globals['_EXTERNALVOLUME_STATUS']._serialized_start=876 - _globals['_EXTERNALVOLUME_STATUS']._serialized_end=969 - _globals['_ACTOR']._serialized_start=972 - _globals['_ACTOR']._serialized_end=1185 - _globals['_EGRESSPOLICY']._serialized_start=1187 - _globals['_EGRESSPOLICY']._serialized_end=1280 - _globals['_EGRESSRULE']._serialized_start=1282 - _globals['_EGRESSRULE']._serialized_end=1405 - _globals['_HOSTNAMERULE']._serialized_start=1407 - _globals['_HOSTNAMERULE']._serialized_end=1483 - _globals['_CIDRRULE']._serialized_start=1485 - _globals['_CIDRRULE']._serialized_end=1510 - _globals['_EGRESSRULEEFFECTS']._serialized_start=1512 - _globals['_EGRESSRULEEFFECTS']._serialized_end=1597 - _globals['_CREDENTIALHEADERINJECTION']._serialized_start=1599 - _globals['_CREDENTIALHEADERINJECTION']._serialized_end=1682 - _globals['_ACTORSTATUS']._serialized_start=1685 - _globals['_ACTORSTATUS']._serialized_end=2053 - _globals['_WORKERASSIGNMENT']._serialized_start=2056 - _globals['_WORKERASSIGNMENT']._serialized_end=2242 - _globals['_TAGSTATUS']._serialized_start=2245 - _globals['_TAGSTATUS']._serialized_end=2380 - _globals['_TAG']._serialized_start=2383 - _globals['_TAG']._serialized_end=2541 - _globals['_ATESPACE']._serialized_start=2543 - _globals['_ATESPACE']._serialized_end=2597 - _globals['_OBJECTREF']._serialized_start=2599 - _globals['_OBJECTREF']._serialized_end=2642 - _globals['_ACTORTEMPLATE']._serialized_start=2645 - _globals['_ACTORTEMPLATE']._serialized_end=3000 - _globals['_RESOURCES']._serialized_start=3002 - _globals['_RESOURCES']._serialized_end=3045 - _globals['_LIMITS']._serialized_start=3047 - _globals['_LIMITS']._serialized_end=3087 - _globals['_GOLDENSNAPSHOTSTATUS']._serialized_start=3090 - _globals['_GOLDENSNAPSHOTSTATUS']._serialized_end=3235 - _globals['_ACTORTEMPLATESTATUS']._serialized_start=3237 - _globals['_ACTORTEMPLATESTATUS']._serialized_end=3320 - _globals['_SANDBOXCONFIG']._serialized_start=3322 - _globals['_SANDBOXCONFIG']._serialized_end=3403 - _globals['_SNAPSHOTSCONFIG']._serialized_start=3406 - _globals['_SNAPSHOTSCONFIG']._serialized_end=3589 - _globals['_ONRESUMECONFIG']._serialized_start=3591 - _globals['_ONRESUMECONFIG']._serialized_end=3648 - _globals['_CONTAINER']._serialized_start=3651 - _globals['_CONTAINER']._serialized_end=3936 - _globals['_SECURITYCONTEXT']._serialized_start=3938 - _globals['_SECURITYCONTEXT']._serialized_end=3999 - _globals['_CAPABILITIES']._serialized_start=4001 - _globals['_CAPABILITIES']._serialized_end=4042 - _globals['_ENVVAR']._serialized_start=4044 - _globals['_ENVVAR']._serialized_end=4086 - _globals['_CONTAINERWAKEUPPROBE']._serialized_start=4088 - _globals['_CONTAINERWAKEUPPROBE']._serialized_end=4176 - _globals['_HTTPGETACTION']._serialized_start=4178 - _globals['_HTTPGETACTION']._serialized_end=4221 - _globals['_VOLUME']._serialized_start=4224 - _globals['_VOLUME']._serialized_end=4460 - _globals['_IMAGEVOLUMESOURCE']._serialized_start=4462 - _globals['_IMAGEVOLUMESOURCE']._serialized_end=4500 - _globals['_DURABLEDIRVOLUMESOURCE']._serialized_start=4502 - _globals['_DURABLEDIRVOLUMESOURCE']._serialized_end=4526 - _globals['_EXTERNALVOLUMETEMPLATE']._serialized_start=4528 - _globals['_EXTERNALVOLUMETEMPLATE']._serialized_end=4598 - _globals['_SYSTEMINFOVOLUMESOURCE']._serialized_start=4600 - _globals['_SYSTEMINFOVOLUMESOURCE']._serialized_end=4676 - _globals['_SYSTEMINFODATASOURCE']._serialized_start=4679 - _globals['_SYSTEMINFODATASOURCE']._serialized_end=4811 - _globals['_ACTORMETADATADATASOURCE']._serialized_start=4813 - _globals['_ACTORMETADATADATASOURCE']._serialized_end=4880 - _globals['_ACTORMETADATAITEM']._serialized_start=4882 - _globals['_ACTORMETADATAITEM']._serialized_end=4958 - _globals['_TRUSTBUNDLEDATASOURCE']._serialized_start=4960 - _globals['_TRUSTBUNDLEDATASOURCE']._serialized_end=5011 - _globals['_VOLUMEMOUNT']._serialized_start=5013 - _globals['_VOLUMEMOUNT']._serialized_end=5060 - _globals['_CREATEATESPACEREQUEST']._serialized_start=5062 - _globals['_CREATEATESPACEREQUEST']._serialized_end=5121 - _globals['_GETATESPACEREQUEST']._serialized_start=5123 - _globals['_GETATESPACEREQUEST']._serialized_end=5180 - _globals['_LISTATESPACESREQUEST']._serialized_start=5182 - _globals['_LISTATESPACESREQUEST']._serialized_end=5243 - _globals['_LISTATESPACESRESPONSE']._serialized_start=5245 - _globals['_LISTATESPACESRESPONSE']._serialized_end=5330 - _globals['_DELETEATESPACEREQUEST']._serialized_start=5332 - _globals['_DELETEATESPACEREQUEST']._serialized_end=5392 - _globals['_CREATEACTORTEMPLATEREQUEST']._serialized_start=5394 - _globals['_CREATEACTORTEMPLATEREQUEST']._serialized_end=5469 - _globals['_GETACTORTEMPLATEREQUEST']._serialized_start=5471 - _globals['_GETACTORTEMPLATEREQUEST']._serialized_end=5539 - _globals['_LISTACTORTEMPLATESREQUEST']._serialized_start=5541 - _globals['_LISTACTORTEMPLATESREQUEST']._serialized_end=5625 - _globals['_LISTACTORTEMPLATESRESPONSE']._serialized_start=5627 - _globals['_LISTACTORTEMPLATESRESPONSE']._serialized_end=5728 - _globals['_DELETEACTORTEMPLATEREQUEST']._serialized_start=5730 - _globals['_DELETEACTORTEMPLATEREQUEST']._serialized_end=5801 - _globals['_GETACTORREQUEST']._serialized_start=5803 - _globals['_GETACTORREQUEST']._serialized_end=5854 - _globals['_CREATEACTORREQUEST']._serialized_start=5856 - _globals['_CREATEACTORREQUEST']._serialized_end=5906 - _globals['_UPDATEACTORREQUEST']._serialized_start=5908 - _globals['_UPDATEACTORREQUEST']._serialized_end=5958 - _globals['_SUSPENDACTORREQUEST']._serialized_start=5960 - _globals['_SUSPENDACTORREQUEST']._serialized_end=6015 - _globals['_SUSPENDACTORRESPONSE']._serialized_start=6017 - _globals['_SUSPENDACTORRESPONSE']._serialized_end=6069 - _globals['_PAUSEACTORREQUEST']._serialized_start=6071 - _globals['_PAUSEACTORREQUEST']._serialized_end=6124 - _globals['_PAUSEACTORRESPONSE']._serialized_start=6126 - _globals['_PAUSEACTORRESPONSE']._serialized_end=6176 - _globals['_RESUMEACTORREQUEST']._serialized_start=6178 - _globals['_RESUMEACTORREQUEST']._serialized_end=6232 - _globals['_RESUMEACTORRESPONSE']._serialized_start=6234 - _globals['_RESUMEACTORRESPONSE']._serialized_end=6302 - _globals['_REVERTACTORREQUEST']._serialized_start=6304 - _globals['_REVERTACTORREQUEST']._serialized_end=6358 - _globals['_REVERTACTORRESPONSE']._serialized_start=6360 - _globals['_REVERTACTORRESPONSE']._serialized_end=6411 - _globals['_DELETEACTORREQUEST']._serialized_start=6413 - _globals['_DELETEACTORREQUEST']._serialized_end=6486 - _globals['_GETACTOREGRESSPOLICYREQUEST']._serialized_start=6488 - _globals['_GETACTOREGRESSPOLICYREQUEST']._serialized_end=6551 - _globals['_CREATEACTOREGRESSPOLICYREQUEST']._serialized_start=6553 - _globals['_CREATEACTOREGRESSPOLICYREQUEST']._serialized_end=6664 - _globals['_UPDATEACTOREGRESSPOLICYREQUEST']._serialized_start=6666 - _globals['_UPDATEACTOREGRESSPOLICYREQUEST']._serialized_end=6777 - _globals['_DELETEACTOREGRESSPOLICYREQUEST']._serialized_start=6779 - _globals['_DELETEACTOREGRESSPOLICYREQUEST']._serialized_end=6845 - _globals['_GETTAGREQUEST']._serialized_start=6847 - _globals['_GETTAGREQUEST']._serialized_end=6894 - _globals['_MINTACTORJWTREQUEST']._serialized_start=6896 - _globals['_MINTACTORJWTREQUEST']._serialized_end=6988 - _globals['_MINTACTORJWTRESPONSE']._serialized_start=6990 - _globals['_MINTACTORJWTRESPONSE']._serialized_end=7036 - _globals['_MINTACTORCERTIFICATEREQUEST']._serialized_start=7039 - _globals['_MINTACTORCERTIFICATEREQUEST']._serialized_end=7208 - _globals['_MINTACTORCERTIFICATERESPONSE']._serialized_start=7210 - _globals['_MINTACTORCERTIFICATERESPONSE']._serialized_end=7268 - _globals['_GETACTORSNAPSHOTREQUEST']._serialized_start=7270 - _globals['_GETACTORSNAPSHOTREQUEST']._serialized_end=7338 - _globals['_GETACTORSNAPSHOTTAGREQUEST']._serialized_start=7340 - _globals['_GETACTORSNAPSHOTTAGREQUEST']._serialized_end=7415 - _globals['_LISTTAGSREQUEST']._serialized_start=7417 - _globals['_LISTTAGSREQUEST']._serialized_end=7491 - _globals['_LISTTAGSRESPONSE']._serialized_start=7493 - _globals['_LISTTAGSRESPONSE']._serialized_end=7563 - _globals['_CREATETAGREQUEST']._serialized_start=7565 - _globals['_CREATETAGREQUEST']._serialized_end=7609 - _globals['_UPDATETAGREQUEST']._serialized_start=7611 - _globals['_UPDATETAGREQUEST']._serialized_end=7655 - _globals['_DELETETAGREQUEST']._serialized_start=7657 - _globals['_DELETETAGREQUEST']._serialized_end=7707 - _globals['_DELETEOPTIONS']._serialized_start=7709 - _globals['_DELETEOPTIONS']._serialized_end=7754 - _globals['_LISTWORKERACTORASSIGNMENTSREQUEST']._serialized_start=7756 - _globals['_LISTWORKERACTORASSIGNMENTSREQUEST']._serialized_end=7865 - _globals['_LISTWORKERACTORASSIGNMENTSRESPONSE']._serialized_start=7867 - _globals['_LISTWORKERACTORASSIGNMENTSRESPONSE']._serialized_end=7980 - _globals['_LISTWORKERSREQUEST']._serialized_start=7982 - _globals['_LISTWORKERSREQUEST']._serialized_end=8041 - _globals['_LISTWORKERSRESPONSE']._serialized_start=8043 - _globals['_LISTWORKERSRESPONSE']._serialized_end=8122 - _globals['_GETWORKERREQUEST']._serialized_start=8124 - _globals['_GETWORKERREQUEST']._serialized_end=8177 - _globals['_CREATEWORKERREQUEST']._serialized_start=8179 - _globals['_CREATEWORKERREQUEST']._serialized_end=8232 - _globals['_UPDATEWORKERREQUEST']._serialized_start=8234 - _globals['_UPDATEWORKERREQUEST']._serialized_end=8287 - _globals['_DELETEWORKERREQUEST']._serialized_start=8289 - _globals['_DELETEWORKERREQUEST']._serialized_end=8385 - _globals['_DRAINWORKERREQUEST']._serialized_start=8387 - _globals['_DRAINWORKERREQUEST']._serialized_end=8442 - _globals['_LISTACTORSREQUEST']._serialized_start=8444 - _globals['_LISTACTORSREQUEST']._serialized_end=8520 - _globals['_LISTACTORSRESPONSE']._serialized_start=8522 - _globals['_LISTACTORSRESPONSE']._serialized_end=8598 - _globals['_WORKER']._serialized_start=8601 - _globals['_WORKER']._serialized_end=8927 - _globals['_WORKER_LABELSENTRY']._serialized_start=8882 - _globals['_WORKER_LABELSENTRY']._serialized_end=8927 - _globals['_WORKERSTATUS']._serialized_start=8930 - _globals['_WORKERSTATUS']._serialized_end=9067 - _globals['_WORKERRESOURCES']._serialized_start=9069 - _globals['_WORKERRESOURCES']._serialized_end=9140 - _globals['_ACTORASSIGNMENT']._serialized_start=9143 - _globals['_ACTORASSIGNMENT']._serialized_end=9342 - _globals['_SETWORKERCAPACITYREQUEST']._serialized_start=9344 - _globals['_SETWORKERCAPACITYREQUEST']._serialized_end=9448 - _globals['_SETWORKERCAPACITYRESPONSE']._serialized_start=9450 - _globals['_SETWORKERCAPACITYRESPONSE']._serialized_end=9509 - _globals['_CONTROL']._serialized_start=10573 - _globals['_CONTROL']._serialized_end=13116 - _globals['_WORKERSERVICE']._serialized_start=13118 - _globals['_WORKERSERVICE']._serialized_end=13223 + _globals['_EXTERNALVOLUME']._serialized_end=1123 + _globals['_EXTERNALVOLUME_VOLUMECONTEXTENTRY']._serialized_start=921 + _globals['_EXTERNALVOLUME_VOLUMECONTEXTENTRY']._serialized_end=973 + _globals['_EXTERNALVOLUME_PUBLISHCONTEXTENTRY']._serialized_start=975 + _globals['_EXTERNALVOLUME_PUBLISHCONTEXTENTRY']._serialized_end=1028 + _globals['_EXTERNALVOLUME_STATUS']._serialized_start=1030 + _globals['_EXTERNALVOLUME_STATUS']._serialized_end=1123 + _globals['_ACTOR']._serialized_start=1126 + _globals['_ACTOR']._serialized_end=1339 + _globals['_EGRESSPOLICY']._serialized_start=1341 + _globals['_EGRESSPOLICY']._serialized_end=1434 + _globals['_EGRESSRULE']._serialized_start=1436 + _globals['_EGRESSRULE']._serialized_end=1559 + _globals['_HOSTNAMERULE']._serialized_start=1561 + _globals['_HOSTNAMERULE']._serialized_end=1637 + _globals['_CIDRRULE']._serialized_start=1639 + _globals['_CIDRRULE']._serialized_end=1664 + _globals['_EGRESSRULEEFFECTS']._serialized_start=1666 + _globals['_EGRESSRULEEFFECTS']._serialized_end=1751 + _globals['_CREDENTIALHEADERINJECTION']._serialized_start=1753 + _globals['_CREDENTIALHEADERINJECTION']._serialized_end=1836 + _globals['_ACTORSTATUS']._serialized_start=1839 + _globals['_ACTORSTATUS']._serialized_end=2207 + _globals['_WORKERASSIGNMENT']._serialized_start=2210 + _globals['_WORKERASSIGNMENT']._serialized_end=2396 + _globals['_TAGSTATUS']._serialized_start=2399 + _globals['_TAGSTATUS']._serialized_end=2534 + _globals['_TAG']._serialized_start=2537 + _globals['_TAG']._serialized_end=2695 + _globals['_ATESPACE']._serialized_start=2697 + _globals['_ATESPACE']._serialized_end=2751 + _globals['_OBJECTREF']._serialized_start=2753 + _globals['_OBJECTREF']._serialized_end=2796 + _globals['_ACTORTEMPLATE']._serialized_start=2799 + _globals['_ACTORTEMPLATE']._serialized_end=3154 + _globals['_RESOURCES']._serialized_start=3156 + _globals['_RESOURCES']._serialized_end=3199 + _globals['_LIMITS']._serialized_start=3201 + _globals['_LIMITS']._serialized_end=3241 + _globals['_GOLDENSNAPSHOTSTATUS']._serialized_start=3244 + _globals['_GOLDENSNAPSHOTSTATUS']._serialized_end=3389 + _globals['_ACTORTEMPLATESTATUS']._serialized_start=3391 + _globals['_ACTORTEMPLATESTATUS']._serialized_end=3474 + _globals['_SANDBOXCONFIG']._serialized_start=3476 + _globals['_SANDBOXCONFIG']._serialized_end=3557 + _globals['_SNAPSHOTSCONFIG']._serialized_start=3560 + _globals['_SNAPSHOTSCONFIG']._serialized_end=3743 + _globals['_ONRESUMECONFIG']._serialized_start=3745 + _globals['_ONRESUMECONFIG']._serialized_end=3802 + _globals['_CONTAINER']._serialized_start=3805 + _globals['_CONTAINER']._serialized_end=4090 + _globals['_SECURITYCONTEXT']._serialized_start=4092 + _globals['_SECURITYCONTEXT']._serialized_end=4153 + _globals['_CAPABILITIES']._serialized_start=4155 + _globals['_CAPABILITIES']._serialized_end=4196 + _globals['_ENVVAR']._serialized_start=4198 + _globals['_ENVVAR']._serialized_end=4240 + _globals['_CONTAINERWAKEUPPROBE']._serialized_start=4242 + _globals['_CONTAINERWAKEUPPROBE']._serialized_end=4330 + _globals['_HTTPGETACTION']._serialized_start=4332 + _globals['_HTTPGETACTION']._serialized_end=4375 + _globals['_VOLUME']._serialized_start=4378 + _globals['_VOLUME']._serialized_end=4614 + _globals['_IMAGEVOLUMESOURCE']._serialized_start=4616 + _globals['_IMAGEVOLUMESOURCE']._serialized_end=4654 + _globals['_DURABLEDIRVOLUMESOURCE']._serialized_start=4656 + _globals['_DURABLEDIRVOLUMESOURCE']._serialized_end=4680 + _globals['_EXTERNALVOLUMETEMPLATE']._serialized_start=4682 + _globals['_EXTERNALVOLUMETEMPLATE']._serialized_end=4752 + _globals['_SYSTEMINFOVOLUMESOURCE']._serialized_start=4754 + _globals['_SYSTEMINFOVOLUMESOURCE']._serialized_end=4830 + _globals['_SYSTEMINFODATASOURCE']._serialized_start=4833 + _globals['_SYSTEMINFODATASOURCE']._serialized_end=4965 + _globals['_ACTORMETADATADATASOURCE']._serialized_start=4967 + _globals['_ACTORMETADATADATASOURCE']._serialized_end=5034 + _globals['_ACTORMETADATAITEM']._serialized_start=5036 + _globals['_ACTORMETADATAITEM']._serialized_end=5112 + _globals['_TRUSTBUNDLEDATASOURCE']._serialized_start=5114 + _globals['_TRUSTBUNDLEDATASOURCE']._serialized_end=5165 + _globals['_VOLUMEMOUNT']._serialized_start=5167 + _globals['_VOLUMEMOUNT']._serialized_end=5214 + _globals['_CREATEATESPACEREQUEST']._serialized_start=5216 + _globals['_CREATEATESPACEREQUEST']._serialized_end=5275 + _globals['_GETATESPACEREQUEST']._serialized_start=5277 + _globals['_GETATESPACEREQUEST']._serialized_end=5334 + _globals['_LISTATESPACESREQUEST']._serialized_start=5336 + _globals['_LISTATESPACESREQUEST']._serialized_end=5397 + _globals['_LISTATESPACESRESPONSE']._serialized_start=5399 + _globals['_LISTATESPACESRESPONSE']._serialized_end=5484 + _globals['_DELETEATESPACEREQUEST']._serialized_start=5486 + _globals['_DELETEATESPACEREQUEST']._serialized_end=5546 + _globals['_CREATEACTORTEMPLATEREQUEST']._serialized_start=5548 + _globals['_CREATEACTORTEMPLATEREQUEST']._serialized_end=5623 + _globals['_GETACTORTEMPLATEREQUEST']._serialized_start=5625 + _globals['_GETACTORTEMPLATEREQUEST']._serialized_end=5693 + _globals['_LISTACTORTEMPLATESREQUEST']._serialized_start=5695 + _globals['_LISTACTORTEMPLATESREQUEST']._serialized_end=5779 + _globals['_LISTACTORTEMPLATESRESPONSE']._serialized_start=5781 + _globals['_LISTACTORTEMPLATESRESPONSE']._serialized_end=5882 + _globals['_DELETEACTORTEMPLATEREQUEST']._serialized_start=5884 + _globals['_DELETEACTORTEMPLATEREQUEST']._serialized_end=5955 + _globals['_GETACTORREQUEST']._serialized_start=5957 + _globals['_GETACTORREQUEST']._serialized_end=6008 + _globals['_CREATEACTORREQUEST']._serialized_start=6010 + _globals['_CREATEACTORREQUEST']._serialized_end=6060 + _globals['_UPDATEACTORREQUEST']._serialized_start=6062 + _globals['_UPDATEACTORREQUEST']._serialized_end=6112 + _globals['_SUSPENDACTORREQUEST']._serialized_start=6114 + _globals['_SUSPENDACTORREQUEST']._serialized_end=6169 + _globals['_SUSPENDACTORRESPONSE']._serialized_start=6171 + _globals['_SUSPENDACTORRESPONSE']._serialized_end=6223 + _globals['_PAUSEACTORREQUEST']._serialized_start=6225 + _globals['_PAUSEACTORREQUEST']._serialized_end=6278 + _globals['_PAUSEACTORRESPONSE']._serialized_start=6280 + _globals['_PAUSEACTORRESPONSE']._serialized_end=6330 + _globals['_RESUMEACTORREQUEST']._serialized_start=6332 + _globals['_RESUMEACTORREQUEST']._serialized_end=6386 + _globals['_RESUMEACTORRESPONSE']._serialized_start=6388 + _globals['_RESUMEACTORRESPONSE']._serialized_end=6456 + _globals['_REVERTACTORREQUEST']._serialized_start=6458 + _globals['_REVERTACTORREQUEST']._serialized_end=6512 + _globals['_REVERTACTORRESPONSE']._serialized_start=6514 + _globals['_REVERTACTORRESPONSE']._serialized_end=6565 + _globals['_DELETEACTORREQUEST']._serialized_start=6567 + _globals['_DELETEACTORREQUEST']._serialized_end=6640 + _globals['_GETACTOREGRESSPOLICYREQUEST']._serialized_start=6642 + _globals['_GETACTOREGRESSPOLICYREQUEST']._serialized_end=6705 + _globals['_CREATEACTOREGRESSPOLICYREQUEST']._serialized_start=6707 + _globals['_CREATEACTOREGRESSPOLICYREQUEST']._serialized_end=6818 + _globals['_UPDATEACTOREGRESSPOLICYREQUEST']._serialized_start=6820 + _globals['_UPDATEACTOREGRESSPOLICYREQUEST']._serialized_end=6931 + _globals['_DELETEACTOREGRESSPOLICYREQUEST']._serialized_start=6933 + _globals['_DELETEACTOREGRESSPOLICYREQUEST']._serialized_end=6999 + _globals['_GETTAGREQUEST']._serialized_start=7001 + _globals['_GETTAGREQUEST']._serialized_end=7048 + _globals['_MINTACTORJWTREQUEST']._serialized_start=7050 + _globals['_MINTACTORJWTREQUEST']._serialized_end=7142 + _globals['_MINTACTORJWTRESPONSE']._serialized_start=7144 + _globals['_MINTACTORJWTRESPONSE']._serialized_end=7190 + _globals['_MINTACTORCERTIFICATEREQUEST']._serialized_start=7193 + _globals['_MINTACTORCERTIFICATEREQUEST']._serialized_end=7362 + _globals['_MINTACTORCERTIFICATERESPONSE']._serialized_start=7364 + _globals['_MINTACTORCERTIFICATERESPONSE']._serialized_end=7422 + _globals['_GETACTORSNAPSHOTREQUEST']._serialized_start=7424 + _globals['_GETACTORSNAPSHOTREQUEST']._serialized_end=7492 + _globals['_GETACTORSNAPSHOTTAGREQUEST']._serialized_start=7494 + _globals['_GETACTORSNAPSHOTTAGREQUEST']._serialized_end=7569 + _globals['_LISTTAGSREQUEST']._serialized_start=7571 + _globals['_LISTTAGSREQUEST']._serialized_end=7645 + _globals['_LISTTAGSRESPONSE']._serialized_start=7647 + _globals['_LISTTAGSRESPONSE']._serialized_end=7717 + _globals['_CREATETAGREQUEST']._serialized_start=7719 + _globals['_CREATETAGREQUEST']._serialized_end=7763 + _globals['_UPDATETAGREQUEST']._serialized_start=7765 + _globals['_UPDATETAGREQUEST']._serialized_end=7809 + _globals['_DELETETAGREQUEST']._serialized_start=7811 + _globals['_DELETETAGREQUEST']._serialized_end=7861 + _globals['_DELETEOPTIONS']._serialized_start=7863 + _globals['_DELETEOPTIONS']._serialized_end=7908 + _globals['_LISTWORKERACTORASSIGNMENTSREQUEST']._serialized_start=7910 + _globals['_LISTWORKERACTORASSIGNMENTSREQUEST']._serialized_end=8019 + _globals['_LISTWORKERACTORASSIGNMENTSRESPONSE']._serialized_start=8021 + _globals['_LISTWORKERACTORASSIGNMENTSRESPONSE']._serialized_end=8134 + _globals['_LISTWORKERSREQUEST']._serialized_start=8136 + _globals['_LISTWORKERSREQUEST']._serialized_end=8195 + _globals['_LISTWORKERSRESPONSE']._serialized_start=8197 + _globals['_LISTWORKERSRESPONSE']._serialized_end=8276 + _globals['_GETWORKERREQUEST']._serialized_start=8278 + _globals['_GETWORKERREQUEST']._serialized_end=8331 + _globals['_CREATEWORKERREQUEST']._serialized_start=8333 + _globals['_CREATEWORKERREQUEST']._serialized_end=8386 + _globals['_UPDATEWORKERREQUEST']._serialized_start=8388 + _globals['_UPDATEWORKERREQUEST']._serialized_end=8441 + _globals['_DELETEWORKERREQUEST']._serialized_start=8443 + _globals['_DELETEWORKERREQUEST']._serialized_end=8539 + _globals['_DRAINWORKERREQUEST']._serialized_start=8541 + _globals['_DRAINWORKERREQUEST']._serialized_end=8596 + _globals['_LISTACTORSREQUEST']._serialized_start=8598 + _globals['_LISTACTORSREQUEST']._serialized_end=8674 + _globals['_LISTACTORSRESPONSE']._serialized_start=8676 + _globals['_LISTACTORSRESPONSE']._serialized_end=8752 + _globals['_WORKER']._serialized_start=8755 + _globals['_WORKER']._serialized_end=9081 + _globals['_WORKER_LABELSENTRY']._serialized_start=9036 + _globals['_WORKER_LABELSENTRY']._serialized_end=9081 + _globals['_WORKERSTATUS']._serialized_start=9084 + _globals['_WORKERSTATUS']._serialized_end=9221 + _globals['_WORKERRESOURCES']._serialized_start=9223 + _globals['_WORKERRESOURCES']._serialized_end=9294 + _globals['_ACTORASSIGNMENT']._serialized_start=9297 + _globals['_ACTORASSIGNMENT']._serialized_end=9496 + _globals['_SETWORKERCAPACITYREQUEST']._serialized_start=9498 + _globals['_SETWORKERCAPACITYREQUEST']._serialized_end=9602 + _globals['_SETWORKERCAPACITYRESPONSE']._serialized_start=9604 + _globals['_SETWORKERCAPACITYRESPONSE']._serialized_end=9663 + _globals['_CONTROL']._serialized_start=10727 + _globals['_CONTROL']._serialized_end=13270 + _globals['_WORKERSERVICE']._serialized_start=13272 + _globals['_WORKERSERVICE']._serialized_end=13377 # @@protoc_insertion_point(module_scope) diff --git a/cmd/ateapi/internal/controlapi/functionaltest/actor_test.go b/cmd/ateapi/internal/controlapi/functionaltest/actor_test.go index 7e2262e3ce..f491cadbe7 100644 --- a/cmd/ateapi/internal/controlapi/functionaltest/actor_test.go +++ b/cmd/ateapi/internal/controlapi/functionaltest/actor_test.go @@ -1485,15 +1485,15 @@ type partialFailVolumePlugin struct { deleted []string } -func (f *partialFailVolumePlugin) CreateVolume(ctx context.Context, name, capacity, driverName string, parameters map[string]string) (string, map[string]string, error) { - if strings.HasSuffix(name, "fail-vol2") { - return "", nil, fmt.Errorf("simulated volume creation failure") +func (f *partialFailVolumePlugin) CreateVolume(ctx context.Context, req volume.CreateVolumeRequest) (volume.CreateVolumeResponse, error) { + if strings.HasSuffix(req.Name, "fail-vol2") { + return volume.CreateVolumeResponse{}, fmt.Errorf("simulated volume creation failure") } - return "storage-" + name, parameters, nil + return volume.CreateVolumeResponse{VolumeID: "storage-" + req.Name, VolumeContext: req.Parameters}, nil } -func (f *partialFailVolumePlugin) AttachVolume(ctx context.Context, volumeID, node string) error { - return nil +func (f *partialFailVolumePlugin) AttachVolume(ctx context.Context, req volume.AttachVolumeRequest) (volume.AttachVolumeResponse, error) { + return volume.AttachVolumeResponse{}, nil } func (f *partialFailVolumePlugin) DetachVolume(ctx context.Context, volumeID, node string) error { @@ -1621,20 +1621,20 @@ type retrySuccessVolumePlugin struct { deleted []string } -func (r *retrySuccessVolumePlugin) CreateVolume(ctx context.Context, name, capacity, driverName string, parameters map[string]string) (string, map[string]string, error) { +func (r *retrySuccessVolumePlugin) CreateVolume(ctx context.Context, req volume.CreateVolumeRequest) (volume.CreateVolumeResponse, error) { r.mu.Lock() defer r.mu.Unlock() - if strings.HasSuffix(name, "retry-vol2") { + if strings.HasSuffix(req.Name, "retry-vol2") { r.attempts++ if r.attempts == 1 { - return "", nil, fmt.Errorf("simulated temporary volume creation failure") + return volume.CreateVolumeResponse{}, fmt.Errorf("simulated temporary volume creation failure") } } - return "storage-" + name, parameters, nil + return volume.CreateVolumeResponse{VolumeID: "storage-" + req.Name, VolumeContext: req.Parameters}, nil } -func (r *retrySuccessVolumePlugin) AttachVolume(ctx context.Context, volumeID, node string) error { - return nil +func (r *retrySuccessVolumePlugin) AttachVolume(ctx context.Context, req volume.AttachVolumeRequest) (volume.AttachVolumeResponse, error) { + return volume.AttachVolumeResponse{}, nil } func (r *retrySuccessVolumePlugin) DetachVolume(ctx context.Context, volumeID, node string) error { diff --git a/cmd/ateapi/internal/controlapi/volumes.go b/cmd/ateapi/internal/controlapi/volumes.go index 14680245b1..acc6752cde 100644 --- a/cmd/ateapi/internal/controlapi/volumes.go +++ b/cmd/ateapi/internal/controlapi/volumes.go @@ -21,6 +21,7 @@ import ( "log/slog" "github.com/agent-substrate/substrate/cmd/ateapi/internal/store" + "github.com/agent-substrate/substrate/internal/volume" "github.com/agent-substrate/substrate/pkg/proto/ateapipb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -114,17 +115,21 @@ func createActorVolumes(ctx context.Context, registry VolumePluginRegistry, scLi return resultVolumes, status.Errorf(codes.FailedPrecondition, "failed to get volume plugin for driver %q (StorageClass %q): %v", sc.Provisioner, scName, err) } - storageVolumeID, volCtx, volErr := plugin.CreateVolume(ctx, actVolID, specVol.GetExternalVolumeTemplate().GetCapacity(), sc.Provisioner, sc.Parameters) + resp, volErr := plugin.CreateVolume(ctx, volume.CreateVolumeRequest{ + Name: actVolID, + Capacity: specVol.GetExternalVolumeTemplate().GetCapacity(), + Parameters: sc.Parameters, + }) if volErr != nil { return resultVolumes, status.Errorf(codes.Internal, "failed to create volume %q: %v", specVol.GetName(), volErr) } resultVolumes = append(resultVolumes, &ateapipb.ExternalVolume{ VolumeName: volName, - StorageVolumeId: storageVolumeID, + StorageVolumeId: resp.VolumeID, VolumeType: sc.Provisioner, Status: ateapipb.ExternalVolume_STATUS_CREATED, - VolumeContext: volCtx, + VolumeContext: resp.VolumeContext, }) } return resultVolumes, nil diff --git a/cmd/ateapi/internal/controlapi/workflow_delete.go b/cmd/ateapi/internal/controlapi/workflow_delete.go index 4337195ee1..bec9e628ba 100644 --- a/cmd/ateapi/internal/controlapi/workflow_delete.go +++ b/cmd/ateapi/internal/controlapi/workflow_delete.go @@ -149,7 +149,7 @@ func (w *ActorWorkflow) ensureAteletTerminated(ctx context.Context, actorRef res var workloadSpec *ateletpb.WorkloadSpec if actorTemplate != nil { - spec, err := workloadSpecFromActorTemplate(actorTemplate, actor) + spec, err := workloadSpecFromActorTemplate(actorTemplate, actor, "") if err != nil { return err } diff --git a/cmd/ateapi/internal/controlapi/workflow_pause.go b/cmd/ateapi/internal/controlapi/workflow_pause.go index 7c7352e5b8..3383361b98 100644 --- a/cmd/ateapi/internal/controlapi/workflow_pause.go +++ b/cmd/ateapi/internal/controlapi/workflow_pause.go @@ -172,7 +172,7 @@ func (w *ActorWorkflow) ensureAteletPaused(ctx context.Context, actorRef resourc } client := ateletpb.NewAteomHerderClient(ateletConn) - workloadSpec, err := workloadSpecFromActorTemplate(actorTemplate, actor) + workloadSpec, err := workloadSpecFromActorTemplate(actorTemplate, actor, "") if err != nil { return "", err } diff --git a/cmd/ateapi/internal/controlapi/workflow_resume.go b/cmd/ateapi/internal/controlapi/workflow_resume.go index 773a19a9ed..dfbca60064 100644 --- a/cmd/ateapi/internal/controlapi/workflow_resume.go +++ b/cmd/ateapi/internal/controlapi/workflow_resume.go @@ -19,6 +19,7 @@ import ( "errors" "fmt" "log/slog" + "maps" "time" "github.com/agent-substrate/substrate/cmd/ateapi/internal/scheduling" @@ -26,6 +27,7 @@ import ( "github.com/agent-substrate/substrate/internal/ateattr" "github.com/agent-substrate/substrate/internal/proto/ateletpb" "github.com/agent-substrate/substrate/internal/resources" + "github.com/agent-substrate/substrate/internal/volume" "github.com/agent-substrate/substrate/pkg/proto/ateapipb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -121,10 +123,12 @@ func (w *ActorWorkflow) ResumeActor(ctx context.Context, actorRef resources.Acto return nil, false, err } actor = assigned - if err = w.ensureVolumesAttached(leaseCtx, actor, worker, actorTemplate); err != nil { + var attached *ateapipb.Actor + if attached, err = w.ensureVolumesAttached(leaseCtx, actorRef, actor, worker, actorTemplate); err != nil { return nil, false, err } - if tele, err = w.ensureAteletRestored(leaseCtx, actorRef, actor, actorTemplate, src); err != nil { + actor = attached + if tele, err = w.ensureAteletRestored(leaseCtx, actorRef, actor, actorTemplate, worker.GetNodeName(), src); err != nil { return nil, false, err } var running *ateapipb.Actor @@ -620,30 +624,55 @@ func schedulingConstraints(actor *ateapipb.Actor, tmpl *ateapipb.ActorTemplate) } // ensureVolumesAttached attaches the actor's mounted external volumes to the -// assigned worker's node. Attachment is idempotent, so a re-entered workflow -// safely runs it again. +// assigned worker's node and records the driver's attachment metadata. // TODO replace re-execution with a proper check on the volumes' attach state. -func (w *ActorWorkflow) ensureVolumesAttached(ctx context.Context, actor *ateapipb.Actor, worker *ateapipb.Worker, actorTemplate *ateapipb.ActorTemplate) (err error) { +func (w *ActorWorkflow) ensureVolumesAttached(ctx context.Context, actorRef resources.ActorRef, actor *ateapipb.Actor, worker *ateapipb.Worker, actorTemplate *ateapipb.ActorTemplate) (_ *ateapipb.Actor, err error) { ctx, done := stepSpan(ctx, "AttachVolumes") defer func() { err = done(err) }() node := worker.GetNodeName() if node == "" { - return fmt.Errorf("assigned worker has no node name") + return nil, fmt.Errorf("assigned worker has no node name") } ref := &ateapipb.ObjectRef{Atespace: actor.GetMetadata().GetAtespace(), Name: actor.GetMetadata().GetName()} + updatedVolumes := make(map[string]map[string]string) for _, vol := range getMountedActorVolumes(ctx, ref, actor.GetStatus().GetActorVolumes(), actorTemplate) { slog.InfoContext(ctx, "Attaching volume to node", slog.String("volume_id", vol.GetStorageVolumeId()), slog.String("node", node)) plugin, err := w.pluginRegistry.GetPlugin(ctx, vol.GetVolumeType()) if err != nil { - return fmt.Errorf("failed to get volume plugin for %q: %w", vol.GetVolumeType(), err) + return nil, fmt.Errorf("failed to get volume plugin for %q: %w", vol.GetVolumeType(), err) } - if err := plugin.AttachVolume(ctx, vol.GetStorageVolumeId(), node); err != nil { - return fmt.Errorf("failed to attach volume %q to node %q: %w", vol.GetStorageVolumeId(), node, err) + + resp, err := plugin.AttachVolume(ctx, volume.AttachVolumeRequest{VolumeID: vol.GetStorageVolumeId(), Node: node}) + if err != nil { + return nil, fmt.Errorf("failed to attach volume %q to node %q: %w", vol.GetStorageVolumeId(), node, err) + } + if maps.Equal(vol.GetPublishContext(), resp.PublishContext) && vol.GetPublishContextNode() == node { + continue + } + updatedVolumes[vol.GetVolumeName()] = resp.PublishContext + } + if len(updatedVolumes) == 0 { + return actor, nil + } + + storedActor, updateErr := w.store.UpdateActor(ctx, actorRef, store.PreconditionFrom(actor), func(toUpdate *ateapipb.Actor) error { + for _, vol := range toUpdate.GetStatus().GetActorVolumes() { + if publishContext, ok := updatedVolumes[vol.GetVolumeName()]; ok { + vol.PublishContext = publishContext + vol.PublishContextNode = node + } + } + return nil + }) + if updateErr != nil { + if errors.Is(updateErr, store.ErrVersionConflict) { + return nil, status.Error(codes.Aborted, "concurrent update conflict, please retry") } + return nil, fmt.Errorf("while updating actor after volume attach: %w", updateErr) } - return nil + return storedActor, nil } // ensureAteletRestored brings the workload up on the assigned worker: @@ -653,7 +682,7 @@ func (w *ActorWorkflow) ensureVolumesAttached(ctx context.Context, actor *ateapi // the worker pod UID, so a re-entered workflow re-sends the same semantic // request; once atelet's Restore/Run are idempotent on those keys this step // becomes fully reentrant with no changes here. -func (w *ActorWorkflow) ensureAteletRestored(ctx context.Context, actorRef resources.ActorRef, actor *ateapipb.Actor, actorTemplate *ateapipb.ActorTemplate, src resumeSnapshotSource) (tele restoreTelemetry, err error) { +func (w *ActorWorkflow) ensureAteletRestored(ctx context.Context, actorRef resources.ActorRef, actor *ateapipb.Actor, actorTemplate *ateapipb.ActorTemplate, node string, src resumeSnapshotSource) (tele restoreTelemetry, err error) { ctx, done := stepSpan(ctx, "CallAteletRestore") defer func() { err = done(err) }() @@ -664,7 +693,7 @@ func (w *ActorWorkflow) ensureAteletRestored(ctx context.Context, actorRef resou } client := ateletpb.NewAteomHerderClient(ateletConn) - workloadSpec, err := workloadSpecFromActorTemplate(actorTemplate, actor) + workloadSpec, err := workloadSpecFromActorTemplate(actorTemplate, actor, node) if err != nil { return tele, err } diff --git a/cmd/ateapi/internal/controlapi/workflow_resume_test.go b/cmd/ateapi/internal/controlapi/workflow_resume_test.go index d63c5c1fb5..1b6258188e 100644 --- a/cmd/ateapi/internal/controlapi/workflow_resume_test.go +++ b/cmd/ateapi/internal/controlapi/workflow_resume_test.go @@ -30,14 +30,17 @@ import ( "github.com/agent-substrate/substrate/internal/installdefaults" "github.com/agent-substrate/substrate/internal/proto/ateletpb" "github.com/agent-substrate/substrate/internal/resources" + "github.com/agent-substrate/substrate/internal/volume" atev1alpha1 "github.com/agent-substrate/substrate/pkg/api/v1alpha1" "github.com/agent-substrate/substrate/pkg/proto/ateapipb" + "github.com/google/go-cmp/cmp" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/status" "google.golang.org/grpc/test/bufconn" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -1764,7 +1767,7 @@ func TestResumeActor_AteletWireRequest(t *testing.T) { actor, loadedTmpl, src, err := w.loadActorForResume(ctx, actorRef) if err == nil { - _, err = w.ensureAteletRestored(ctx, actorRef, actor, loadedTmpl, src) + _, err = w.ensureAteletRestored(ctx, actorRef, actor, loadedTmpl, actor.GetStatus().GetWorkerAssignment().GetNodeName(), src) } if got := status.Code(err); got != tt.want.code { t.Fatalf("status.Code(err) = %v, want %v (err: %v)", got, tt.want.code, err) @@ -1805,3 +1808,85 @@ func TestResumeActor_AteletWireRequest(t *testing.T) { }) } } + +type volumeUpdateStore struct { + store.Interface +} + +func (s *volumeUpdateStore) UpdateActor(ctx context.Context, actorRef resources.ActorRef, precondition store.Precondition, mutate func(*ateapipb.Actor) error) (*ateapipb.Actor, error) { + return s.Interface.UpdateActor(ctx, actorRef, precondition, mutate) +} + +// publishContextVolumePlugin hands back a fixed publish context, standing in +// for a driver whose node plugin needs attachment metadata. +type publishContextVolumePlugin struct { + volume.VolumePluginControlPlane + publishContext map[string]string +} + +func (p *publishContextVolumePlugin) AttachVolume(ctx context.Context, req volume.AttachVolumeRequest) (volume.AttachVolumeResponse, error) { + return volume.AttachVolumeResponse{PublishContext: p.publishContext}, nil +} + +func TestEnsureVolumesAttached_PersistsPublishContext(t *testing.T) { + ctx := context.Background() + persistence := newTestPersistence(t) + actorRef := resources.ActorRef{Atespace: "team-a", Name: "id1"} + storetest.MustCreateActor(t, ctx, persistence, &ateapipb.Actor{ + Metadata: &ateapipb.ResourceMetadata{Atespace: "team-a", Name: "id1"}, + Status: &ateapipb.ActorStatus{ + State: ateapipb.ActorState_ACTOR_STATE_RESUMING, + ActorVolumes: []*ateapipb.ExternalVolume{ + {VolumeName: "mounted", StorageVolumeId: "storage-mounted", VolumeType: "mock", Status: ateapipb.ExternalVolume_STATUS_CREATED}, + {VolumeName: "unmounted", StorageVolumeId: "storage-unmounted", VolumeType: "mock", Status: ateapipb.ExternalVolume_STATUS_CREATED}, + }, + }, + }) + actor, err := persistence.GetActor(ctx, actorRef) + if err != nil { + t.Fatalf("GetActor: %v", err) + } + + st := &volumeUpdateStore{Interface: persistence} + w := &ActorWorkflow{ + store: st, + pluginRegistry: &mockPluginRegistry{plugins: map[string]volume.VolumePluginControlPlane{ + "mock": &publishContextVolumePlugin{publishContext: map[string]string{"devicePath": "/dev/xvdba"}}, + }}, + } + worker := &ateapipb.Worker{NodeName: "node-1"} + tmpl := &ateapipb.ActorTemplate{ + Volumes: []*ateapipb.Volume{ + {Name: "mounted", ExternalVolumeTemplate: &ateapipb.ExternalVolumeTemplate{StorageClassName: "sc"}}, + {Name: "unmounted", ExternalVolumeTemplate: &ateapipb.ExternalVolumeTemplate{StorageClassName: "sc"}}, + }, + Containers: []*ateapipb.Container{ + {Name: "main", Image: "img", VolumeMounts: []*ateapipb.VolumeMount{{Name: "mounted", MountPath: "/data"}}}, + }, + } + + want := []*ateapipb.ExternalVolume{ + { + VolumeName: "mounted", + StorageVolumeId: "storage-mounted", + VolumeType: "mock", + Status: ateapipb.ExternalVolume_STATUS_CREATED, + PublishContext: map[string]string{"devicePath": "/dev/xvdba"}, + PublishContextNode: "node-1", + }, + { + VolumeName: "unmounted", + StorageVolumeId: "storage-unmounted", + VolumeType: "mock", + Status: ateapipb.ExternalVolume_STATUS_CREATED, + }, + } + got, err := w.ensureVolumesAttached(ctx, actorRef, actor, worker, tmpl) + if err != nil { + t.Fatalf("ensureVolumesAttached: %v", err) + } + + if diff := cmp.Diff(want, got.GetStatus().GetActorVolumes(), protocmp.Transform()); diff != "" { + t.Errorf("actor volumes mismatch (-want +got):\n%s", diff) + } +} diff --git a/cmd/ateapi/internal/controlapi/workflow_suspend.go b/cmd/ateapi/internal/controlapi/workflow_suspend.go index f7cb00125f..9e2ad4f9ff 100644 --- a/cmd/ateapi/internal/controlapi/workflow_suspend.go +++ b/cmd/ateapi/internal/controlapi/workflow_suspend.go @@ -225,7 +225,7 @@ func (w *ActorWorkflow) ensureAteletSuspended(ctx context.Context, actorRef reso } client := ateletpb.NewAteomHerderClient(ateletConn) - workloadSpec, err := workloadSpecFromActorTemplate(actorTemplate, actor) + workloadSpec, err := workloadSpecFromActorTemplate(actorTemplate, actor, "") if err != nil { return "", err } diff --git a/cmd/ateapi/internal/controlapi/workload_spec.go b/cmd/ateapi/internal/controlapi/workload_spec.go index 933f8feb0f..75e23f371a 100644 --- a/cmd/ateapi/internal/controlapi/workload_spec.go +++ b/cmd/ateapi/internal/controlapi/workload_spec.go @@ -48,7 +48,7 @@ func toAteletResources(r *ateapipb.Resources) (*ateletpb.ResourceLimits, error) // workloadSpecFromActorTemplate builds a WorkloadSpec from the template; // container env is copied verbatim. -func workloadSpecFromActorTemplate(actorTemplate *ateapipb.ActorTemplate, actor *ateapipb.Actor) (*ateletpb.WorkloadSpec, error) { +func workloadSpecFromActorTemplate(actorTemplate *ateapipb.ActorTemplate, actor *ateapipb.Actor, node string) (*ateletpb.WorkloadSpec, error) { workloadSpec := &ateletpb.WorkloadSpec{} // Convert volumes to atelet's representation. ActorTemplate validation has @@ -119,7 +119,7 @@ func workloadSpecFromActorTemplate(actorTemplate *ateapipb.ActorTemplate, actor // TODO: order may be important for nested mounts. Also need to think about // nested mount support in general. - if err := appendExternalVolumes(workloadSpec, actorTemplate, actor); err != nil { + if err := appendExternalVolumes(workloadSpec, actorTemplate, actor, node); err != nil { return nil, err } @@ -157,7 +157,7 @@ func workloadSpecFromActorTemplate(actorTemplate *ateapipb.ActorTemplate, actor // appendExternalVolumes maps template external volumes to resolved actor volumes and appends them to workloadSpec // if they are referenced in container volumeMounts. -func appendExternalVolumes(workloadSpec *ateletpb.WorkloadSpec, template *ateapipb.ActorTemplate, actor *ateapipb.Actor) error { +func appendExternalVolumes(workloadSpec *ateletpb.WorkloadSpec, template *ateapipb.ActorTemplate, actor *ateapipb.Actor, node string) error { if template == nil { return nil } @@ -173,11 +173,15 @@ func appendExternalVolumes(workloadSpec *ateletpb.WorkloadSpec, template *ateapi var storageVolID string var volType string var volCtx map[string]string + var publishCtx map[string]string for _, dbVol := range actor.GetStatus().GetActorVolumes() { if dbVol.GetVolumeName() == vol.GetName() { storageVolID = dbVol.GetStorageVolumeId() volType = dbVol.GetVolumeType() volCtx = dbVol.GetVolumeContext() + if dbVol.GetPublishContextNode() == node { + publishCtx = dbVol.GetPublishContext() + } break } } @@ -191,6 +195,7 @@ func appendExternalVolumes(workloadSpec *ateletpb.WorkloadSpec, template *ateapi StorageVolumeId: storageVolID, VolumeType: volType, VolumeContext: volCtx, + PublishContext: publishCtx, }, }, }) diff --git a/cmd/ateapi/internal/controlapi/workload_spec_test.go b/cmd/ateapi/internal/controlapi/workload_spec_test.go index 5d32d8cd31..91bddb0755 100644 --- a/cmd/ateapi/internal/controlapi/workload_spec_test.go +++ b/cmd/ateapi/internal/controlapi/workload_spec_test.go @@ -331,7 +331,7 @@ func TestWorkloadSpecFromActorTemplate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := workloadSpecFromActorTemplate(tt.template, nil) + got, err := workloadSpecFromActorTemplate(tt.template, nil, "") if err != nil { t.Fatalf("workloadSpecFromActorTemplate failed: %v", err) } @@ -359,7 +359,7 @@ func TestWorkloadSpecFromActorTemplatePropagatesWakeupProbe(t *testing.T) { Image: "side", }, }, - }, nil) + }, nil, "") if err != nil { t.Fatalf("workloadSpecFromActorTemplate failed: %v", err) } @@ -423,37 +423,58 @@ func TestAppendExternalVolumes(t *testing.T) { Status: &ateapipb.ActorStatus{ ActorVolumes: []*ateapipb.ExternalVolume{ { - VolumeName: "vol-1", - StorageVolumeId: "vol-gce-pd-123", - VolumeType: "pd-standard", - VolumeContext: map[string]string{"foo": "bar"}, + VolumeName: "vol-1", + StorageVolumeId: "vol-gce-pd-123", + VolumeType: "pd-standard", + VolumeContext: map[string]string{"foo": "bar"}, + PublishContext: map[string]string{"devicePath": "/dev/xvdba"}, + PublishContextNode: "node-1", }, }, }, } - workloadSpec := &ateletpb.WorkloadSpec{} - if err := appendExternalVolumes(workloadSpec, template, actor); err != nil { - t.Fatalf("appendExternalVolumes unexpected error: %v", err) - } + for _, tt := range []struct { + name string + node string + wantPublishCtx map[string]string + }{ + { + name: "matching node", + node: "node-1", + wantPublishCtx: map[string]string{"devicePath": "/dev/xvdba"}, + }, + { + name: "different node", + node: "node-2", + }, + } { + t.Run(tt.name, func(t *testing.T) { + workloadSpec := &ateletpb.WorkloadSpec{} + if err := appendExternalVolumes(workloadSpec, template, actor, tt.node); err != nil { + t.Fatalf("appendExternalVolumes unexpected error: %v", err) + } - want := &ateletpb.WorkloadSpec{ - Volumes: []*ateletpb.Volume{ - { - Name: "vol-1", - Source: &ateletpb.Volume_External{ - External: &ateletpb.ExternalVolumeSource{ - StorageVolumeId: "vol-gce-pd-123", - VolumeType: "pd-standard", - VolumeContext: map[string]string{"foo": "bar"}, + want := &ateletpb.WorkloadSpec{ + Volumes: []*ateletpb.Volume{ + { + Name: "vol-1", + Source: &ateletpb.Volume_External{ + External: &ateletpb.ExternalVolumeSource{ + StorageVolumeId: "vol-gce-pd-123", + VolumeType: "pd-standard", + VolumeContext: map[string]string{"foo": "bar"}, + PublishContext: tt.wantPublishCtx, + }, + }, }, }, - }, - }, - } + } - if diff := cmp.Diff(want, workloadSpec, protocmp.Transform()); diff != "" { - t.Errorf("appendExternalVolumes mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(want, workloadSpec, protocmp.Transform()); diff != "" { + t.Errorf("appendExternalVolumes mismatch (-want +got):\n%s", diff) + } + }) } // Test missing mounted volume returns an error @@ -464,7 +485,7 @@ func TestAppendExternalVolumes(t *testing.T) { }, Status: &ateapipb.ActorStatus{ActorVolumes: []*ateapipb.ExternalVolume{}}, } - if err := appendExternalVolumes(&ateletpb.WorkloadSpec{}, template, missingActor); err == nil { + if err := appendExternalVolumes(&ateletpb.WorkloadSpec{}, template, missingActor, "node-1"); err == nil { t.Errorf("appendExternalVolumes expected error for missing volume, got nil") } } @@ -495,7 +516,7 @@ func TestWorkloadSpecFromActorTemplatePropagatesSecurityContext(t *testing.T) { SecurityContext: &ateapipb.SecurityContext{Capabilities: &ateapipb.Capabilities{}}, }, }, - }, nil) + }, nil, "") if err != nil { t.Fatalf("workloadSpecFromActorTemplate failed: %v", err) } @@ -612,7 +633,7 @@ func TestWorkloadSpecFromActorTemplatePropagatesResources(t *testing.T) { }, {Name: "unlimited", Image: "main"}, }, - }, nil) + }, nil, "") if err != nil { t.Fatalf("workloadSpecFromActorTemplate failed: %v", err) } diff --git a/cmd/ateapi/internal/controlapi/zz_generated.validation.go b/cmd/ateapi/internal/controlapi/zz_generated.validation.go index f43c5ad7b2..f8799b6347 100644 --- a/cmd/ateapi/internal/controlapi/zz_generated.validation.go +++ b/cmd/ateapi/internal/controlapi/zz_generated.validation.go @@ -3189,6 +3189,81 @@ func Validate_ExternalVolume( errs = append(errs, fn(fldPath.Child("volume_context"), obj.VolumeContext, oldVal, oldObj != nil)...) } + { // field ateapipb.ExternalVolume.PublishContext + fn := func( + fldPath *field.Path, + obj, oldObj map[string]string, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if ateDeepEqual(obj, oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.MaxProperties(ctx, op, fldPath, obj, oldObj, 32).MarkShortCircuit(); len(e) != 0 { + errs = append(errs, e...) + earlyReturn = true + } + if e := validate.OptionalMap(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + if e := validate.EachMapKey(ctx, op, fldPath, obj, oldObj, + func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *string) field.ErrorList { + return validate.MaxLength(ctx, op, fldPath, obj, oldObj, 128) + }); len(e) != 0 { + errs = append(errs, e...) + } + if e := validate.EachMapVal(ctx, op, fldPath, obj, oldObj, validate.DirectEqual, + func(ctx context.Context, op operation.Operation, fldPath *field.Path, obj, oldObj *string) field.ErrorList { + return validate.MaxLength(ctx, op, fldPath, obj, oldObj, 256) + }); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *ateapipb.ExternalVolume) map[string]string { + return oldObj.PublishContext + }) + errs = append(errs, fn(fldPath.Child("publish_context"), obj.PublishContext, oldVal, oldObj != nil)...) + } + + { // field ateapipb.ExternalVolume.PublishContextNode + fn := func( + fldPath *field.Path, + obj, oldObj *string, + oldValueCorrelated bool) (errs field.ErrorList) { + // don't revalidate unchanged data + if oldValueCorrelated && op.Type == operation.Update { + if obj == oldObj || (obj != nil && oldObj != nil && *obj == *oldObj) { + return nil + } + } + // call field-attached validations + earlyReturn := false + if e := validate.OptionalValue(ctx, op, fldPath, obj, oldObj).MarkShortCircuit(); len(e) != 0 { + earlyReturn = true + } + if earlyReturn { + return // do not proceed + } + if e := validate.MaxLength(ctx, op, fldPath, obj, oldObj, 253); len(e) != 0 { + errs = append(errs, e...) + } + return + } + oldVal := safe.Field(oldObj, + func(oldObj *ateapipb.ExternalVolume) *string { + return &oldObj.PublishContextNode + }) + errs = append(errs, fn(fldPath.Child("publish_context_node"), &obj.PublishContextNode, oldVal, oldObj != nil)...) + } + return errs } diff --git a/cmd/atelet/volumes.go b/cmd/atelet/volumes.go index 2a1e54cefb..f846cccf36 100644 --- a/cmd/atelet/volumes.go +++ b/cmd/atelet/volumes.go @@ -44,7 +44,12 @@ func (s *AteomHerder) mountExternalVolumes(ctx context.Context, actorUID string, if err != nil { return fmt.Errorf("failed to get volume plugin for %q: %w", ext.GetVolumeType(), err) } - if err := plugin.MountVolume(ctx, ext.GetStorageVolumeId(), hostPath, ext.GetVolumeContext()); err != nil { + if err := plugin.MountVolume(ctx, volume.MountVolumeRequest{ + VolumeID: ext.GetStorageVolumeId(), + TargetPath: hostPath, + VolumeContext: ext.GetVolumeContext(), + PublishContext: ext.GetPublishContext(), + }); err != nil { return fmt.Errorf("failed to mount volume %q to %q: %w", ext.GetStorageVolumeId(), hostPath, err) } } diff --git a/cmd/atelet/volumes_test.go b/cmd/atelet/volumes_test.go index 588d1f637d..c6c9d11d5a 100644 --- a/cmd/atelet/volumes_test.go +++ b/cmd/atelet/volumes_test.go @@ -30,7 +30,7 @@ type fakeWorkerPlugin struct { unmounted []string } -func (f *fakeWorkerPlugin) MountVolume(ctx context.Context, volumeID string, targetPath string, attributes map[string]string) error { +func (f *fakeWorkerPlugin) MountVolume(ctx context.Context, req volume.MountVolumeRequest) error { return f.mountErr } diff --git a/internal/proto/ateletpb/atelet.pb.go b/internal/proto/ateletpb/atelet.pb.go index b6e2e17221..5c788e3e6c 100644 --- a/internal/proto/ateletpb/atelet.pb.go +++ b/internal/proto/ateletpb/atelet.pb.go @@ -976,8 +976,11 @@ type ExternalVolumeSource struct { StorageVolumeId string `protobuf:"bytes,1,opt,name=storage_volume_id,json=storageVolumeId,proto3" json:"storage_volume_id,omitempty"` VolumeType string `protobuf:"bytes,2,opt,name=volume_type,json=volumeType,proto3" json:"volume_type,omitempty"` VolumeContext map[string]string `protobuf:"bytes,3,rep,name=volume_context,json=volumeContext,proto3" json:"volume_context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // publish_context is the driver's attachment metadata for this node, which + // the node plugin needs to complete the mount. + PublishContext map[string]string `protobuf:"bytes,4,rep,name=publish_context,json=publishContext,proto3" json:"publish_context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ExternalVolumeSource) Reset() { @@ -1031,6 +1034,13 @@ func (x *ExternalVolumeSource) GetVolumeContext() map[string]string { return nil } +func (x *ExternalVolumeSource) GetPublishContext() map[string]string { + if x != nil { + return x.PublishContext + } + return nil +} + type ImageVolumeSource struct { state protoimpl.MessageState `protogen:"open.v1"` Reference string `protobuf:"bytes,1,opt,name=reference,proto3" json:"reference,omitempty"` @@ -2740,14 +2750,18 @@ const file_atelet_proto_rawDesc = "" + "containers\x18\x01 \x03(\v2\x11.atelet.ContainerR\n" + "containers\x12(\n" + "\avolumes\x18\x03 \x03(\v2\x0e.atelet.VolumeR\avolumesJ\x04\b\x02\x10\x03R\vpause_image\"\x12\n" + - "\x10DurableDirVolume\"\xfd\x01\n" + + "\x10DurableDirVolume\"\x9b\x03\n" + "\x14ExternalVolumeSource\x12*\n" + "\x11storage_volume_id\x18\x01 \x01(\tR\x0fstorageVolumeId\x12\x1f\n" + "\vvolume_type\x18\x02 \x01(\tR\n" + "volumeType\x12V\n" + - "\x0evolume_context\x18\x03 \x03(\v2/.atelet.ExternalVolumeSource.VolumeContextEntryR\rvolumeContext\x1a@\n" + + "\x0evolume_context\x18\x03 \x03(\v2/.atelet.ExternalVolumeSource.VolumeContextEntryR\rvolumeContext\x12Y\n" + + "\x0fpublish_context\x18\x04 \x03(\v20.atelet.ExternalVolumeSource.PublishContextEntryR\x0epublishContext\x1a@\n" + "\x12VolumeContextEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1aA\n" + + "\x13PublishContextEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"1\n" + "\x11ImageVolumeSource\x12\x1c\n" + "\treference\x18\x01 \x01(\tR\treference\"Y\n" + @@ -2897,7 +2911,7 @@ func file_atelet_proto_rawDescGZIP() []byte { } var file_atelet_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_atelet_proto_msgTypes = make([]protoimpl.MessageInfo, 41) +var file_atelet_proto_msgTypes = make([]protoimpl.MessageInfo, 42) var file_atelet_proto_goTypes = []any{ (ActorMetadataField)(0), // 0: atelet.ActorMetadataField (CheckpointType)(0), // 1: atelet.CheckpointType @@ -2943,10 +2957,11 @@ var file_atelet_proto_goTypes = []any{ nil, // 41: atelet.ArchAssets.FilesEntry nil, // 42: atelet.SandboxAssets.AssetsEntry nil, // 43: atelet.ExternalVolumeSource.VolumeContextEntry - (*ateapipb.WorkerResources)(nil), // 44: ateapi.WorkerResources + nil, // 44: atelet.ExternalVolumeSource.PublishContextEntry + (*ateapipb.WorkerResources)(nil), // 45: ateapi.WorkerResources } var file_atelet_proto_depIdxs = []int32{ - 44, // 0: atelet.SetWorkerCapacityRequest.capacity:type_name -> ateapi.WorkerResources + 45, // 0: atelet.SetWorkerCapacityRequest.capacity:type_name -> ateapi.WorkerResources 14, // 1: atelet.TerminateRequest.spec:type_name -> atelet.WorkloadSpec 14, // 2: atelet.RunRequest.spec:type_name -> atelet.WorkloadSpec 13, // 3: atelet.RunRequest.sandbox_assets:type_name -> atelet.SandboxAssets @@ -2956,55 +2971,56 @@ var file_atelet_proto_depIdxs = []int32{ 25, // 7: atelet.WorkloadSpec.containers:type_name -> atelet.Container 23, // 8: atelet.WorkloadSpec.volumes:type_name -> atelet.Volume 43, // 9: atelet.ExternalVolumeSource.volume_context:type_name -> atelet.ExternalVolumeSource.VolumeContextEntry - 0, // 10: atelet.ActorMetadataItem.field:type_name -> atelet.ActorMetadataField - 18, // 11: atelet.ActorMetadataDataSource.items:type_name -> atelet.ActorMetadataItem - 19, // 12: atelet.SystemInfoDataSource.actor_metadata:type_name -> atelet.ActorMetadataDataSource - 20, // 13: atelet.SystemInfoDataSource.trust_bundle:type_name -> atelet.TrustBundleDataSource - 21, // 14: atelet.SystemInfoVolume.data_sources:type_name -> atelet.SystemInfoDataSource - 15, // 15: atelet.Volume.durable_dir:type_name -> atelet.DurableDirVolume - 16, // 16: atelet.Volume.external:type_name -> atelet.ExternalVolumeSource - 22, // 17: atelet.Volume.system_info:type_name -> atelet.SystemInfoVolume - 17, // 18: atelet.Volume.image:type_name -> atelet.ImageVolumeSource - 29, // 19: atelet.Container.env:type_name -> atelet.EnvEntry - 30, // 20: atelet.Container.wakeup_probe:type_name -> atelet.WakeupProbe - 24, // 21: atelet.Container.volume_mounts:type_name -> atelet.VolumeMount - 26, // 22: atelet.Container.security_context:type_name -> atelet.SecurityContext - 28, // 23: atelet.Container.resources:type_name -> atelet.ResourceLimits - 27, // 24: atelet.SecurityContext.capabilities:type_name -> atelet.Capabilities - 31, // 25: atelet.WakeupProbe.http_get:type_name -> atelet.HTTPGetAction - 14, // 26: atelet.CheckpointRequest.spec:type_name -> atelet.WorkloadSpec - 1, // 27: atelet.CheckpointRequest.type:type_name -> atelet.CheckpointType - 33, // 28: atelet.CheckpointRequest.local_config:type_name -> atelet.LocalCheckpointConfiguration - 34, // 29: atelet.CheckpointRequest.external_config:type_name -> atelet.ExternalCheckpointConfiguration - 2, // 30: atelet.CheckpointRequest.scope:type_name -> atelet.SnapshotScope - 2, // 31: atelet.UploadPausedCheckpointRequest.desired_scope:type_name -> atelet.SnapshotScope - 14, // 32: atelet.RestoreRequest.spec:type_name -> atelet.WorkloadSpec - 1, // 33: atelet.RestoreRequest.type:type_name -> atelet.CheckpointType - 33, // 34: atelet.RestoreRequest.local_config:type_name -> atelet.LocalCheckpointConfiguration - 34, // 35: atelet.RestoreRequest.external_config:type_name -> atelet.ExternalCheckpointConfiguration - 2, // 36: atelet.RestoreRequest.scope:type_name -> atelet.SnapshotScope - 10, // 37: atelet.RestoreRequest.egress_gateway:type_name -> atelet.EgressGateway - 11, // 38: atelet.ArchAssets.FilesEntry.value:type_name -> atelet.AssetFile - 12, // 39: atelet.SandboxAssets.AssetsEntry.value:type_name -> atelet.ArchAssets - 5, // 40: atelet.AteomSupport.MintActorCertificate:input_type -> atelet.MintActorCertificateRequest - 3, // 41: atelet.AteomSupport.SetWorkerCapacity:input_type -> atelet.SetWorkerCapacityRequest - 9, // 42: atelet.AteomHerder.Run:input_type -> atelet.RunRequest - 35, // 43: atelet.AteomHerder.Checkpoint:input_type -> atelet.CheckpointRequest - 39, // 44: atelet.AteomHerder.Restore:input_type -> atelet.RestoreRequest - 37, // 45: atelet.AteomHerder.UploadPausedCheckpoint:input_type -> atelet.UploadPausedCheckpointRequest - 7, // 46: atelet.AteomHerder.Terminate:input_type -> atelet.TerminateRequest - 6, // 47: atelet.AteomSupport.MintActorCertificate:output_type -> atelet.MintActorCertificateResponse - 4, // 48: atelet.AteomSupport.SetWorkerCapacity:output_type -> atelet.SetWorkerCapacityResponse - 32, // 49: atelet.AteomHerder.Run:output_type -> atelet.RunResponse - 36, // 50: atelet.AteomHerder.Checkpoint:output_type -> atelet.CheckpointResponse - 40, // 51: atelet.AteomHerder.Restore:output_type -> atelet.RestoreResponse - 38, // 52: atelet.AteomHerder.UploadPausedCheckpoint:output_type -> atelet.UploadPausedCheckpointResponse - 8, // 53: atelet.AteomHerder.Terminate:output_type -> atelet.TerminateResponse - 47, // [47:54] is the sub-list for method output_type - 40, // [40:47] is the sub-list for method input_type - 40, // [40:40] is the sub-list for extension type_name - 40, // [40:40] is the sub-list for extension extendee - 0, // [0:40] is the sub-list for field type_name + 44, // 10: atelet.ExternalVolumeSource.publish_context:type_name -> atelet.ExternalVolumeSource.PublishContextEntry + 0, // 11: atelet.ActorMetadataItem.field:type_name -> atelet.ActorMetadataField + 18, // 12: atelet.ActorMetadataDataSource.items:type_name -> atelet.ActorMetadataItem + 19, // 13: atelet.SystemInfoDataSource.actor_metadata:type_name -> atelet.ActorMetadataDataSource + 20, // 14: atelet.SystemInfoDataSource.trust_bundle:type_name -> atelet.TrustBundleDataSource + 21, // 15: atelet.SystemInfoVolume.data_sources:type_name -> atelet.SystemInfoDataSource + 15, // 16: atelet.Volume.durable_dir:type_name -> atelet.DurableDirVolume + 16, // 17: atelet.Volume.external:type_name -> atelet.ExternalVolumeSource + 22, // 18: atelet.Volume.system_info:type_name -> atelet.SystemInfoVolume + 17, // 19: atelet.Volume.image:type_name -> atelet.ImageVolumeSource + 29, // 20: atelet.Container.env:type_name -> atelet.EnvEntry + 30, // 21: atelet.Container.wakeup_probe:type_name -> atelet.WakeupProbe + 24, // 22: atelet.Container.volume_mounts:type_name -> atelet.VolumeMount + 26, // 23: atelet.Container.security_context:type_name -> atelet.SecurityContext + 28, // 24: atelet.Container.resources:type_name -> atelet.ResourceLimits + 27, // 25: atelet.SecurityContext.capabilities:type_name -> atelet.Capabilities + 31, // 26: atelet.WakeupProbe.http_get:type_name -> atelet.HTTPGetAction + 14, // 27: atelet.CheckpointRequest.spec:type_name -> atelet.WorkloadSpec + 1, // 28: atelet.CheckpointRequest.type:type_name -> atelet.CheckpointType + 33, // 29: atelet.CheckpointRequest.local_config:type_name -> atelet.LocalCheckpointConfiguration + 34, // 30: atelet.CheckpointRequest.external_config:type_name -> atelet.ExternalCheckpointConfiguration + 2, // 31: atelet.CheckpointRequest.scope:type_name -> atelet.SnapshotScope + 2, // 32: atelet.UploadPausedCheckpointRequest.desired_scope:type_name -> atelet.SnapshotScope + 14, // 33: atelet.RestoreRequest.spec:type_name -> atelet.WorkloadSpec + 1, // 34: atelet.RestoreRequest.type:type_name -> atelet.CheckpointType + 33, // 35: atelet.RestoreRequest.local_config:type_name -> atelet.LocalCheckpointConfiguration + 34, // 36: atelet.RestoreRequest.external_config:type_name -> atelet.ExternalCheckpointConfiguration + 2, // 37: atelet.RestoreRequest.scope:type_name -> atelet.SnapshotScope + 10, // 38: atelet.RestoreRequest.egress_gateway:type_name -> atelet.EgressGateway + 11, // 39: atelet.ArchAssets.FilesEntry.value:type_name -> atelet.AssetFile + 12, // 40: atelet.SandboxAssets.AssetsEntry.value:type_name -> atelet.ArchAssets + 5, // 41: atelet.AteomSupport.MintActorCertificate:input_type -> atelet.MintActorCertificateRequest + 3, // 42: atelet.AteomSupport.SetWorkerCapacity:input_type -> atelet.SetWorkerCapacityRequest + 9, // 43: atelet.AteomHerder.Run:input_type -> atelet.RunRequest + 35, // 44: atelet.AteomHerder.Checkpoint:input_type -> atelet.CheckpointRequest + 39, // 45: atelet.AteomHerder.Restore:input_type -> atelet.RestoreRequest + 37, // 46: atelet.AteomHerder.UploadPausedCheckpoint:input_type -> atelet.UploadPausedCheckpointRequest + 7, // 47: atelet.AteomHerder.Terminate:input_type -> atelet.TerminateRequest + 6, // 48: atelet.AteomSupport.MintActorCertificate:output_type -> atelet.MintActorCertificateResponse + 4, // 49: atelet.AteomSupport.SetWorkerCapacity:output_type -> atelet.SetWorkerCapacityResponse + 32, // 50: atelet.AteomHerder.Run:output_type -> atelet.RunResponse + 36, // 51: atelet.AteomHerder.Checkpoint:output_type -> atelet.CheckpointResponse + 40, // 52: atelet.AteomHerder.Restore:output_type -> atelet.RestoreResponse + 38, // 53: atelet.AteomHerder.UploadPausedCheckpoint:output_type -> atelet.UploadPausedCheckpointResponse + 8, // 54: atelet.AteomHerder.Terminate:output_type -> atelet.TerminateResponse + 48, // [48:55] is the sub-list for method output_type + 41, // [41:48] is the sub-list for method input_type + 41, // [41:41] is the sub-list for extension type_name + 41, // [41:41] is the sub-list for extension extendee + 0, // [0:41] is the sub-list for field type_name } func init() { file_atelet_proto_init() } @@ -3037,7 +3053,7 @@ func file_atelet_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_atelet_proto_rawDesc), len(file_atelet_proto_rawDesc)), NumEnums: 3, - NumMessages: 41, + NumMessages: 42, NumExtensions: 0, NumServices: 2, }, diff --git a/internal/proto/ateletpb/atelet.proto b/internal/proto/ateletpb/atelet.proto index 8feeff2da8..57a06c48af 100644 --- a/internal/proto/ateletpb/atelet.proto +++ b/internal/proto/ateletpb/atelet.proto @@ -189,6 +189,10 @@ message ExternalVolumeSource { string storage_volume_id = 1; string volume_type = 2; map volume_context = 3; + + // publish_context is the driver's attachment metadata for this node, which + // the node plugin needs to complete the mount. + map publish_context = 4; } message ImageVolumeSource { diff --git a/internal/volume/csi/plugin.go b/internal/volume/csi/plugin.go index ab1337efd9..00f52b0415 100644 --- a/internal/volume/csi/plugin.go +++ b/internal/volume/csi/plugin.go @@ -80,32 +80,35 @@ func (p *Plugin) DriverName(ctx context.Context) (string, error) { } // CreateVolume maps to CSI Controller CreateVolume. -func (p *Plugin) CreateVolume(ctx context.Context, name string, capacity string, driverName string, parameters map[string]string) (string, map[string]string, error) { - qty, err := resource.ParseQuantity(capacity) +func (p *Plugin) CreateVolume(ctx context.Context, req volume.CreateVolumeRequest) (volume.CreateVolumeResponse, error) { + qty, err := resource.ParseQuantity(req.Capacity) if err != nil { - return "", nil, fmt.Errorf("failed to parse capacity %q: %w", capacity, err) + return volume.CreateVolumeResponse{}, fmt.Errorf("failed to parse capacity %q: %w", req.Capacity, err) } capBytes := qty.Value() - req := &csi.CreateVolumeRequest{ - Name: name, + csiReq := &csi.CreateVolumeRequest{ + Name: req.Name, CapacityRange: &csi.CapacityRange{ RequiredBytes: capBytes, }, VolumeCapabilities: getStandardCapabilities(), - Parameters: parameters, + Parameters: req.Parameters, } - resp, err := p.client.CreateVolume(ctx, req) + resp, err := p.client.CreateVolume(ctx, csiReq) if err != nil { - return "", nil, fmt.Errorf("CSI CreateVolume failed: %w", err) + return volume.CreateVolumeResponse{}, fmt.Errorf("CSI CreateVolume failed: %w", err) } if resp.GetVolume() == nil { - return "", nil, fmt.Errorf("CSI CreateVolume response returned nil volume") + return volume.CreateVolumeResponse{}, fmt.Errorf("CSI CreateVolume response returned nil volume") } - return resp.GetVolume().GetVolumeId(), resp.GetVolume().GetVolumeContext(), nil + return volume.CreateVolumeResponse{ + VolumeID: resp.GetVolume().GetVolumeId(), + VolumeContext: resp.GetVolume().GetVolumeContext(), + }, nil } // DeleteVolume maps to CSI Controller DeleteVolume. @@ -122,35 +125,26 @@ func (p *Plugin) DeleteVolume(ctx context.Context, volumeID string) error { } // AttachVolume maps to CSI Controller ControllerPublishVolume. -func (p *Plugin) AttachVolume(ctx context.Context, volumeID string, node string) error { - req := &csi.ControllerPublishVolumeRequest{ - VolumeId: volumeID, - NodeId: node, +func (p *Plugin) AttachVolume(ctx context.Context, req volume.AttachVolumeRequest) (volume.AttachVolumeResponse, error) { + csiReq := &csi.ControllerPublishVolumeRequest{ + VolumeId: req.VolumeID, + NodeId: req.Node, VolumeCapability: getStandardCapabilities()[0], // Use primary capability Readonly: false, } - resp, err := p.client.ControllerPublishVolume(ctx, req) + resp, err := p.client.ControllerPublishVolume(ctx, csiReq) if err != nil { // TODO: Query CSI driver capabilities ahead of time (e.g. during plugin initialization) // to avoid calling unimplemented methods and generating spammy logs. if status.Code(err) == codes.Unimplemented { - slog.WarnContext(ctx, "CSI ControllerPublishVolume is unimplemented by driver; skipping attach", slog.String("volume_id", volumeID), slog.String("node", node)) - return nil + slog.WarnContext(ctx, "CSI ControllerPublishVolume is unimplemented by driver; skipping attach", slog.String("volume_id", req.VolumeID), slog.String("node", req.Node)) + return volume.AttachVolumeResponse{}, nil } - return fmt.Errorf("CSI ControllerPublishVolume failed: %w", err) - } - - // NOTE: CSI ControllerPublishVolume returns PublishContext (metadata needed for mounting). - // Currently, Substrate VolumePlugin interface does not support returning PublishContext. - // We might need to store this context if the driver requires it (e.g. AWS EBS attachment info). - // TODO: Extend Substrate's VolumePlugin interface to return and propagate - // PublishContext if required by the driver for mounting. - if resp != nil { - _ = resp.GetPublishContext() + return volume.AttachVolumeResponse{}, fmt.Errorf("CSI ControllerPublishVolume failed: %w", err) } - return nil + return volume.AttachVolumeResponse{PublishContext: resp.GetPublishContext()}, nil } // DetachVolume maps to CSI Controller ControllerUnpublishVolume. @@ -173,24 +167,25 @@ func (p *Plugin) DetachVolume(ctx context.Context, volumeID string, node string) // MountVolume maps to CSI Node NodePublishVolume. // It also handles NodeStageVolume staging if required by the driver. -func (p *Plugin) MountVolume(ctx context.Context, volumeID string, targetPath string, volumeContext map[string]string) error { +func (p *Plugin) MountVolume(ctx context.Context, req volume.MountVolumeRequest) error { // 1. Stage the volume - stagingPath := filepath.Join(p.stagingDirPrefix, volumeID) + stagingPath := filepath.Join(p.stagingDirPrefix, req.VolumeID) if err := os.MkdirAll(stagingPath, 0750); err != nil { return fmt.Errorf("failed to create staging directory %q: %w", stagingPath, err) } stageReq := &csi.NodeStageVolumeRequest{ - VolumeId: volumeID, + VolumeId: req.VolumeID, StagingTargetPath: stagingPath, VolumeCapability: getStandardCapabilities()[0], // Use primary capability - VolumeContext: volumeContext, + VolumeContext: req.VolumeContext, + PublishContext: req.PublishContext, } _, err := p.client.NodeStageVolume(ctx, stageReq) if err != nil { if status.Code(err) == codes.Unimplemented { - slog.WarnContext(ctx, "CSI NodeStageVolume is unimplemented by driver; skipping staging", slog.String("volume_id", volumeID)) + slog.WarnContext(ctx, "CSI NodeStageVolume is unimplemented by driver; skipping staging", slog.String("volume_id", req.VolumeID)) stagingPath = "" } else { return fmt.Errorf("CSI NodeStageVolume failed: %w", err) @@ -198,18 +193,19 @@ func (p *Plugin) MountVolume(ctx context.Context, volumeID string, targetPath st } // 2. Publish (Mount) the volume - req := &csi.NodePublishVolumeRequest{ - VolumeId: volumeID, - TargetPath: targetPath, + publishReq := &csi.NodePublishVolumeRequest{ + VolumeId: req.VolumeID, + TargetPath: req.TargetPath, VolumeCapability: getStandardCapabilities()[0], Readonly: false, - VolumeContext: volumeContext, + VolumeContext: req.VolumeContext, + PublishContext: req.PublishContext, } if stagingPath != "" { - req.StagingTargetPath = stagingPath + publishReq.StagingTargetPath = stagingPath } - _, err = p.client.NodePublishVolume(ctx, req) + _, err = p.client.NodePublishVolume(ctx, publishReq) if err != nil { return fmt.Errorf("CSI NodePublishVolume failed: %w", err) } diff --git a/internal/volume/csi/plugin_test.go b/internal/volume/csi/plugin_test.go index 79b5a75d9d..51b3ac4c17 100644 --- a/internal/volume/csi/plugin_test.go +++ b/internal/volume/csi/plugin_test.go @@ -21,7 +21,9 @@ import ( "path/filepath" "testing" + "github.com/agent-substrate/substrate/internal/volume" "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/google/go-cmp/cmp" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -184,13 +186,16 @@ func TestPlugin_CreateVolume(t *testing.T) { plugin := NewPlugin(client) ctx := context.Background() - volID, _, err := plugin.CreateVolume(ctx, "test-vol", "1Gi", "standard", nil) + resp, err := plugin.CreateVolume(ctx, volume.CreateVolumeRequest{ + Name: "test-vol", + Capacity: "1Gi", + }) if err != nil { t.Fatalf("CreateVolume failed: %v", err) } - if volID != "test-vol" { - t.Errorf("expected volume ID %q, got %q", "test-vol", volID) + if resp.VolumeID != "test-vol" { + t.Errorf("expected volume ID %q, got %q", "test-vol", resp.VolumeID) } } @@ -228,19 +233,39 @@ func TestPlugin_AttachVolume(t *testing.T) { plugin := NewPlugin(client) ctx := context.Background() - err = plugin.AttachVolume(ctx, "test-vol", "node-1") + resp, err := plugin.AttachVolume(ctx, volume.AttachVolumeRequest{VolumeID: "test-vol", Node: "node-1"}) if err != nil { t.Fatalf("AttachVolume failed: %v", err) } + if len(resp.PublishContext) != 0 { + t.Errorf("expected no publish context from a driver that returns none, got %v", resp.PublishContext) + } + + driver.controllerPublishVolumeFunc = func(ctx context.Context, req *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) { + return &csi.ControllerPublishVolumeResponse{ + PublishContext: map[string]string{"devicePath": "/dev/xvdba"}, + }, nil + } + resp, err = plugin.AttachVolume(ctx, volume.AttachVolumeRequest{VolumeID: "test-vol", Node: "node-1"}) + if err != nil { + t.Fatalf("AttachVolume failed: %v", err) + } + wantPublishCtx := map[string]string{"devicePath": "/dev/xvdba"} + if diff := cmp.Diff(wantPublishCtx, resp.PublishContext); diff != "" { + t.Errorf("publish context mismatch (-want +got):\n%s", diff) + } // Test Unimplemented warning bypass driver.controllerPublishVolumeFunc = func(ctx context.Context, req *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) { return nil, status.Error(codes.Unimplemented, "unimplemented") } - err = plugin.AttachVolume(ctx, "test-vol", "node-1") + resp, err = plugin.AttachVolume(ctx, volume.AttachVolumeRequest{VolumeID: "test-vol", Node: "node-1"}) if err != nil { t.Errorf("AttachVolume should have ignored Unimplemented error, got: %v", err) } + if len(resp.PublishContext) != 0 { + t.Errorf("expected no publish context from an unimplemented attach, got %v", resp.PublishContext) + } } func TestPlugin_DetachVolume(t *testing.T) { @@ -294,7 +319,11 @@ func TestPlugin_MountVolume(t *testing.T) { targetPath := filepath.Join(tmpDir, "target") ctx := context.Background() - err = plugin.MountVolume(ctx, "test-vol", targetPath, nil) + err = plugin.MountVolume(ctx, volume.MountVolumeRequest{ + VolumeID: "test-vol", + TargetPath: targetPath, + PublishContext: map[string]string{"devicePath": "/dev/xvdba"}, + }) if err != nil { t.Fatalf("MountVolume failed: %v", err) } @@ -313,7 +342,7 @@ func TestPlugin_MountVolume(t *testing.T) { os.RemoveAll(tmpDir) os.MkdirAll(plugin.stagingDirPrefix, 0750) - err = plugin.MountVolume(ctx, "test-vol-2", targetPath, nil) + err = plugin.MountVolume(ctx, volume.MountVolumeRequest{VolumeID: "test-vol-2", TargetPath: targetPath}) if err != nil { t.Errorf("MountVolume should have succeeded when NodeStageVolume is unimplemented, got: %v", err) } diff --git a/internal/volume/mock.go b/internal/volume/mock.go index 017d3ca11d..49359bf563 100644 --- a/internal/volume/mock.go +++ b/internal/volume/mock.go @@ -62,10 +62,10 @@ func (p *MockVolumePlugin) DriverName(ctx context.Context) (string, error) { } // CreateVolume simulates volume provisioning. -func (p *MockVolumePlugin) CreateVolume(ctx context.Context, name string, capacity string, storageClass string, parameters map[string]string) (string, map[string]string, error) { - volumeID := "mock-vol-" + name - slog.InfoContext(ctx, "MockVolumePlugin.CreateVolume", slog.String("name", name), slog.String("capacity", capacity), slog.String("storageClass", storageClass), slog.String("volumeID", volumeID)) - return volumeID, parameters, nil +func (p *MockVolumePlugin) CreateVolume(ctx context.Context, req CreateVolumeRequest) (CreateVolumeResponse, error) { + volumeID := "mock-vol-" + req.Name + slog.InfoContext(ctx, "MockVolumePlugin.CreateVolume", slog.String("name", req.Name), slog.String("capacity", req.Capacity), slog.String("volumeID", volumeID)) + return CreateVolumeResponse{VolumeID: volumeID, VolumeContext: req.Parameters}, nil } // DeleteVolume simulates volume deletion. @@ -74,10 +74,11 @@ func (p *MockVolumePlugin) DeleteVolume(ctx context.Context, volumeID string) er return nil } -// AttachVolume simulates volume attachment to a node. -func (p *MockVolumePlugin) AttachVolume(ctx context.Context, volumeID string, node string) error { - slog.InfoContext(ctx, "MockVolumePlugin.AttachVolume", slog.String("volumeID", volumeID), slog.String("node", node)) - return nil +// AttachVolume simulates volume attachment to a node. The mock driver needs no +// attachment metadata, so the response carries no publish context. +func (p *MockVolumePlugin) AttachVolume(ctx context.Context, req AttachVolumeRequest) (AttachVolumeResponse, error) { + slog.InfoContext(ctx, "MockVolumePlugin.AttachVolume", slog.String("volumeID", req.VolumeID), slog.String("node", req.Node)) + return AttachVolumeResponse{}, nil } // DetachVolume simulates volume detachment from a node. @@ -87,25 +88,25 @@ func (p *MockVolumePlugin) DetachVolume(ctx context.Context, volumeID string, no } // MountVolume simulates mounting volume on the host. -func (p *MockVolumePlugin) MountVolume(ctx context.Context, volumeID string, targetPath string, volumeContext map[string]string) error { - slog.InfoContext(ctx, "MockVolumePlugin.MountVolume", slog.String("volumeID", volumeID), slog.String("targetPath", targetPath)) +func (p *MockVolumePlugin) MountVolume(ctx context.Context, req MountVolumeRequest) error { + slog.InfoContext(ctx, "MockVolumePlugin.MountVolume", slog.String("volumeID", req.VolumeID), slog.String("targetPath", req.TargetPath)) - volumeDir := filepath.Join(mockVolumeDirectories, volumeID) + volumeDir := filepath.Join(mockVolumeDirectories, req.VolumeID) if err := os.MkdirAll(volumeDir, 0755); err != nil { - slog.ErrorContext(ctx, "MockVolumePlugin.MountVolume failed: mkdir error", slog.String("volumeID", volumeID), slog.Any("error", err)) + slog.ErrorContext(ctx, "MockVolumePlugin.MountVolume failed: mkdir error", slog.String("volumeID", req.VolumeID), slog.Any("error", err)) return fmt.Errorf("failed to create mock volume directory %q: %w", volumeDir, err) } testFilePath := filepath.Join(volumeDir, "test.txt") if err := os.WriteFile(testFilePath, []byte("test content\n"), 0644); err != nil { - slog.ErrorContext(ctx, "MockVolumePlugin.MountVolume failed: create test file error", slog.String("volumeID", volumeID), slog.Any("error", err)) + slog.ErrorContext(ctx, "MockVolumePlugin.MountVolume failed: create test file error", slog.String("volumeID", req.VolumeID), slog.Any("error", err)) return fmt.Errorf("failed to create test file in %q: %w", volumeDir, err) } // Use symlink instead of bind mount to avoid atelet requiring bidirectional mount propagation. - _ = os.Remove(targetPath) - if err := os.Symlink(volumeDir, targetPath); err != nil { - return fmt.Errorf("failed to symlink %q to %q: %w", volumeDir, targetPath, err) + _ = os.Remove(req.TargetPath) + if err := os.Symlink(volumeDir, req.TargetPath); err != nil { + return fmt.Errorf("failed to symlink %q to %q: %w", volumeDir, req.TargetPath, err) } return nil } diff --git a/internal/volume/plugin.go b/internal/volume/plugin.go index ee54799c2b..20e898700f 100644 --- a/internal/volume/plugin.go +++ b/internal/volume/plugin.go @@ -18,17 +18,66 @@ import ( "context" ) +// CreateVolumeRequest describes a volume to provision. +type CreateVolumeRequest struct { + // Name is the name to provision the volume under. + Name string + // Capacity is the requested size as a Kubernetes resource.Quantity string. + Capacity string + // Parameters are the driver-specific parameters from the StorageClass. + Parameters map[string]string +} + +// CreateVolumeResponse describes a provisioned volume. +type CreateVolumeResponse struct { + // VolumeID is the globally unique ID assigned by the storage system. + VolumeID string + // VolumeContext is driver-defined metadata that the node plugin needs to + // mount the volume. + VolumeContext map[string]string +} + +// AttachVolumeRequest describes a volume to attach to a node. +type AttachVolumeRequest struct { + // VolumeID is the ID assigned by the storage system at creation. + VolumeID string + // Node is the node to attach the volume to. + Node string +} + +// AttachVolumeResponse describes a completed attachment. +type AttachVolumeResponse struct { + // PublishContext is driver-defined attachment metadata that must be echoed + // back on the node's mount calls (e.g. the device path for AWS EBS). It is + // empty for drivers that do not implement attachment, and is only + // meaningful for the node named in the request. + PublishContext map[string]string +} + +// MountVolumeRequest describes a volume to mount on the local node. +type MountVolumeRequest struct { + // VolumeID is the ID assigned by the storage system at creation. + VolumeID string + // TargetPath is the host path to mount the volume at. + TargetPath string + // VolumeContext is the metadata returned when the volume was created. + VolumeContext map[string]string + // PublishContext is the metadata returned when the volume was attached to + // this node. It is empty for drivers that do not implement attachment. + PublishContext map[string]string +} + // VolumePluginControlPlane abstracts storage operations performed on the control plane. type VolumePluginControlPlane interface { DriverName(ctx context.Context) (string, error) - CreateVolume(ctx context.Context, name string, capacity string, driverName string, parameters map[string]string) (volumeID string, volumeContext map[string]string, err error) + CreateVolume(ctx context.Context, req CreateVolumeRequest) (CreateVolumeResponse, error) DeleteVolume(ctx context.Context, volumeID string) error - AttachVolume(ctx context.Context, volumeID string, node string) error + AttachVolume(ctx context.Context, req AttachVolumeRequest) (AttachVolumeResponse, error) DetachVolume(ctx context.Context, volumeID string, node string) error } // VolumePluginWorkerPlane abstracts storage operations performed on worker nodes. type VolumePluginWorkerPlane interface { - MountVolume(ctx context.Context, volumeID string, targetPath string, volumeContext map[string]string) error + MountVolume(ctx context.Context, req MountVolumeRequest) error UnmountVolume(ctx context.Context, volumeID string, targetPath string) error } diff --git a/pkg/proto/ateapipb/ateapi.pb.go b/pkg/proto/ateapipb/ateapi.pb.go index ad7d95f071..7a6b0cd540 100644 --- a/pkg/proto/ateapipb/ateapi.pb.go +++ b/pkg/proto/ateapipb/ateapi.pb.go @@ -903,8 +903,27 @@ type ExternalVolume struct { // +k8s:eachKey=+k8s:maxLength=128 // +k8s:eachVal=+k8s:maxLength=256 VolumeContext map[string]string `protobuf:"bytes,5,rep,name=volume_context,json=volumeContext,proto3" json:"volume_context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // publish_context contains metadata returned by the CSI driver when the + // volume was attached to a node, which the node plugin needs to complete the + // mount (e.g. the device path for AWS EBS). It is empty for drivers that do + // not implement attachment, and is only meaningful for + // publish_context_node. Keys and values are the driver's own, so they are + // only bounded, not validated. + // + // +k8s:optional + // +k8s:maxProperties=32 + // +k8s:eachKey=+k8s:maxLength=128 + // +k8s:eachVal=+k8s:maxLength=256 + PublishContext map[string]string `protobuf:"bytes,6,rep,name=publish_context,json=publishContext,proto3" json:"publish_context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // publish_context_node is the node the volume was attached to when + // publish_context was captured. Attachment metadata is node-specific, so a + // publish_context recorded for a different node must not be reused. + // + // +k8s:optional + // +k8s:maxLength=253 + PublishContextNode string `protobuf:"bytes,7,opt,name=publish_context_node,json=publishContextNode,proto3" json:"publish_context_node,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ExternalVolume) Reset() { @@ -972,6 +991,20 @@ func (x *ExternalVolume) GetVolumeContext() map[string]string { return nil } +func (x *ExternalVolume) GetPublishContext() map[string]string { + if x != nil { + return x.PublishContext + } + return nil +} + +func (x *ExternalVolume) GetPublishContextNode() string { + if x != nil { + return x.PublishContextNode + } + return "" +} + type Actor struct { state protoimpl.MessageState `protogen:"open.v1"` // Common resource metadata: atespace, name, uid, version, timestamps. @@ -6985,7 +7018,7 @@ const file_ateapi_proto_rawDesc = "" + "\vcreate_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\n" + "createTime\x12;\n" + "\vupdate_time\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\n" + - "updateTime\"\xa8\x03\n" + + "updateTime\"\xf2\x04\n" + "\x0eExternalVolume\x12\x1f\n" + "\vvolume_name\x18\x01 \x01(\tR\n" + "volumeName\x12*\n" + @@ -6993,9 +7026,14 @@ const file_ateapi_proto_rawDesc = "" + "\vvolume_type\x18\x03 \x01(\tR\n" + "volumeType\x125\n" + "\x06status\x18\x04 \x01(\x0e2\x1d.ateapi.ExternalVolume.StatusR\x06status\x12P\n" + - "\x0evolume_context\x18\x05 \x03(\v2).ateapi.ExternalVolume.VolumeContextEntryR\rvolumeContext\x1a@\n" + + "\x0evolume_context\x18\x05 \x03(\v2).ateapi.ExternalVolume.VolumeContextEntryR\rvolumeContext\x12S\n" + + "\x0fpublish_context\x18\x06 \x03(\v2*.ateapi.ExternalVolume.PublishContextEntryR\x0epublishContext\x120\n" + + "\x14publish_context_node\x18\a \x01(\tR\x12publishContextNode\x1a@\n" + "\x12VolumeContextEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1aA\n" + + "\x13PublishContextEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"]\n" + "\x06Status\x12\x16\n" + "\x12STATUS_UNSPECIFIED\x10\x00\x12\x12\n" + @@ -7412,7 +7450,7 @@ func file_ateapi_proto_rawDescGZIP() []byte { } var file_ateapi_proto_enumTypes = make([]protoimpl.EnumInfo, 9) -var file_ateapi_proto_msgTypes = make([]protoimpl.MessageInfo, 101) +var file_ateapi_proto_msgTypes = make([]protoimpl.MessageInfo, 102) var file_ateapi_proto_goTypes = []any{ (SnapshotContentScope)(0), // 0: ateapi.SnapshotContentScope (TagScope)(0), // 1: ateapi.TagScope @@ -7523,212 +7561,214 @@ var file_ateapi_proto_goTypes = []any{ (*SetWorkerCapacityResponse)(nil), // 106: ateapi.SetWorkerCapacityResponse nil, // 107: ateapi.Selector.MatchLabelsEntry nil, // 108: ateapi.ExternalVolume.VolumeContextEntry - nil, // 109: ateapi.Worker.LabelsEntry - (*timestamppb.Timestamp)(nil), // 110: google.protobuf.Timestamp - (*emptypb.Empty)(nil), // 111: google.protobuf.Empty + nil, // 109: ateapi.ExternalVolume.PublishContextEntry + nil, // 110: ateapi.Worker.LabelsEntry + (*timestamppb.Timestamp)(nil), // 111: google.protobuf.Timestamp + (*emptypb.Empty)(nil), // 112: google.protobuf.Empty } var file_ateapi_proto_depIdxs = []int32{ 0, // 0: ateapi.ExternalSnapshot.content_scope:type_name -> ateapi.SnapshotContentScope 0, // 1: ateapi.LocalSnapshotInfo.content_scope:type_name -> ateapi.SnapshotContentScope 107, // 2: ateapi.Selector.match_labels:type_name -> ateapi.Selector.MatchLabelsEntry - 110, // 3: ateapi.ResourceMetadata.create_time:type_name -> google.protobuf.Timestamp - 110, // 4: ateapi.ResourceMetadata.update_time:type_name -> google.protobuf.Timestamp + 111, // 3: ateapi.ResourceMetadata.create_time:type_name -> google.protobuf.Timestamp + 111, // 4: ateapi.ResourceMetadata.update_time:type_name -> google.protobuf.Timestamp 8, // 5: ateapi.ExternalVolume.status:type_name -> ateapi.ExternalVolume.Status 108, // 6: ateapi.ExternalVolume.volume_context:type_name -> ateapi.ExternalVolume.VolumeContextEntry - 12, // 7: ateapi.Actor.metadata:type_name -> ateapi.ResourceMetadata - 26, // 8: ateapi.Actor.actor_template:type_name -> ateapi.ObjectRef - 11, // 9: ateapi.Actor.worker_selector:type_name -> ateapi.Selector - 26, // 10: ateapi.Actor.source_tag:type_name -> ateapi.ObjectRef - 21, // 11: ateapi.Actor.status:type_name -> ateapi.ActorStatus - 12, // 12: ateapi.EgressPolicy.metadata:type_name -> ateapi.ResourceMetadata - 16, // 13: ateapi.EgressPolicy.rules:type_name -> ateapi.EgressRule - 17, // 14: ateapi.EgressRule.hostnames:type_name -> ateapi.HostnameRule - 18, // 15: ateapi.EgressRule.cidrs:type_name -> ateapi.CIDRRule - 111, // 16: ateapi.EgressRule.all:type_name -> google.protobuf.Empty - 19, // 17: ateapi.HostnameRule.effects:type_name -> ateapi.EgressRuleEffects - 20, // 18: ateapi.EgressRuleEffects.inject_static_headers:type_name -> ateapi.CredentialHeaderInjection - 2, // 19: ateapi.ActorStatus.state:type_name -> ateapi.ActorState - 22, // 20: ateapi.ActorStatus.worker_assignment:type_name -> ateapi.WorkerAssignment - 9, // 21: ateapi.ActorStatus.external_snapshot:type_name -> ateapi.ExternalSnapshot - 10, // 22: ateapi.ActorStatus.local_snapshot_info:type_name -> ateapi.LocalSnapshotInfo - 13, // 23: ateapi.ActorStatus.actor_volumes:type_name -> ateapi.ExternalVolume - 26, // 24: ateapi.WorkerAssignment.worker:type_name -> ateapi.ObjectRef - 9, // 25: ateapi.TagStatus.snapshot:type_name -> ateapi.ExternalSnapshot - 12, // 26: ateapi.Tag.metadata:type_name -> ateapi.ResourceMetadata - 23, // 27: ateapi.Tag.status:type_name -> ateapi.TagStatus - 1, // 28: ateapi.Tag.scope:type_name -> ateapi.TagScope - 26, // 29: ateapi.Tag.source_actor:type_name -> ateapi.ObjectRef - 12, // 30: ateapi.Atespace.metadata:type_name -> ateapi.ResourceMetadata - 12, // 31: ateapi.ActorTemplate.metadata:type_name -> ateapi.ResourceMetadata - 11, // 32: ateapi.ActorTemplate.worker_selector:type_name -> ateapi.Selector - 35, // 33: ateapi.ActorTemplate.containers:type_name -> ateapi.Container - 41, // 34: ateapi.ActorTemplate.volumes:type_name -> ateapi.Volume - 33, // 35: ateapi.ActorTemplate.snapshots_config:type_name -> ateapi.SnapshotsConfig - 32, // 36: ateapi.ActorTemplate.sandbox_config:type_name -> ateapi.SandboxConfig - 28, // 37: ateapi.ActorTemplate.resources:type_name -> ateapi.Resources - 31, // 38: ateapi.ActorTemplate.status:type_name -> ateapi.ActorTemplateStatus - 29, // 39: ateapi.Resources.limits:type_name -> ateapi.Limits - 26, // 40: ateapi.GoldenSnapshotStatus.golden_tag:type_name -> ateapi.ObjectRef - 110, // 41: ateapi.GoldenSnapshotStatus.take_golden_snapshot_at:type_name -> google.protobuf.Timestamp - 30, // 42: ateapi.ActorTemplateStatus.golden_snapshot_status:type_name -> ateapi.GoldenSnapshotStatus - 3, // 43: ateapi.SandboxConfig.sandbox_class:type_name -> ateapi.SandboxClass - 0, // 44: ateapi.SnapshotsConfig.on_pause:type_name -> ateapi.SnapshotContentScope - 0, // 45: ateapi.SnapshotsConfig.on_commit:type_name -> ateapi.SnapshotContentScope - 34, // 46: ateapi.SnapshotsConfig.on_resume:type_name -> ateapi.OnResumeConfig - 4, // 47: ateapi.OnResumeConfig.from_data:type_name -> ateapi.ResumeSource - 38, // 48: ateapi.Container.env:type_name -> ateapi.EnvVar - 39, // 49: ateapi.Container.wakeup_probe:type_name -> ateapi.ContainerWakeupProbe - 50, // 50: ateapi.Container.volume_mounts:type_name -> ateapi.VolumeMount - 36, // 51: ateapi.Container.security_context:type_name -> ateapi.SecurityContext - 28, // 52: ateapi.Container.resources:type_name -> ateapi.Resources - 37, // 53: ateapi.SecurityContext.capabilities:type_name -> ateapi.Capabilities - 40, // 54: ateapi.ContainerWakeupProbe.http_get:type_name -> ateapi.HTTPGetAction - 43, // 55: ateapi.Volume.durable_dir:type_name -> ateapi.DurableDirVolumeSource - 44, // 56: ateapi.Volume.external_volume_template:type_name -> ateapi.ExternalVolumeTemplate - 45, // 57: ateapi.Volume.system_info:type_name -> ateapi.SystemInfoVolumeSource - 42, // 58: ateapi.Volume.image:type_name -> ateapi.ImageVolumeSource - 46, // 59: ateapi.SystemInfoVolumeSource.data_sources:type_name -> ateapi.SystemInfoDataSource - 47, // 60: ateapi.SystemInfoDataSource.actor_metadata:type_name -> ateapi.ActorMetadataDataSource - 49, // 61: ateapi.SystemInfoDataSource.trust_bundle:type_name -> ateapi.TrustBundleDataSource - 48, // 62: ateapi.ActorMetadataDataSource.items:type_name -> ateapi.ActorMetadataItem - 5, // 63: ateapi.ActorMetadataItem.field:type_name -> ateapi.ActorMetadataField - 25, // 64: ateapi.CreateAtespaceRequest.atespace:type_name -> ateapi.Atespace - 26, // 65: ateapi.GetAtespaceRequest.atespace:type_name -> ateapi.ObjectRef - 25, // 66: ateapi.ListAtespacesResponse.atespaces:type_name -> ateapi.Atespace - 26, // 67: ateapi.DeleteAtespaceRequest.atespace:type_name -> ateapi.ObjectRef - 27, // 68: ateapi.CreateActorTemplateRequest.actor_template:type_name -> ateapi.ActorTemplate - 26, // 69: ateapi.GetActorTemplateRequest.actor_template:type_name -> ateapi.ObjectRef - 27, // 70: ateapi.ListActorTemplatesResponse.actor_templates:type_name -> ateapi.ActorTemplate - 26, // 71: ateapi.DeleteActorTemplateRequest.actor_template:type_name -> ateapi.ObjectRef - 26, // 72: ateapi.GetActorRequest.actor:type_name -> ateapi.ObjectRef - 14, // 73: ateapi.CreateActorRequest.actor:type_name -> ateapi.Actor - 14, // 74: ateapi.UpdateActorRequest.actor:type_name -> ateapi.Actor - 26, // 75: ateapi.SuspendActorRequest.actor:type_name -> ateapi.ObjectRef - 14, // 76: ateapi.SuspendActorResponse.actor:type_name -> ateapi.Actor - 26, // 77: ateapi.PauseActorRequest.actor:type_name -> ateapi.ObjectRef - 14, // 78: ateapi.PauseActorResponse.actor:type_name -> ateapi.Actor - 26, // 79: ateapi.ResumeActorRequest.actor:type_name -> ateapi.ObjectRef - 14, // 80: ateapi.ResumeActorResponse.actor:type_name -> ateapi.Actor - 26, // 81: ateapi.RevertActorRequest.actor:type_name -> ateapi.ObjectRef - 14, // 82: ateapi.RevertActorResponse.actor:type_name -> ateapi.Actor - 26, // 83: ateapi.DeleteActorRequest.actor:type_name -> ateapi.ObjectRef - 26, // 84: ateapi.GetActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef - 26, // 85: ateapi.CreateActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef - 15, // 86: ateapi.CreateActorEgressPolicyRequest.egress_policy:type_name -> ateapi.EgressPolicy - 26, // 87: ateapi.UpdateActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef - 15, // 88: ateapi.UpdateActorEgressPolicyRequest.egress_policy:type_name -> ateapi.EgressPolicy - 26, // 89: ateapi.DeleteActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef - 26, // 90: ateapi.GetTagRequest.tag:type_name -> ateapi.ObjectRef - 26, // 91: ateapi.MintActorJWTRequest.actor:type_name -> ateapi.ObjectRef - 26, // 92: ateapi.MintActorCertificateRequest.actor:type_name -> ateapi.ObjectRef - 6, // 93: ateapi.MintActorCertificateRequest.purpose:type_name -> ateapi.ActorCertificatePurpose - 26, // 94: ateapi.GetActorSnapshotRequest.actor_snapshot:type_name -> ateapi.ObjectRef - 26, // 95: ateapi.GetActorSnapshotTagRequest.actor_snapshot_tag:type_name -> ateapi.ObjectRef - 24, // 96: ateapi.ListTagsResponse.tags:type_name -> ateapi.Tag - 24, // 97: ateapi.CreateTagRequest.tag:type_name -> ateapi.Tag - 24, // 98: ateapi.UpdateTagRequest.tag:type_name -> ateapi.Tag - 26, // 99: ateapi.DeleteTagRequest.tag:type_name -> ateapi.ObjectRef - 26, // 100: ateapi.ListWorkerActorAssignmentsRequest.worker:type_name -> ateapi.ObjectRef - 104, // 101: ateapi.ListWorkerActorAssignmentsResponse.actor_assignments:type_name -> ateapi.ActorAssignment - 101, // 102: ateapi.ListWorkersResponse.workers:type_name -> ateapi.Worker - 26, // 103: ateapi.GetWorkerRequest.worker:type_name -> ateapi.ObjectRef - 101, // 104: ateapi.CreateWorkerRequest.worker:type_name -> ateapi.Worker - 101, // 105: ateapi.UpdateWorkerRequest.worker:type_name -> ateapi.Worker - 26, // 106: ateapi.DeleteWorkerRequest.worker:type_name -> ateapi.ObjectRef - 89, // 107: ateapi.DeleteWorkerRequest.options:type_name -> ateapi.DeleteOptions - 26, // 108: ateapi.DrainWorkerRequest.worker:type_name -> ateapi.ObjectRef - 14, // 109: ateapi.ListActorsResponse.actors:type_name -> ateapi.Actor - 12, // 110: ateapi.Worker.metadata:type_name -> ateapi.ResourceMetadata - 109, // 111: ateapi.Worker.labels:type_name -> ateapi.Worker.LabelsEntry - 102, // 112: ateapi.Worker.status:type_name -> ateapi.WorkerStatus - 7, // 113: ateapi.WorkerStatus.state:type_name -> ateapi.WorkerState - 103, // 114: ateapi.WorkerStatus.capacity:type_name -> ateapi.WorkerResources - 103, // 115: ateapi.WorkerStatus.allocated:type_name -> ateapi.WorkerResources - 28, // 116: ateapi.WorkerResources.resources:type_name -> ateapi.Resources - 12, // 117: ateapi.ActorAssignment.metadata:type_name -> ateapi.ResourceMetadata - 26, // 118: ateapi.ActorAssignment.actor:type_name -> ateapi.ObjectRef - 26, // 119: ateapi.ActorAssignment.actor_template_ref:type_name -> ateapi.ObjectRef - 28, // 120: ateapi.ActorAssignment.resources:type_name -> ateapi.Resources - 26, // 121: ateapi.SetWorkerCapacityRequest.worker:type_name -> ateapi.ObjectRef - 103, // 122: ateapi.SetWorkerCapacityRequest.capacity:type_name -> ateapi.WorkerResources - 101, // 123: ateapi.SetWorkerCapacityResponse.worker:type_name -> ateapi.Worker - 61, // 124: ateapi.Control.GetActor:input_type -> ateapi.GetActorRequest - 62, // 125: ateapi.Control.CreateActor:input_type -> ateapi.CreateActorRequest - 63, // 126: ateapi.Control.UpdateActor:input_type -> ateapi.UpdateActorRequest - 64, // 127: ateapi.Control.SuspendActor:input_type -> ateapi.SuspendActorRequest - 66, // 128: ateapi.Control.PauseActor:input_type -> ateapi.PauseActorRequest - 68, // 129: ateapi.Control.ResumeActor:input_type -> ateapi.ResumeActorRequest - 70, // 130: ateapi.Control.RevertActor:input_type -> ateapi.RevertActorRequest - 72, // 131: ateapi.Control.DeleteActor:input_type -> ateapi.DeleteActorRequest - 73, // 132: ateapi.Control.GetActorEgressPolicy:input_type -> ateapi.GetActorEgressPolicyRequest - 74, // 133: ateapi.Control.CreateActorEgressPolicy:input_type -> ateapi.CreateActorEgressPolicyRequest - 75, // 134: ateapi.Control.UpdateActorEgressPolicy:input_type -> ateapi.UpdateActorEgressPolicyRequest - 76, // 135: ateapi.Control.DeleteActorEgressPolicy:input_type -> ateapi.DeleteActorEgressPolicyRequest - 78, // 136: ateapi.Control.MintActorJWT:input_type -> ateapi.MintActorJWTRequest - 80, // 137: ateapi.Control.MintActorCertificate:input_type -> ateapi.MintActorCertificateRequest - 86, // 138: ateapi.Control.CreateTag:input_type -> ateapi.CreateTagRequest - 77, // 139: ateapi.Control.GetTag:input_type -> ateapi.GetTagRequest - 84, // 140: ateapi.Control.ListTags:input_type -> ateapi.ListTagsRequest - 87, // 141: ateapi.Control.UpdateTag:input_type -> ateapi.UpdateTagRequest - 88, // 142: ateapi.Control.DeleteTag:input_type -> ateapi.DeleteTagRequest - 92, // 143: ateapi.Control.ListWorkers:input_type -> ateapi.ListWorkersRequest - 94, // 144: ateapi.Control.GetWorker:input_type -> ateapi.GetWorkerRequest - 95, // 145: ateapi.Control.CreateWorker:input_type -> ateapi.CreateWorkerRequest - 96, // 146: ateapi.Control.UpdateWorker:input_type -> ateapi.UpdateWorkerRequest - 97, // 147: ateapi.Control.DeleteWorker:input_type -> ateapi.DeleteWorkerRequest - 98, // 148: ateapi.Control.DrainWorker:input_type -> ateapi.DrainWorkerRequest - 90, // 149: ateapi.Control.ListWorkerActorAssignments:input_type -> ateapi.ListWorkerActorAssignmentsRequest - 99, // 150: ateapi.Control.ListActors:input_type -> ateapi.ListActorsRequest - 51, // 151: ateapi.Control.CreateAtespace:input_type -> ateapi.CreateAtespaceRequest - 52, // 152: ateapi.Control.GetAtespace:input_type -> ateapi.GetAtespaceRequest - 53, // 153: ateapi.Control.ListAtespaces:input_type -> ateapi.ListAtespacesRequest - 55, // 154: ateapi.Control.DeleteAtespace:input_type -> ateapi.DeleteAtespaceRequest - 56, // 155: ateapi.Control.CreateActorTemplate:input_type -> ateapi.CreateActorTemplateRequest - 57, // 156: ateapi.Control.GetActorTemplate:input_type -> ateapi.GetActorTemplateRequest - 58, // 157: ateapi.Control.ListActorTemplates:input_type -> ateapi.ListActorTemplatesRequest - 60, // 158: ateapi.Control.DeleteActorTemplate:input_type -> ateapi.DeleteActorTemplateRequest - 105, // 159: ateapi.WorkerService.SetWorkerCapacity:input_type -> ateapi.SetWorkerCapacityRequest - 14, // 160: ateapi.Control.GetActor:output_type -> ateapi.Actor - 14, // 161: ateapi.Control.CreateActor:output_type -> ateapi.Actor - 14, // 162: ateapi.Control.UpdateActor:output_type -> ateapi.Actor - 65, // 163: ateapi.Control.SuspendActor:output_type -> ateapi.SuspendActorResponse - 67, // 164: ateapi.Control.PauseActor:output_type -> ateapi.PauseActorResponse - 69, // 165: ateapi.Control.ResumeActor:output_type -> ateapi.ResumeActorResponse - 71, // 166: ateapi.Control.RevertActor:output_type -> ateapi.RevertActorResponse - 14, // 167: ateapi.Control.DeleteActor:output_type -> ateapi.Actor - 15, // 168: ateapi.Control.GetActorEgressPolicy:output_type -> ateapi.EgressPolicy - 15, // 169: ateapi.Control.CreateActorEgressPolicy:output_type -> ateapi.EgressPolicy - 15, // 170: ateapi.Control.UpdateActorEgressPolicy:output_type -> ateapi.EgressPolicy - 15, // 171: ateapi.Control.DeleteActorEgressPolicy:output_type -> ateapi.EgressPolicy - 79, // 172: ateapi.Control.MintActorJWT:output_type -> ateapi.MintActorJWTResponse - 81, // 173: ateapi.Control.MintActorCertificate:output_type -> ateapi.MintActorCertificateResponse - 24, // 174: ateapi.Control.CreateTag:output_type -> ateapi.Tag - 24, // 175: ateapi.Control.GetTag:output_type -> ateapi.Tag - 85, // 176: ateapi.Control.ListTags:output_type -> ateapi.ListTagsResponse - 24, // 177: ateapi.Control.UpdateTag:output_type -> ateapi.Tag - 24, // 178: ateapi.Control.DeleteTag:output_type -> ateapi.Tag - 93, // 179: ateapi.Control.ListWorkers:output_type -> ateapi.ListWorkersResponse - 101, // 180: ateapi.Control.GetWorker:output_type -> ateapi.Worker - 101, // 181: ateapi.Control.CreateWorker:output_type -> ateapi.Worker - 101, // 182: ateapi.Control.UpdateWorker:output_type -> ateapi.Worker - 101, // 183: ateapi.Control.DeleteWorker:output_type -> ateapi.Worker - 101, // 184: ateapi.Control.DrainWorker:output_type -> ateapi.Worker - 91, // 185: ateapi.Control.ListWorkerActorAssignments:output_type -> ateapi.ListWorkerActorAssignmentsResponse - 100, // 186: ateapi.Control.ListActors:output_type -> ateapi.ListActorsResponse - 25, // 187: ateapi.Control.CreateAtespace:output_type -> ateapi.Atespace - 25, // 188: ateapi.Control.GetAtespace:output_type -> ateapi.Atespace - 54, // 189: ateapi.Control.ListAtespaces:output_type -> ateapi.ListAtespacesResponse - 25, // 190: ateapi.Control.DeleteAtespace:output_type -> ateapi.Atespace - 27, // 191: ateapi.Control.CreateActorTemplate:output_type -> ateapi.ActorTemplate - 27, // 192: ateapi.Control.GetActorTemplate:output_type -> ateapi.ActorTemplate - 59, // 193: ateapi.Control.ListActorTemplates:output_type -> ateapi.ListActorTemplatesResponse - 27, // 194: ateapi.Control.DeleteActorTemplate:output_type -> ateapi.ActorTemplate - 106, // 195: ateapi.WorkerService.SetWorkerCapacity:output_type -> ateapi.SetWorkerCapacityResponse - 160, // [160:196] is the sub-list for method output_type - 124, // [124:160] is the sub-list for method input_type - 124, // [124:124] is the sub-list for extension type_name - 124, // [124:124] is the sub-list for extension extendee - 0, // [0:124] is the sub-list for field type_name + 109, // 7: ateapi.ExternalVolume.publish_context:type_name -> ateapi.ExternalVolume.PublishContextEntry + 12, // 8: ateapi.Actor.metadata:type_name -> ateapi.ResourceMetadata + 26, // 9: ateapi.Actor.actor_template:type_name -> ateapi.ObjectRef + 11, // 10: ateapi.Actor.worker_selector:type_name -> ateapi.Selector + 26, // 11: ateapi.Actor.source_tag:type_name -> ateapi.ObjectRef + 21, // 12: ateapi.Actor.status:type_name -> ateapi.ActorStatus + 12, // 13: ateapi.EgressPolicy.metadata:type_name -> ateapi.ResourceMetadata + 16, // 14: ateapi.EgressPolicy.rules:type_name -> ateapi.EgressRule + 17, // 15: ateapi.EgressRule.hostnames:type_name -> ateapi.HostnameRule + 18, // 16: ateapi.EgressRule.cidrs:type_name -> ateapi.CIDRRule + 112, // 17: ateapi.EgressRule.all:type_name -> google.protobuf.Empty + 19, // 18: ateapi.HostnameRule.effects:type_name -> ateapi.EgressRuleEffects + 20, // 19: ateapi.EgressRuleEffects.inject_static_headers:type_name -> ateapi.CredentialHeaderInjection + 2, // 20: ateapi.ActorStatus.state:type_name -> ateapi.ActorState + 22, // 21: ateapi.ActorStatus.worker_assignment:type_name -> ateapi.WorkerAssignment + 9, // 22: ateapi.ActorStatus.external_snapshot:type_name -> ateapi.ExternalSnapshot + 10, // 23: ateapi.ActorStatus.local_snapshot_info:type_name -> ateapi.LocalSnapshotInfo + 13, // 24: ateapi.ActorStatus.actor_volumes:type_name -> ateapi.ExternalVolume + 26, // 25: ateapi.WorkerAssignment.worker:type_name -> ateapi.ObjectRef + 9, // 26: ateapi.TagStatus.snapshot:type_name -> ateapi.ExternalSnapshot + 12, // 27: ateapi.Tag.metadata:type_name -> ateapi.ResourceMetadata + 23, // 28: ateapi.Tag.status:type_name -> ateapi.TagStatus + 1, // 29: ateapi.Tag.scope:type_name -> ateapi.TagScope + 26, // 30: ateapi.Tag.source_actor:type_name -> ateapi.ObjectRef + 12, // 31: ateapi.Atespace.metadata:type_name -> ateapi.ResourceMetadata + 12, // 32: ateapi.ActorTemplate.metadata:type_name -> ateapi.ResourceMetadata + 11, // 33: ateapi.ActorTemplate.worker_selector:type_name -> ateapi.Selector + 35, // 34: ateapi.ActorTemplate.containers:type_name -> ateapi.Container + 41, // 35: ateapi.ActorTemplate.volumes:type_name -> ateapi.Volume + 33, // 36: ateapi.ActorTemplate.snapshots_config:type_name -> ateapi.SnapshotsConfig + 32, // 37: ateapi.ActorTemplate.sandbox_config:type_name -> ateapi.SandboxConfig + 28, // 38: ateapi.ActorTemplate.resources:type_name -> ateapi.Resources + 31, // 39: ateapi.ActorTemplate.status:type_name -> ateapi.ActorTemplateStatus + 29, // 40: ateapi.Resources.limits:type_name -> ateapi.Limits + 26, // 41: ateapi.GoldenSnapshotStatus.golden_tag:type_name -> ateapi.ObjectRef + 111, // 42: ateapi.GoldenSnapshotStatus.take_golden_snapshot_at:type_name -> google.protobuf.Timestamp + 30, // 43: ateapi.ActorTemplateStatus.golden_snapshot_status:type_name -> ateapi.GoldenSnapshotStatus + 3, // 44: ateapi.SandboxConfig.sandbox_class:type_name -> ateapi.SandboxClass + 0, // 45: ateapi.SnapshotsConfig.on_pause:type_name -> ateapi.SnapshotContentScope + 0, // 46: ateapi.SnapshotsConfig.on_commit:type_name -> ateapi.SnapshotContentScope + 34, // 47: ateapi.SnapshotsConfig.on_resume:type_name -> ateapi.OnResumeConfig + 4, // 48: ateapi.OnResumeConfig.from_data:type_name -> ateapi.ResumeSource + 38, // 49: ateapi.Container.env:type_name -> ateapi.EnvVar + 39, // 50: ateapi.Container.wakeup_probe:type_name -> ateapi.ContainerWakeupProbe + 50, // 51: ateapi.Container.volume_mounts:type_name -> ateapi.VolumeMount + 36, // 52: ateapi.Container.security_context:type_name -> ateapi.SecurityContext + 28, // 53: ateapi.Container.resources:type_name -> ateapi.Resources + 37, // 54: ateapi.SecurityContext.capabilities:type_name -> ateapi.Capabilities + 40, // 55: ateapi.ContainerWakeupProbe.http_get:type_name -> ateapi.HTTPGetAction + 43, // 56: ateapi.Volume.durable_dir:type_name -> ateapi.DurableDirVolumeSource + 44, // 57: ateapi.Volume.external_volume_template:type_name -> ateapi.ExternalVolumeTemplate + 45, // 58: ateapi.Volume.system_info:type_name -> ateapi.SystemInfoVolumeSource + 42, // 59: ateapi.Volume.image:type_name -> ateapi.ImageVolumeSource + 46, // 60: ateapi.SystemInfoVolumeSource.data_sources:type_name -> ateapi.SystemInfoDataSource + 47, // 61: ateapi.SystemInfoDataSource.actor_metadata:type_name -> ateapi.ActorMetadataDataSource + 49, // 62: ateapi.SystemInfoDataSource.trust_bundle:type_name -> ateapi.TrustBundleDataSource + 48, // 63: ateapi.ActorMetadataDataSource.items:type_name -> ateapi.ActorMetadataItem + 5, // 64: ateapi.ActorMetadataItem.field:type_name -> ateapi.ActorMetadataField + 25, // 65: ateapi.CreateAtespaceRequest.atespace:type_name -> ateapi.Atespace + 26, // 66: ateapi.GetAtespaceRequest.atespace:type_name -> ateapi.ObjectRef + 25, // 67: ateapi.ListAtespacesResponse.atespaces:type_name -> ateapi.Atespace + 26, // 68: ateapi.DeleteAtespaceRequest.atespace:type_name -> ateapi.ObjectRef + 27, // 69: ateapi.CreateActorTemplateRequest.actor_template:type_name -> ateapi.ActorTemplate + 26, // 70: ateapi.GetActorTemplateRequest.actor_template:type_name -> ateapi.ObjectRef + 27, // 71: ateapi.ListActorTemplatesResponse.actor_templates:type_name -> ateapi.ActorTemplate + 26, // 72: ateapi.DeleteActorTemplateRequest.actor_template:type_name -> ateapi.ObjectRef + 26, // 73: ateapi.GetActorRequest.actor:type_name -> ateapi.ObjectRef + 14, // 74: ateapi.CreateActorRequest.actor:type_name -> ateapi.Actor + 14, // 75: ateapi.UpdateActorRequest.actor:type_name -> ateapi.Actor + 26, // 76: ateapi.SuspendActorRequest.actor:type_name -> ateapi.ObjectRef + 14, // 77: ateapi.SuspendActorResponse.actor:type_name -> ateapi.Actor + 26, // 78: ateapi.PauseActorRequest.actor:type_name -> ateapi.ObjectRef + 14, // 79: ateapi.PauseActorResponse.actor:type_name -> ateapi.Actor + 26, // 80: ateapi.ResumeActorRequest.actor:type_name -> ateapi.ObjectRef + 14, // 81: ateapi.ResumeActorResponse.actor:type_name -> ateapi.Actor + 26, // 82: ateapi.RevertActorRequest.actor:type_name -> ateapi.ObjectRef + 14, // 83: ateapi.RevertActorResponse.actor:type_name -> ateapi.Actor + 26, // 84: ateapi.DeleteActorRequest.actor:type_name -> ateapi.ObjectRef + 26, // 85: ateapi.GetActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef + 26, // 86: ateapi.CreateActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef + 15, // 87: ateapi.CreateActorEgressPolicyRequest.egress_policy:type_name -> ateapi.EgressPolicy + 26, // 88: ateapi.UpdateActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef + 15, // 89: ateapi.UpdateActorEgressPolicyRequest.egress_policy:type_name -> ateapi.EgressPolicy + 26, // 90: ateapi.DeleteActorEgressPolicyRequest.actor:type_name -> ateapi.ObjectRef + 26, // 91: ateapi.GetTagRequest.tag:type_name -> ateapi.ObjectRef + 26, // 92: ateapi.MintActorJWTRequest.actor:type_name -> ateapi.ObjectRef + 26, // 93: ateapi.MintActorCertificateRequest.actor:type_name -> ateapi.ObjectRef + 6, // 94: ateapi.MintActorCertificateRequest.purpose:type_name -> ateapi.ActorCertificatePurpose + 26, // 95: ateapi.GetActorSnapshotRequest.actor_snapshot:type_name -> ateapi.ObjectRef + 26, // 96: ateapi.GetActorSnapshotTagRequest.actor_snapshot_tag:type_name -> ateapi.ObjectRef + 24, // 97: ateapi.ListTagsResponse.tags:type_name -> ateapi.Tag + 24, // 98: ateapi.CreateTagRequest.tag:type_name -> ateapi.Tag + 24, // 99: ateapi.UpdateTagRequest.tag:type_name -> ateapi.Tag + 26, // 100: ateapi.DeleteTagRequest.tag:type_name -> ateapi.ObjectRef + 26, // 101: ateapi.ListWorkerActorAssignmentsRequest.worker:type_name -> ateapi.ObjectRef + 104, // 102: ateapi.ListWorkerActorAssignmentsResponse.actor_assignments:type_name -> ateapi.ActorAssignment + 101, // 103: ateapi.ListWorkersResponse.workers:type_name -> ateapi.Worker + 26, // 104: ateapi.GetWorkerRequest.worker:type_name -> ateapi.ObjectRef + 101, // 105: ateapi.CreateWorkerRequest.worker:type_name -> ateapi.Worker + 101, // 106: ateapi.UpdateWorkerRequest.worker:type_name -> ateapi.Worker + 26, // 107: ateapi.DeleteWorkerRequest.worker:type_name -> ateapi.ObjectRef + 89, // 108: ateapi.DeleteWorkerRequest.options:type_name -> ateapi.DeleteOptions + 26, // 109: ateapi.DrainWorkerRequest.worker:type_name -> ateapi.ObjectRef + 14, // 110: ateapi.ListActorsResponse.actors:type_name -> ateapi.Actor + 12, // 111: ateapi.Worker.metadata:type_name -> ateapi.ResourceMetadata + 110, // 112: ateapi.Worker.labels:type_name -> ateapi.Worker.LabelsEntry + 102, // 113: ateapi.Worker.status:type_name -> ateapi.WorkerStatus + 7, // 114: ateapi.WorkerStatus.state:type_name -> ateapi.WorkerState + 103, // 115: ateapi.WorkerStatus.capacity:type_name -> ateapi.WorkerResources + 103, // 116: ateapi.WorkerStatus.allocated:type_name -> ateapi.WorkerResources + 28, // 117: ateapi.WorkerResources.resources:type_name -> ateapi.Resources + 12, // 118: ateapi.ActorAssignment.metadata:type_name -> ateapi.ResourceMetadata + 26, // 119: ateapi.ActorAssignment.actor:type_name -> ateapi.ObjectRef + 26, // 120: ateapi.ActorAssignment.actor_template_ref:type_name -> ateapi.ObjectRef + 28, // 121: ateapi.ActorAssignment.resources:type_name -> ateapi.Resources + 26, // 122: ateapi.SetWorkerCapacityRequest.worker:type_name -> ateapi.ObjectRef + 103, // 123: ateapi.SetWorkerCapacityRequest.capacity:type_name -> ateapi.WorkerResources + 101, // 124: ateapi.SetWorkerCapacityResponse.worker:type_name -> ateapi.Worker + 61, // 125: ateapi.Control.GetActor:input_type -> ateapi.GetActorRequest + 62, // 126: ateapi.Control.CreateActor:input_type -> ateapi.CreateActorRequest + 63, // 127: ateapi.Control.UpdateActor:input_type -> ateapi.UpdateActorRequest + 64, // 128: ateapi.Control.SuspendActor:input_type -> ateapi.SuspendActorRequest + 66, // 129: ateapi.Control.PauseActor:input_type -> ateapi.PauseActorRequest + 68, // 130: ateapi.Control.ResumeActor:input_type -> ateapi.ResumeActorRequest + 70, // 131: ateapi.Control.RevertActor:input_type -> ateapi.RevertActorRequest + 72, // 132: ateapi.Control.DeleteActor:input_type -> ateapi.DeleteActorRequest + 73, // 133: ateapi.Control.GetActorEgressPolicy:input_type -> ateapi.GetActorEgressPolicyRequest + 74, // 134: ateapi.Control.CreateActorEgressPolicy:input_type -> ateapi.CreateActorEgressPolicyRequest + 75, // 135: ateapi.Control.UpdateActorEgressPolicy:input_type -> ateapi.UpdateActorEgressPolicyRequest + 76, // 136: ateapi.Control.DeleteActorEgressPolicy:input_type -> ateapi.DeleteActorEgressPolicyRequest + 78, // 137: ateapi.Control.MintActorJWT:input_type -> ateapi.MintActorJWTRequest + 80, // 138: ateapi.Control.MintActorCertificate:input_type -> ateapi.MintActorCertificateRequest + 86, // 139: ateapi.Control.CreateTag:input_type -> ateapi.CreateTagRequest + 77, // 140: ateapi.Control.GetTag:input_type -> ateapi.GetTagRequest + 84, // 141: ateapi.Control.ListTags:input_type -> ateapi.ListTagsRequest + 87, // 142: ateapi.Control.UpdateTag:input_type -> ateapi.UpdateTagRequest + 88, // 143: ateapi.Control.DeleteTag:input_type -> ateapi.DeleteTagRequest + 92, // 144: ateapi.Control.ListWorkers:input_type -> ateapi.ListWorkersRequest + 94, // 145: ateapi.Control.GetWorker:input_type -> ateapi.GetWorkerRequest + 95, // 146: ateapi.Control.CreateWorker:input_type -> ateapi.CreateWorkerRequest + 96, // 147: ateapi.Control.UpdateWorker:input_type -> ateapi.UpdateWorkerRequest + 97, // 148: ateapi.Control.DeleteWorker:input_type -> ateapi.DeleteWorkerRequest + 98, // 149: ateapi.Control.DrainWorker:input_type -> ateapi.DrainWorkerRequest + 90, // 150: ateapi.Control.ListWorkerActorAssignments:input_type -> ateapi.ListWorkerActorAssignmentsRequest + 99, // 151: ateapi.Control.ListActors:input_type -> ateapi.ListActorsRequest + 51, // 152: ateapi.Control.CreateAtespace:input_type -> ateapi.CreateAtespaceRequest + 52, // 153: ateapi.Control.GetAtespace:input_type -> ateapi.GetAtespaceRequest + 53, // 154: ateapi.Control.ListAtespaces:input_type -> ateapi.ListAtespacesRequest + 55, // 155: ateapi.Control.DeleteAtespace:input_type -> ateapi.DeleteAtespaceRequest + 56, // 156: ateapi.Control.CreateActorTemplate:input_type -> ateapi.CreateActorTemplateRequest + 57, // 157: ateapi.Control.GetActorTemplate:input_type -> ateapi.GetActorTemplateRequest + 58, // 158: ateapi.Control.ListActorTemplates:input_type -> ateapi.ListActorTemplatesRequest + 60, // 159: ateapi.Control.DeleteActorTemplate:input_type -> ateapi.DeleteActorTemplateRequest + 105, // 160: ateapi.WorkerService.SetWorkerCapacity:input_type -> ateapi.SetWorkerCapacityRequest + 14, // 161: ateapi.Control.GetActor:output_type -> ateapi.Actor + 14, // 162: ateapi.Control.CreateActor:output_type -> ateapi.Actor + 14, // 163: ateapi.Control.UpdateActor:output_type -> ateapi.Actor + 65, // 164: ateapi.Control.SuspendActor:output_type -> ateapi.SuspendActorResponse + 67, // 165: ateapi.Control.PauseActor:output_type -> ateapi.PauseActorResponse + 69, // 166: ateapi.Control.ResumeActor:output_type -> ateapi.ResumeActorResponse + 71, // 167: ateapi.Control.RevertActor:output_type -> ateapi.RevertActorResponse + 14, // 168: ateapi.Control.DeleteActor:output_type -> ateapi.Actor + 15, // 169: ateapi.Control.GetActorEgressPolicy:output_type -> ateapi.EgressPolicy + 15, // 170: ateapi.Control.CreateActorEgressPolicy:output_type -> ateapi.EgressPolicy + 15, // 171: ateapi.Control.UpdateActorEgressPolicy:output_type -> ateapi.EgressPolicy + 15, // 172: ateapi.Control.DeleteActorEgressPolicy:output_type -> ateapi.EgressPolicy + 79, // 173: ateapi.Control.MintActorJWT:output_type -> ateapi.MintActorJWTResponse + 81, // 174: ateapi.Control.MintActorCertificate:output_type -> ateapi.MintActorCertificateResponse + 24, // 175: ateapi.Control.CreateTag:output_type -> ateapi.Tag + 24, // 176: ateapi.Control.GetTag:output_type -> ateapi.Tag + 85, // 177: ateapi.Control.ListTags:output_type -> ateapi.ListTagsResponse + 24, // 178: ateapi.Control.UpdateTag:output_type -> ateapi.Tag + 24, // 179: ateapi.Control.DeleteTag:output_type -> ateapi.Tag + 93, // 180: ateapi.Control.ListWorkers:output_type -> ateapi.ListWorkersResponse + 101, // 181: ateapi.Control.GetWorker:output_type -> ateapi.Worker + 101, // 182: ateapi.Control.CreateWorker:output_type -> ateapi.Worker + 101, // 183: ateapi.Control.UpdateWorker:output_type -> ateapi.Worker + 101, // 184: ateapi.Control.DeleteWorker:output_type -> ateapi.Worker + 101, // 185: ateapi.Control.DrainWorker:output_type -> ateapi.Worker + 91, // 186: ateapi.Control.ListWorkerActorAssignments:output_type -> ateapi.ListWorkerActorAssignmentsResponse + 100, // 187: ateapi.Control.ListActors:output_type -> ateapi.ListActorsResponse + 25, // 188: ateapi.Control.CreateAtespace:output_type -> ateapi.Atespace + 25, // 189: ateapi.Control.GetAtespace:output_type -> ateapi.Atespace + 54, // 190: ateapi.Control.ListAtespaces:output_type -> ateapi.ListAtespacesResponse + 25, // 191: ateapi.Control.DeleteAtespace:output_type -> ateapi.Atespace + 27, // 192: ateapi.Control.CreateActorTemplate:output_type -> ateapi.ActorTemplate + 27, // 193: ateapi.Control.GetActorTemplate:output_type -> ateapi.ActorTemplate + 59, // 194: ateapi.Control.ListActorTemplates:output_type -> ateapi.ListActorTemplatesResponse + 27, // 195: ateapi.Control.DeleteActorTemplate:output_type -> ateapi.ActorTemplate + 106, // 196: ateapi.WorkerService.SetWorkerCapacity:output_type -> ateapi.SetWorkerCapacityResponse + 161, // [161:197] is the sub-list for method output_type + 125, // [125:161] is the sub-list for method input_type + 125, // [125:125] is the sub-list for extension type_name + 125, // [125:125] is the sub-list for extension extendee + 0, // [0:125] is the sub-list for field type_name } func init() { file_ateapi_proto_init() } @@ -7742,7 +7782,7 @@ func file_ateapi_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_ateapi_proto_rawDesc), len(file_ateapi_proto_rawDesc)), NumEnums: 9, - NumMessages: 101, + NumMessages: 102, NumExtensions: 0, NumServices: 2, }, diff --git a/pkg/proto/ateapipb/ateapi.proto b/pkg/proto/ateapipb/ateapi.proto index 1b5935cd67..e21765a2d1 100644 --- a/pkg/proto/ateapipb/ateapi.proto +++ b/pkg/proto/ateapipb/ateapi.proto @@ -347,6 +347,27 @@ message ExternalVolume { // +k8s:eachKey=+k8s:maxLength=128 // +k8s:eachVal=+k8s:maxLength=256 map volume_context = 5; + + // publish_context contains metadata returned by the CSI driver when the + // volume was attached to a node, which the node plugin needs to complete the + // mount (e.g. the device path for AWS EBS). It is empty for drivers that do + // not implement attachment, and is only meaningful for + // publish_context_node. Keys and values are the driver's own, so they are + // only bounded, not validated. + // + // +k8s:optional + // +k8s:maxProperties=32 + // +k8s:eachKey=+k8s:maxLength=128 + // +k8s:eachVal=+k8s:maxLength=256 + map publish_context = 6; + + // publish_context_node is the node the volume was attached to when + // publish_context was captured. Attachment metadata is node-specific, so a + // publish_context recorded for a different node must not be reused. + // + // +k8s:optional + // +k8s:maxLength=253 + string publish_context_node = 7; } message Actor {