Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6d9c742
add global-scoped ExternalVolumeClass message in ateapi.proto,
lekhoavu2909 Nov 6, 2026
5fcea16
add sql migration on store.Interface and atepg.Persistence, unittest,
lekhoavu2909 Nov 6, 2026
ac15cf9
add EVC CRUD, delete precondition, pruning tests, EVC to atepg test
lekhoavu2909 Nov 6, 2026
60152ee
add Substrate Authors headers
lekhoavu2909 Nov 9, 2026
722a190
openFGA model, contextual tuples and authz helpers
lekhoavu2909 Nov 9, 2026
5f005db
ExternalVolumeClass CRUD RPCs, validation, RPC permission registry and
lekhoavu2909 Nov 9, 2026
32dddc1
resource model and authorization docs
lekhoavu2909 Nov 9, 2026
5a58f85
RPCService and ServiceImpl handlers and serviceStore interface
lekhoavu2909 Nov 9, 2026
1594d1f
functionaltest CRUD, precondition, preview-gate and validation tests
lekhoavu2909 Nov 9, 2026
f60f6a6
ExternalVolumeTemplate field, union validation, and validation tests
lekhoavu2909 Nov 10, 2026
09b5583
volume resolver, provisioning wiring, and unit+functional tests
lekhoavu2909 Nov 10, 2026
33d6e7f
ExternalVolumeClass printer and unit tests
lekhoavu2909 Nov 10, 2026
8de3dcc
kubectl-ate get/create/delete commands and unit tests
lekhoavu2909 Nov 10, 2026
5c0456a
CLI reference documentation
lekhoavu2909 Nov 10, 2026
472a0cf
proto, validation & apitool
lekhoavu2909 Nov 11, 2026
f8dc4ac
migration, stoe, atepg, defaults and controlapi
lekhoavu2909 Nov 11, 2026
f8cf6c0
store contract and Postgres tamper/concurrency tests
lekhoavu2909 Nov 11, 2026
b94e64d
openfga model, contextual tuple and authz helpers
lekhoavu2909 Nov 11, 2026
1d1076f
control rpcs, request/update validation, permission registry and apitool
lekhoavu2909 Nov 11, 2026
ec9d915
resource model and authorization
lekhoavu2909 Nov 11, 2026
8bc000d
add RPCService and ServiceImpl handlers + methods on serviceStore
lekhoavu2909 Nov 11, 2026
56075f9
add CsiDriverConfig printer and unit tests
lekhoavu2909 Nov 12, 2026
dffc3e9
add kubectl-ate get/create/update/delete csi-driver-config commands a…
lekhoavu2909 Nov 12, 2026
7e65017
cli reference docs
lekhoavu2909 Nov 12, 2026
02ee4ef
switch to ateapi.CsiDriverConfig, add close functions and update
lekhoavu2909 Nov 12, 2026
10deef8
switch RPCService.GetPlugin to Postgres CsiDriverConfig lookup with unit
lekhoavu2909 Nov 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,319 changes: 1,652 additions & 667 deletions api/ateapi/v1/ateapi.pb.go

Large diffs are not rendered by default.

291 changes: 289 additions & 2 deletions api/ateapi/v1/ateapi.proto
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,54 @@ service Control {
option (method).resource = "Atespace";
}

// Create an ExternalVolumeClass.
rpc CreateExternalVolumeClass(CreateExternalVolumeClassRequest) returns (ExternalVolumeClass) {
option (method).resource = "ExternalVolumeClass";
}

// Get an ExternalVolumeClass by name.
rpc GetExternalVolumeClass(GetExternalVolumeClassRequest) returns (ExternalVolumeClass) {
option (method).resource = "ExternalVolumeClass";
}

// List ExternalVolumeClasses.
rpc ListExternalVolumeClasses(ListExternalVolumeClassesRequest) returns (ListExternalVolumeClassesResponse) {
option (method).resource = "ExternalVolumeClass";
}

// Delete an ExternalVolumeClass. Delete does not check for ActorTemplates
// that still reference the class. Volumes from those templates then fail to
// provision.
rpc DeleteExternalVolumeClass(DeleteExternalVolumeClassRequest) returns (ExternalVolumeClass) {
option (method).resource = "ExternalVolumeClass";
}

// Create a CsiDriverConfig.
rpc CreateCsiDriverConfig(CreateCsiDriverConfigRequest) returns (CsiDriverConfig) {
option (method).resource = "CsiDriverConfig";
}

// Get a CsiDriverConfig by name.
rpc GetCsiDriverConfig(GetCsiDriverConfigRequest) returns (CsiDriverConfig) {
option (method).resource = "CsiDriverConfig";
}

// List CsiDriverConfigs.
rpc ListCsiDriverConfigs(ListCsiDriverConfigsRequest) returns (ListCsiDriverConfigsResponse) {
option (method).resource = "CsiDriverConfig";
}

// Update a CsiDriverConfig.
rpc UpdateCsiDriverConfig(UpdateCsiDriverConfigRequest) returns (CsiDriverConfig) {
option (method).resource = "CsiDriverConfig";
}

