Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1,687 changes: 1,042 additions & 645 deletions api/ateapi/v1/ateapi.pb.go

Large diffs are not rendered by default.

107 changes: 107 additions & 0 deletions api/ateapi/v1/ateapi.proto
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,28 @@ 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";
}

rpc CreateActorTemplate(CreateActorTemplateRequest) returns (ActorTemplate) {
option (method).resource = "ActorTemplate";
}
Expand Down Expand Up @@ -1561,6 +1583,40 @@ message ExternalVolumeTemplate {
string storage_class_name = 2;
}

// 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;
}

// SystemInfoVolumeSource is a read-only volume of substrate-generated
// per-actor files (identity fields, projected trust bundles), regenerated by
// atelet on every Run/Restore.
Expand Down Expand Up @@ -1719,6 +1775,57 @@ 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;
}

message CreateActorTemplateRequest {
// The actor template version to create. Server-assigned metadata (uid,
// version, timestamps) is ignored, as are the status fields.
Expand Down
164 changes: 164 additions & 0 deletions api/ateapi/v1/ateapi_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions cmd/ateapi/internal/apivalidation/external_volume_class.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2026 The Agent Substrate Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package apivalidation

import (
"context"

"go.ate.dev/substrate/api/ateapi/v1"
"go.ate.dev/substrate/internal/resources"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/util/validation/field"
)

func ValidateCreateExternalVolumeClassRequest(ctx context.Context, req *ateapi.CreateExternalVolumeClassRequest) field.ErrorList {
return Validate_CreateExternalVolumeClassRequest(ctx, MakeCreateOp(ctx), nil, req, nil)
}

func ValidateGetExternalVolumeClassRequest(ctx context.Context, req *ateapi.GetExternalVolumeClassRequest) field.ErrorList {
return Validate_GetExternalVolumeClassRequest(ctx, MakeCreateOp(ctx), nil, req, nil)
}

func ValidateListExternalVolumeClassesRequest(ctx context.Context, req *ateapi.ListExternalVolumeClassesRequest) field.ErrorList {
return Validate_ListExternalVolumeClassesRequest(ctx, MakeCreateOp(ctx), nil, req, nil)
}

func ValidateDeleteExternalVolumeClassRequest(ctx context.Context, req *ateapi.DeleteExternalVolumeClassRequest) field.ErrorList {
return Validate_DeleteExternalVolumeClassRequest(ctx, MakeCreateOp(ctx), nil, req, nil)
}

func ValidateCustom_ExternalVolumeClass_DriverName(_ context.Context, _ operation.Operation, fldPath *field.Path, value, _ *string) field.ErrorList {
return resources.ValidateVolumeType(fldPath, *value)
}
Loading
Loading