// Delete a CsiDriverConfig. Rejects (FailedPrecondition) if an
// ExternalVolumeClass still references its driver_name.
rpc DeleteCsiDriverConfig(DeleteCsiDriverConfigRequest) returns (CsiDriverConfig) {
option (method).resource = "CsiDriverConfig";
}

rpc CreateActorTemplate(CreateActorTemplateRequest) returns (ActorTemplate) {
option (method).resource = "ActorTemplate";
}
Expand Down Expand Up @@ -1554,11 +1602,128 @@ message ExternalVolumeTemplate {
int64 capacity_bytes = 1;

// storage_class_name names the cluster-scoped Kubernetes StorageClass to
// create the volume from. Required.
// create the volume from. Prefer external_volume_class.
//
// +k8s:required
// Exactly one of storage_class_name and external_volume_class must be set.
//
// +k8s:optional
// +k8s:unionMember
// +k8s:format=k8s-long-name
string storage_class_name = 2;

// external_volume_class names the ExternalVolumeClass to create the volume
// from. atespace must be empty.
//
// +k8s:optional
// +k8s:unionMember
// +k8s:beta(since: "0.0")=+k8s:subfield(atespace)=+k8s:forbidden # TODO: get rid of beta prefix
ObjectRef external_volume_class = 3;
}

// ExternalVolumeClass names the CSI driver that provisions external volumes
// and the parameters for its CreateVolume call. Global-scoped and immutable:
// metadata.atespace must be empty.
message ExternalVolumeClass {
option (resource) = {
scope : SCOPE_GLOBAL
plural : "ExternalVolumeClasses"
};

// Common resource metadata: name, uid, version, timestamps.
//
// +k8s:required
// +k8s:beta(since: "0.0")=+k8s:subfield(atespace)=+k8s:forbidden # TODO: get rid of beta prefix
ResourceMetadata metadata = 1;

// driver_name is the CSI driver that provisions the volumes, e.g.
// "nfs.csi.k8s.io". It is a DNS subdomain, optionally prefixed with
// "substrate.io/".
//
// +k8s:required
// +k8s:maxLength=63
// +k8s:customValidation # optional "substrate.io/" prefix + DNS-1123 subdomain
string driver_name = 2;

// parameters are passed unchanged to the driver's CreateVolume call. The
// driver defines their keys and values, so they are only bounded in size.
//
// +k8s:optional
// +k8s:maxProperties=32
// +k8s:eachKey=+k8s:maxLength=128
// +k8s:eachVal=+k8s:maxLength=256
map<string, string> parameters = 3;
}

// CsiDriverConfig configures how the control plane and worker nodes connect to
// a CSI driver. Global-scoped: metadata.atespace must be empty.
message CsiDriverConfig {
option (resource) = {
scope : SCOPE_GLOBAL
plural : "CsiDriverConfigs"
};

// Common resource metadata: name, uid, version, timestamps.
//
// +k8s:required
// +k8s:beta(since: "0.0")=+k8s:subfield(atespace)=+k8s:forbidden # TODO: get rid of beta prefix
ResourceMetadata metadata = 1;

// driver_name is the CSI driver name, e.g. "nfs.csi.k8s.io". It is a DNS
// subdomain, optionally prefixed with "substrate.io/", and is unique across
// all CsiDriverConfigs.
//
// +k8s:required
// +k8s:maxLength=63
// +k8s:immutable
// +k8s:customValidation # optional "substrate.io/" prefix + DNS-1123 subdomain
string driver_name = 2;

// controller_endpoint is the gRPC URI of the CSI Controller service, e.g.
// "dns:///csi-service:9000" or "tcp://127.0.0.1:9000".
//
// +k8s:required
// +k8s:maxLength=1024
// +k8s:customValidation # tcp://host:port or dns://[authority]/host:port
string controller_endpoint = 3;

// node_socket_override overrides the Unix domain socket URI for the CSI Node
// service on worker nodes. When empty, worker nodes connect to
// `unix:///var/lib/kubelet/plugins/<driver_name>/csi.sock`.
//
// +k8s:optional
// +k8s:maxLength=1024
// +k8s:customValidation # unix:// followed by a clean absolute path
string node_socket_override = 4;

// tls configures TLS for connections to controller_endpoint.
//
// +k8s:optional
CsiDriverTlsConfig tls = 5;
}

// CsiDriverTlsConfig configures TLS for CSI controller gRPC connections.
//
// +k8s:customValidation # enabled requires use_pod_identity and server_name; disabled forbids both
message CsiDriverTlsConfig {
// enabled turns on TLS for controller_endpoint connections.
//
// +k8s:optional
bool enabled = 1;

// use_pod_identity authenticates the client with Substrate pod identity
// certificates. Must be true when enabled is true, and must not be set when
// enabled is false.
//
// +k8s:optional
bool use_pod_identity = 2;

// server_name is the expected TLS server name on the controller certificate.
// Required when enabled is true, and must not be set when enabled is false.
//
// +k8s:optional
// +k8s:format=k8s-long-name
// +k8s:maxLength=253
string server_name = 3;
}

// SystemInfoVolumeSource is a read-only volume of substrate-generated
Expand Down Expand Up @@ -1719,6 +1884,128 @@ message DeleteAtespaceRequest {
DeleteOptions options = 2;
}

// CreateExternalVolumeClassRequest creates an ExternalVolumeClass.
message CreateExternalVolumeClassRequest {
// The class to create. metadata.name is required and metadata.atespace
// must be empty.
//
// +ate:preview=ExternalVolumes
// +k8s:ifDisabled(ExternalVolumes)=+k8s:forbidden
// +k8s:required
ExternalVolumeClass external_volume_class = 1;
}

// GetExternalVolumeClassRequest identifies the ExternalVolumeClass to get.
message GetExternalVolumeClassRequest {
// The class to get. atespace must be empty.
//
// +k8s:required
// +k8s:beta(since: "0.0")=+k8s:subfield(atespace)=+k8s:forbidden # TODO: get rid of beta prefix
ObjectRef external_volume_class = 1;
}

// ListExternalVolumeClassesRequest asks for a page of ExternalVolumeClasses.
message ListExternalVolumeClassesRequest {
// Pagination controls.
//
// +k8s:optional
ListOptions options = 1;
}

// ListExternalVolumeClassesResponse is one page of ExternalVolumeClasses.
message ListExternalVolumeClassesResponse {
// The page of classes. This list may be empty even if there are more results.
repeated ExternalVolumeClass external_volume_classes = 1;

// Pagination token for the next page. Empty if this is the last page.
string next_page_token = 2;
}

// DeleteExternalVolumeClassRequest identifies the ExternalVolumeClass to delete.
message DeleteExternalVolumeClassRequest {
// The class to delete. atespace must be empty.
//
// +k8s:required
// +k8s:beta(since: "0.0")=+k8s:subfield(atespace)=+k8s:forbidden # TODO: get rid of beta prefix
ObjectRef external_volume_class = 1;

// Optional per-delete preconditions.
//
// +k8s:optional
DeleteOptions options = 2;
}

// CreateCsiDriverConfigRequest creates a CsiDriverConfig.
message CreateCsiDriverConfigRequest {
// The config to create. metadata.name is required and metadata.atespace
// must be empty.
//
// +ate:preview=ExternalVolumes
// +k8s:ifDisabled(ExternalVolumes)=+k8s:forbidden
// +k8s:required
CsiDriverConfig csi_driver_config = 1;
}

// GetCsiDriverConfigRequest identifies the CsiDriverConfig to get.
message GetCsiDriverConfigRequest {
// The config to get. atespace must be empty.
//
// +k8s:required
// +k8s:beta(since: "0.0")=+k8s:subfield(atespace)=+k8s:forbidden # TODO: get rid of beta prefix
ObjectRef csi_driver_config = 1;
}

// ListCsiDriverConfigsRequest asks for a page of CsiDriverConfigs.
message ListCsiDriverConfigsRequest {
// Pagination controls.
//
// +k8s:optional
ListOptions options = 1;
}

// ListCsiDriverConfigsResponse is one page of CsiDriverConfigs.
message ListCsiDriverConfigsResponse {
// The page of configs. This list may be empty even if there are more results.
repeated CsiDriverConfig csi_driver_configs = 1;

// Pagination token for the next page. Empty if this is the last page.
string next_page_token = 2;
}

// UpdateCsiDriverConfigRequest updates a CsiDriverConfig.
message UpdateCsiDriverConfigRequest {
// The config to update. csi_driver_config.metadata.name identifies which
// resource to update, and metadata.atespace must be empty.
// csi_driver_config.metadata.uid and csi_driver_config.metadata.version are
// required preconditions.
//
// controller_endpoint, node_socket_override, and tls are replaced with what
// the request carries, and any omitted optional field is cleared.
// driver_name is immutable.
//
// +ate:preview=ExternalVolumes
// +k8s:ifDisabled(ExternalVolumes)=+k8s:forbidden
// +k8s:required
// +k8s:opaqueType # updates are handled in 2 steps, do not descend
// +k8s:subfield(metadata)=+k8s:required
// +k8s:customValidation # TODO: when we get nested subfields, forbid metadata.atespace
CsiDriverConfig csi_driver_config = 1;
}

// DeleteCsiDriverConfigRequest identifies the CsiDriverConfig to delete.
message DeleteCsiDriverConfigRequest {
// The config to delete. atespace must be empty.
//
// +k8s:required
// +k8s:beta(since: "0.0")=+k8s:subfield(atespace)=+k8s:forbidden # TODO: get rid of beta prefix
ObjectRef csi_driver_config = 1;

// Optional per-delete preconditions.
//
// +k8s:optional
DeleteOptions options = 2;
}

message CreateActorTemplateRequest {
// The actor template version to create. Server-assigned metadata (uid,
// version, timestamps) is ignored, as are the status fields.
Expand Down
Loading
Loading