diff --git a/controller/api/v1alpha1/lease_helpers.go b/controller/api/v1alpha1/lease_helpers.go index 5f371c370..a96058dc8 100644 --- a/controller/api/v1alpha1/lease_helpers.go +++ b/controller/api/v1alpha1/lease_helpers.go @@ -323,6 +323,9 @@ func (l *Lease) ToProtobuf() *cpb.Lease { Name: l.Status.ExporterRef.Name, })) } + if alias, ok := l.Labels[string(LeaseLabelName)]; ok { + lease.Alias = ptr.To(alias) + } return &lease } diff --git a/controller/api/v1alpha1/lease_helpers_test.go b/controller/api/v1alpha1/lease_helpers_test.go index 8d0e28445..cc91f63a4 100644 --- a/controller/api/v1alpha1/lease_helpers_test.go +++ b/controller/api/v1alpha1/lease_helpers_test.go @@ -574,4 +574,44 @@ var _ = Describe("Lease.ToProtobuf", func() { Expect(pb.Tags).To(BeEmpty()) }) + + It("should populate alias from lease-name label", func() { + lease := &Lease{ + ObjectMeta: metav1.ObjectMeta{ + Name: "demo-x7k2q", + Namespace: "default", + Labels: map[string]string{ + string(LeaseLabelName): "demo", + }, + }, + Spec: LeaseSpec{ + ClientRef: corev1.LocalObjectReference{Name: "test-client"}, + Duration: &metav1.Duration{Duration: time.Hour}, + Selector: metav1.LabelSelector{MatchLabels: map[string]string{"board": "rpi4"}}, + }, + } + + pb := lease.ToProtobuf() + + Expect(pb.Alias).NotTo(BeNil()) + Expect(*pb.Alias).To(Equal("demo")) + }) + + It("should not set alias when lease-name label is absent", func() { + lease := &Lease{ + ObjectMeta: metav1.ObjectMeta{ + Name: "lease-m9p3r", + Namespace: "default", + }, + Spec: LeaseSpec{ + ClientRef: corev1.LocalObjectReference{Name: "test-client"}, + Duration: &metav1.Duration{Duration: time.Hour}, + Selector: metav1.LabelSelector{MatchLabels: map[string]string{"board": "rpi4"}}, + }, + } + + pb := lease.ToProtobuf() + + Expect(pb.Alias).To(BeNil()) + }) }) diff --git a/controller/api/v1alpha1/lease_types.go b/controller/api/v1alpha1/lease_types.go index b01f582c1..7d67a85f9 100644 --- a/controller/api/v1alpha1/lease_types.go +++ b/controller/api/v1alpha1/lease_types.go @@ -82,6 +82,7 @@ type LeaseLabel string const ( LeaseLabelEnded LeaseLabel = "jumpstarter.dev/lease-ended" LeaseLabelEndedValue string = "true" + LeaseLabelName LeaseLabel = "jumpstarter.dev/lease-name" LeaseTagMetadataPrefix string = "metadata.jumpstarter.dev/" ) diff --git a/controller/internal/protocol/jumpstarter/client/v1/client.pb.go b/controller/internal/protocol/jumpstarter/client/v1/client.pb.go index c1a515e84..9d625f48c 100644 --- a/controller/internal/protocol/jumpstarter/client/v1/client.pb.go +++ b/controller/internal/protocol/jumpstarter/client/v1/client.pb.go @@ -34,14 +34,21 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// An exporter resource representing a registered device provider. type Exporter struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Labels map[string]string `protobuf:"bytes,2,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + state protoimpl.MessageState `protogen:"open.v1"` + // The resource name of the exporter. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The set of labels associated with the exporter. + Labels map[string]string `protobuf:"bytes,2,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Whether the exporter is currently online. Deprecated in favor of the status field. + // // Deprecated: Marked as deprecated in jumpstarter/client/v1/client.proto. - Online bool `protobuf:"varint,3,opt,name=online,proto3" json:"online,omitempty"` - Status v1.ExporterStatus `protobuf:"varint,4,opt,name=status,proto3,enum=jumpstarter.v1.ExporterStatus" json:"status,omitempty"` - StatusMessage string `protobuf:"bytes,5,opt,name=status_message,json=statusMessage,proto3" json:"status_message,omitempty"` + Online bool `protobuf:"varint,3,opt,name=online,proto3" json:"online,omitempty"` + // The current status of the exporter. + Status v1.ExporterStatus `protobuf:"varint,4,opt,name=status,proto3,enum=jumpstarter.v1.ExporterStatus" json:"status,omitempty"` + // A human-readable message providing details about the exporter status. + StatusMessage string `protobuf:"bytes,5,opt,name=status_message,json=statusMessage,proto3" json:"status_message,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -112,23 +119,39 @@ func (x *Exporter) GetStatusMessage() string { return "" } +// A lease resource representing a reservation of an exporter. type Lease struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Selector string `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` - Duration *durationpb.Duration `protobuf:"bytes,3,opt,name=duration,proto3,oneof" json:"duration,omitempty"` - EffectiveDuration *durationpb.Duration `protobuf:"bytes,4,opt,name=effective_duration,json=effectiveDuration,proto3" json:"effective_duration,omitempty"` - BeginTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=begin_time,json=beginTime,proto3,oneof" json:"begin_time,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The resource name of the lease. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The label selector expression used to match an exporter. + Selector string `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` + // The requested duration of the lease. + Duration *durationpb.Duration `protobuf:"bytes,3,opt,name=duration,proto3,oneof" json:"duration,omitempty"` + // The server-computed effective duration of the lease. + EffectiveDuration *durationpb.Duration `protobuf:"bytes,4,opt,name=effective_duration,json=effectiveDuration,proto3" json:"effective_duration,omitempty"` + // The requested begin time of the lease. + BeginTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=begin_time,json=beginTime,proto3,oneof" json:"begin_time,omitempty"` + // The server-computed effective begin time of the lease. EffectiveBeginTime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=effective_begin_time,json=effectiveBeginTime,proto3,oneof" json:"effective_begin_time,omitempty"` - EndTime *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=end_time,json=endTime,proto3,oneof" json:"end_time,omitempty"` - EffectiveEndTime *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=effective_end_time,json=effectiveEndTime,proto3,oneof" json:"effective_end_time,omitempty"` - Client *string `protobuf:"bytes,9,opt,name=client,proto3,oneof" json:"client,omitempty"` - Exporter *string `protobuf:"bytes,10,opt,name=exporter,proto3,oneof" json:"exporter,omitempty"` - Conditions []*v1.Condition `protobuf:"bytes,11,rep,name=conditions,proto3" json:"conditions,omitempty"` - ExporterName *string `protobuf:"bytes,12,opt,name=exporter_name,json=exporterName,proto3,oneof" json:"exporter_name,omitempty"` - Tags map[string]string `protobuf:"bytes,13,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // The requested end time of the lease. + EndTime *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=end_time,json=endTime,proto3,oneof" json:"end_time,omitempty"` + // The server-computed effective end time of the lease. + EffectiveEndTime *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=effective_end_time,json=effectiveEndTime,proto3,oneof" json:"effective_end_time,omitempty"` + // The resource name of the client that owns this lease. + Client *string `protobuf:"bytes,9,opt,name=client,proto3,oneof" json:"client,omitempty"` + // The resource name of the exporter assigned to this lease. + Exporter *string `protobuf:"bytes,10,opt,name=exporter,proto3,oneof" json:"exporter,omitempty"` + // The list of conditions reflecting the current state of the lease. + Conditions []*v1.Condition `protobuf:"bytes,11,rep,name=conditions,proto3" json:"conditions,omitempty"` + // The name of a specific exporter to target for the lease. + ExporterName *string `protobuf:"bytes,12,opt,name=exporter_name,json=exporterName,proto3,oneof" json:"exporter_name,omitempty"` + // The set of tags associated with the lease. + Tags map[string]string `protobuf:"bytes,13,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // The user-provided alias for this lease (from lease_id at creation time). + Alias *string `protobuf:"bytes,14,opt,name=alias,proto3,oneof" json:"alias,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Lease) Reset() { @@ -252,9 +275,18 @@ func (x *Lease) GetTags() map[string]string { return nil } +func (x *Lease) GetAlias() string { + if x != nil && x.Alias != nil { + return *x.Alias + } + return "" +} + +// Request to retrieve an exporter. type GetExporterRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The resource name of the exporter. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -296,12 +328,17 @@ func (x *GetExporterRequest) GetName() string { return "" } +// Request to list exporters. type ListExportersRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` - PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` - Filter string `protobuf:"bytes,4,opt,name=filter,proto3" json:"filter,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The parent resource name (namespace). + Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` + // Maximum number of results to return. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + // Token for retrieving the next page of results. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + // Filter expression for the results. + Filter string `protobuf:"bytes,4,opt,name=filter,proto3" json:"filter,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -364,10 +401,13 @@ func (x *ListExportersRequest) GetFilter() string { return "" } +// Response containing a list of exporters. type ListExportersResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Exporters []*Exporter `protobuf:"bytes,1,rep,name=exporters,proto3" json:"exporters,omitempty"` - NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The list of exporters. + Exporters []*Exporter `protobuf:"bytes,1,rep,name=exporters,proto3" json:"exporters,omitempty"` + // Token for the next page of results. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -416,9 +456,11 @@ func (x *ListExportersResponse) GetNextPageToken() string { return "" } +// Request to retrieve a lease. type GetLeaseRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The resource name of the lease. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -460,14 +502,21 @@ func (x *GetLeaseRequest) GetName() string { return "" } +// Request to list leases. type ListLeasesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` - PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` - Filter string `protobuf:"bytes,4,opt,name=filter,proto3" json:"filter,omitempty"` - OnlyActive *bool `protobuf:"varint,5,opt,name=only_active,json=onlyActive,proto3,oneof" json:"only_active,omitempty"` - TagFilter string `protobuf:"bytes,6,opt,name=tag_filter,json=tagFilter,proto3" json:"tag_filter,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The parent resource name (namespace). + Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` + // Maximum number of results to return. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + // Token for retrieving the next page of results. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + // Filter expression for the results. + Filter string `protobuf:"bytes,4,opt,name=filter,proto3" json:"filter,omitempty"` + // If true, return only active leases. + OnlyActive *bool `protobuf:"varint,5,opt,name=only_active,json=onlyActive,proto3,oneof" json:"only_active,omitempty"` + // Filter expression for lease tags. + TagFilter string `protobuf:"bytes,6,opt,name=tag_filter,json=tagFilter,proto3" json:"tag_filter,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -544,10 +593,13 @@ func (x *ListLeasesRequest) GetTagFilter() string { return "" } +// Response containing a list of leases. type ListLeasesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Leases []*Lease `protobuf:"bytes,1,rep,name=leases,proto3" json:"leases,omitempty"` - NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The list of leases. + Leases []*Lease `protobuf:"bytes,1,rep,name=leases,proto3" json:"leases,omitempty"` + // Token for the next page of results. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -596,11 +648,15 @@ func (x *ListLeasesResponse) GetNextPageToken() string { return "" } +// Request to create a lease. type CreateLeaseRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` - LeaseId string `protobuf:"bytes,2,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` - Lease *Lease `protobuf:"bytes,3,opt,name=lease,proto3" json:"lease,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The parent resource name (namespace). + Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` + // The client-assigned identifier for the lease. + LeaseId string `protobuf:"bytes,2,opt,name=lease_id,json=leaseId,proto3" json:"lease_id,omitempty"` + // The lease resource to create. + Lease *Lease `protobuf:"bytes,3,opt,name=lease,proto3" json:"lease,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -656,9 +712,12 @@ func (x *CreateLeaseRequest) GetLease() *Lease { return nil } +// Request to update a lease. type UpdateLeaseRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Lease *Lease `protobuf:"bytes,1,opt,name=lease,proto3" json:"lease,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The lease resource with updated fields. + Lease *Lease `protobuf:"bytes,1,opt,name=lease,proto3" json:"lease,omitempty"` + // The set of fields to update. UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -708,9 +767,11 @@ func (x *UpdateLeaseRequest) GetUpdateMask() *fieldmaskpb.FieldMask { return nil } +// Request to delete a lease. type DeleteLeaseRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The resource name of the lease. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -752,9 +813,11 @@ func (x *DeleteLeaseRequest) GetName() string { return "" } +// Request to rotate the authentication token for a client. type RotateTokenRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The parent resource name (namespace). + Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -796,9 +859,12 @@ func (x *RotateTokenRequest) GetParent() string { return "" } +// Response containing the newly rotated token. type RotateTokenResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The new authentication token. + Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` + // The expiration time of the new token. Expiry *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expiry,proto3" json:"expiry,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -862,7 +928,7 @@ const file_jumpstarter_client_v1_client_proto_rawDesc = "" + "\vLabelsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01:_\xeaA\\\n" + - "\x18jumpstarter.dev/Exporter\x12+namespaces/{namespace}/exporters/{exporter}*\texporters2\bexporter\"\xb5\b\n" + + "\x18jumpstarter.dev/Exporter\x12+namespaces/{namespace}/exporters/{exporter}*\texporters2\bexporter\"\xdf\b\n" + "\x05Lease\x12\x17\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12\"\n" + "\bselector\x18\x02 \x01(\tB\x06\xe0A\x02\xe0A\x05R\bselector\x12:\n" + @@ -882,7 +948,8 @@ const file_jumpstarter_client_v1_client_proto_rawDesc = "" + "conditions\x18\v \x03(\v2\x19.jumpstarter.v1.ConditionB\x03\xe0A\x03R\n" + "conditions\x12-\n" + "\rexporter_name\x18\f \x01(\tB\x03\xe0A\x05H\aR\fexporterName\x88\x01\x01\x12?\n" + - "\x04tags\x18\r \x03(\v2&.jumpstarter.client.v1.Lease.TagsEntryB\x03\xe0A\x05R\x04tags\x1a7\n" + + "\x04tags\x18\r \x03(\v2&.jumpstarter.client.v1.Lease.TagsEntryB\x03\xe0A\x05R\x04tags\x12\x1e\n" + + "\x05alias\x18\x0e \x01(\tB\x03\xe0A\x03H\bR\x05alias\x88\x01\x01\x1a7\n" + "\tTagsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01:P\xeaAM\n" + @@ -894,7 +961,8 @@ const file_jumpstarter_client_v1_client_proto_rawDesc = "" + "\x13_effective_end_timeB\t\n" + "\a_clientB\v\n" + "\t_exporterB\x10\n" + - "\x0e_exporter_name\"J\n" + + "\x0e_exporter_nameB\b\n" + + "\x06_alias\"J\n" + "\x12GetExporterRequest\x124\n" + "\x04name\x18\x01 \x01(\tB \xe0A\x02\xfaA\x1a\n" + "\x18jumpstarter.dev/ExporterR\x04name\"\xb3\x01\n" + diff --git a/controller/internal/protocol/jumpstarter/client/v1/client_grpc.pb.go b/controller/internal/protocol/jumpstarter/client/v1/client_grpc.pb.go index 4ce13ee43..7fc078b65 100644 --- a/controller/internal/protocol/jumpstarter/client/v1/client_grpc.pb.go +++ b/controller/internal/protocol/jumpstarter/client/v1/client_grpc.pb.go @@ -40,14 +40,24 @@ const ( // ClientServiceClient is the client API for ClientService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// Client-facing API service for managing exporters and leases. type ClientServiceClient interface { + // Retrieve a single exporter by resource name. GetExporter(ctx context.Context, in *GetExporterRequest, opts ...grpc.CallOption) (*Exporter, error) + // List exporters in a namespace with optional filtering. ListExporters(ctx context.Context, in *ListExportersRequest, opts ...grpc.CallOption) (*ListExportersResponse, error) + // Retrieve a single lease by resource name. GetLease(ctx context.Context, in *GetLeaseRequest, opts ...grpc.CallOption) (*Lease, error) + // List leases in a namespace with optional filtering. ListLeases(ctx context.Context, in *ListLeasesRequest, opts ...grpc.CallOption) (*ListLeasesResponse, error) + // Create a new lease for an exporter. CreateLease(ctx context.Context, in *CreateLeaseRequest, opts ...grpc.CallOption) (*Lease, error) + // Update an existing lease. UpdateLease(ctx context.Context, in *UpdateLeaseRequest, opts ...grpc.CallOption) (*Lease, error) + // Delete a lease by resource name. DeleteLease(ctx context.Context, in *DeleteLeaseRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + // Rotate the authentication token for the client. RotateToken(ctx context.Context, in *RotateTokenRequest, opts ...grpc.CallOption) (*RotateTokenResponse, error) } @@ -142,14 +152,24 @@ func (c *clientServiceClient) RotateToken(ctx context.Context, in *RotateTokenRe // ClientServiceServer is the server API for ClientService service. // All implementations must embed UnimplementedClientServiceServer // for forward compatibility. +// +// Client-facing API service for managing exporters and leases. type ClientServiceServer interface { + // Retrieve a single exporter by resource name. GetExporter(context.Context, *GetExporterRequest) (*Exporter, error) + // List exporters in a namespace with optional filtering. ListExporters(context.Context, *ListExportersRequest) (*ListExportersResponse, error) + // Retrieve a single lease by resource name. GetLease(context.Context, *GetLeaseRequest) (*Lease, error) + // List leases in a namespace with optional filtering. ListLeases(context.Context, *ListLeasesRequest) (*ListLeasesResponse, error) + // Create a new lease for an exporter. CreateLease(context.Context, *CreateLeaseRequest) (*Lease, error) + // Update an existing lease. UpdateLease(context.Context, *UpdateLeaseRequest) (*Lease, error) + // Delete a lease by resource name. DeleteLease(context.Context, *DeleteLeaseRequest) (*emptypb.Empty, error) + // Rotate the authentication token for the client. RotateToken(context.Context, *RotateTokenRequest) (*RotateTokenResponse, error) mustEmbedUnimplementedClientServiceServer() } diff --git a/controller/internal/protocol/jumpstarter/v1/common.pb.go b/controller/internal/protocol/jumpstarter/v1/common.pb.go index 030ecf76d..4a379ab96 100644 --- a/controller/internal/protocol/jumpstarter/v1/common.pb.go +++ b/controller/internal/protocol/jumpstarter/v1/common.pb.go @@ -23,18 +23,18 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// Exporter status information +// Exporter status information. type ExporterStatus int32 const ( - ExporterStatus_EXPORTER_STATUS_UNSPECIFIED ExporterStatus = 0 // Unspecified exporter status - ExporterStatus_EXPORTER_STATUS_OFFLINE ExporterStatus = 1 // Exporter is offline - ExporterStatus_EXPORTER_STATUS_AVAILABLE ExporterStatus = 2 // Exporter is available to be leased - ExporterStatus_EXPORTER_STATUS_BEFORE_LEASE_HOOK ExporterStatus = 3 // Exporter is executing before lease hook(s) - ExporterStatus_EXPORTER_STATUS_LEASE_READY ExporterStatus = 4 // Exporter is leased and ready to accept commands - ExporterStatus_EXPORTER_STATUS_AFTER_LEASE_HOOK ExporterStatus = 5 // Exporter is executing after lease hook(s) - ExporterStatus_EXPORTER_STATUS_BEFORE_LEASE_HOOK_FAILED ExporterStatus = 6 // Exporter before lease hook failed - ExporterStatus_EXPORTER_STATUS_AFTER_LEASE_HOOK_FAILED ExporterStatus = 7 // Exporter after lease hook failed + ExporterStatus_EXPORTER_STATUS_UNSPECIFIED ExporterStatus = 0 // Unspecified exporter status. + ExporterStatus_EXPORTER_STATUS_OFFLINE ExporterStatus = 1 // Exporter is offline. + ExporterStatus_EXPORTER_STATUS_AVAILABLE ExporterStatus = 2 // Exporter is available to be leased. + ExporterStatus_EXPORTER_STATUS_BEFORE_LEASE_HOOK ExporterStatus = 3 // Exporter is executing before lease hook(s). + ExporterStatus_EXPORTER_STATUS_LEASE_READY ExporterStatus = 4 // Exporter is leased and ready to accept commands. + ExporterStatus_EXPORTER_STATUS_AFTER_LEASE_HOOK ExporterStatus = 5 // Exporter is executing after lease hook(s). + ExporterStatus_EXPORTER_STATUS_BEFORE_LEASE_HOOK_FAILED ExporterStatus = 6 // Exporter before lease hook failed. + ExporterStatus_EXPORTER_STATUS_AFTER_LEASE_HOOK_FAILED ExporterStatus = 7 // Exporter after lease hook failed. ) // Enum value maps for ExporterStatus. @@ -88,15 +88,15 @@ func (ExporterStatus) EnumDescriptor() ([]byte, []int) { return file_jumpstarter_v1_common_proto_rawDescGZIP(), []int{0} } -// Source of log stream messages +// Source of log stream messages. type LogSource int32 const ( - LogSource_LOG_SOURCE_UNSPECIFIED LogSource = 0 // Unspecified log source - LogSource_LOG_SOURCE_DRIVER LogSource = 1 // Driver/device logs - LogSource_LOG_SOURCE_BEFORE_LEASE_HOOK LogSource = 2 // beforeLease hook execution logs - LogSource_LOG_SOURCE_AFTER_LEASE_HOOK LogSource = 3 // afterLease hook execution logs - LogSource_LOG_SOURCE_SYSTEM LogSource = 4 // System/exporter logs + LogSource_LOG_SOURCE_UNSPECIFIED LogSource = 0 // Unspecified log source. + LogSource_LOG_SOURCE_DRIVER LogSource = 1 // Driver/device logs. + LogSource_LOG_SOURCE_BEFORE_LEASE_HOOK LogSource = 2 // beforeLease hook execution logs. + LogSource_LOG_SOURCE_AFTER_LEASE_HOOK LogSource = 3 // afterLease hook execution logs. + LogSource_LOG_SOURCE_SYSTEM LogSource = 4 // System/exporter logs. ) // Enum value maps for LogSource. diff --git a/controller/internal/protocol/jumpstarter/v1/jumpstarter.pb.go b/controller/internal/protocol/jumpstarter/v1/jumpstarter.pb.go index 1fc35ab7a..093c8d4af 100644 --- a/controller/internal/protocol/jumpstarter/v1/jumpstarter.pb.go +++ b/controller/internal/protocol/jumpstarter/v1/jumpstarter.pb.go @@ -27,15 +27,11 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// Registration request sent by an exporter to the controller. type RegisterRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // additional context: - // - token/authentication mechanism - Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - // standard labels: - // jumpstarter.dev/hostname= - // jumpstarter.dev/name= - Reports []*DriverInstanceReport `protobuf:"bytes,2,rep,name=reports,proto3" json:"reports,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Key-value metadata labels. + Reports []*DriverInstanceReport `protobuf:"bytes,2,rep,name=reports,proto3" json:"reports,omitempty"` // Driver instance reports for this exporter. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -84,13 +80,14 @@ func (x *RegisterRequest) GetReports() []*DriverInstanceReport { return nil } +// Report describing a single driver instance on an exporter. type DriverInstanceReport struct { state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // a unique id within the exporter - ParentUuid *string `protobuf:"bytes,2,opt,name=parent_uuid,json=parentUuid,proto3,oneof" json:"parent_uuid,omitempty"` // optional, if device has a parent device - Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Description *string `protobuf:"bytes,4,opt,name=description,proto3,oneof" json:"description,omitempty"` // optional custom driver description for CLI - MethodsDescription map[string]string `protobuf:"bytes,5,rep,name=methods_description,json=methodsDescription,proto3" json:"methods_description,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // method name -> help text for CLI + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // Unique identifier within the exporter. + ParentUuid *string `protobuf:"bytes,2,opt,name=parent_uuid,json=parentUuid,proto3,oneof" json:"parent_uuid,omitempty"` // Parent device UUID, if this is a child device. + Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Key-value metadata labels. + Description *string `protobuf:"bytes,4,opt,name=description,proto3,oneof" json:"description,omitempty"` // Custom driver description for CLI display. + MethodsDescription map[string]string `protobuf:"bytes,5,rep,name=methods_description,json=methodsDescription,proto3" json:"methods_description,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Method name to help text mapping for CLI. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -160,9 +157,10 @@ func (x *DriverInstanceReport) GetMethodsDescription() map[string]string { return nil } +// Registration response returned by the controller. type RegisterResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // Assigned exporter UUID. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -204,9 +202,10 @@ func (x *RegisterResponse) GetUuid() string { return "" } +// Request to unregister an exporter from the controller. type UnregisterRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` // Reason for unregistering. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -248,6 +247,7 @@ func (x *UnregisterRequest) GetReason() string { return "" } +// Response to an unregister request. type UnregisterResponse struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -284,9 +284,10 @@ func (*UnregisterResponse) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{4} } +// Request to listen for incoming client connections on a lease. type ListenRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - LeaseName string `protobuf:"bytes,1,opt,name=lease_name,json=leaseName,proto3" json:"lease_name,omitempty"` + LeaseName string `protobuf:"bytes,1,opt,name=lease_name,json=leaseName,proto3" json:"lease_name,omitempty"` // Name of the lease to listen on. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -328,10 +329,11 @@ func (x *ListenRequest) GetLeaseName() string { return "" } +// Response containing router connection details for an incoming client. type ListenResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - RouterEndpoint string `protobuf:"bytes,1,opt,name=router_endpoint,json=routerEndpoint,proto3" json:"router_endpoint,omitempty"` - RouterToken string `protobuf:"bytes,2,opt,name=router_token,json=routerToken,proto3" json:"router_token,omitempty"` + RouterEndpoint string `protobuf:"bytes,1,opt,name=router_endpoint,json=routerEndpoint,proto3" json:"router_endpoint,omitempty"` // The router gRPC endpoint URL. + RouterToken string `protobuf:"bytes,2,opt,name=router_token,json=routerToken,proto3" json:"router_token,omitempty"` // Authentication token for the router. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -380,6 +382,7 @@ func (x *ListenResponse) GetRouterToken() string { return "" } +// Request to subscribe to exporter lease status updates. type StatusRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -416,11 +419,12 @@ func (*StatusRequest) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{7} } +// Lease status update for an exporter. type StatusResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Leased bool `protobuf:"varint,1,opt,name=leased,proto3" json:"leased,omitempty"` - LeaseName *string `protobuf:"bytes,2,opt,name=lease_name,json=leaseName,proto3,oneof" json:"lease_name,omitempty"` - ClientName *string `protobuf:"bytes,3,opt,name=client_name,json=clientName,proto3,oneof" json:"client_name,omitempty"` + Leased bool `protobuf:"varint,1,opt,name=leased,proto3" json:"leased,omitempty"` // Whether the exporter is currently leased. + LeaseName *string `protobuf:"bytes,2,opt,name=lease_name,json=leaseName,proto3,oneof" json:"lease_name,omitempty"` // Name of the active lease, if any. + ClientName *string `protobuf:"bytes,3,opt,name=client_name,json=clientName,proto3,oneof" json:"client_name,omitempty"` // Name of the connected client, if any. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -476,9 +480,10 @@ func (x *StatusResponse) GetClientName() string { return "" } +// Request to dial an exporter through the router. type DialRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - LeaseName string `protobuf:"bytes,1,opt,name=lease_name,json=leaseName,proto3" json:"lease_name,omitempty"` + LeaseName string `protobuf:"bytes,1,opt,name=lease_name,json=leaseName,proto3" json:"lease_name,omitempty"` // Name of the lease to connect through. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -520,10 +525,11 @@ func (x *DialRequest) GetLeaseName() string { return "" } +// Response containing router connection details for the dialed exporter. type DialResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - RouterEndpoint string `protobuf:"bytes,1,opt,name=router_endpoint,json=routerEndpoint,proto3" json:"router_endpoint,omitempty"` - RouterToken string `protobuf:"bytes,2,opt,name=router_token,json=routerToken,proto3" json:"router_token,omitempty"` + RouterEndpoint string `protobuf:"bytes,1,opt,name=router_endpoint,json=routerEndpoint,proto3" json:"router_endpoint,omitempty"` // The router gRPC endpoint URL. + RouterToken string `protobuf:"bytes,2,opt,name=router_token,json=routerToken,proto3" json:"router_token,omitempty"` // Authentication token for the router. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -572,14 +578,13 @@ func (x *DialResponse) GetRouterToken() string { return "" } +// An audit event sent from an exporter to the controller. type AuditStreamRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // additional context: - // - token/authentication mechanism - ExporterUuid string `protobuf:"bytes,1,opt,name=exporter_uuid,json=exporterUuid,proto3" json:"exporter_uuid,omitempty"` - DriverInstanceUuid string `protobuf:"bytes,2,opt,name=driver_instance_uuid,json=driverInstanceUuid,proto3" json:"driver_instance_uuid,omitempty"` - Severity string `protobuf:"bytes,3,opt,name=severity,proto3" json:"severity,omitempty"` - Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + ExporterUuid string `protobuf:"bytes,1,opt,name=exporter_uuid,json=exporterUuid,proto3" json:"exporter_uuid,omitempty"` // UUID of the exporter. + DriverInstanceUuid string `protobuf:"bytes,2,opt,name=driver_instance_uuid,json=driverInstanceUuid,proto3" json:"driver_instance_uuid,omitempty"` // UUID of the driver instance. + Severity string `protobuf:"bytes,3,opt,name=severity,proto3" json:"severity,omitempty"` // Severity level of the event. + Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` // Human-readable event message. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -642,11 +647,12 @@ func (x *AuditStreamRequest) GetMessage() string { return "" } +// Request to report exporter status to the controller. type ReportStatusRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Status ExporterStatus `protobuf:"varint,1,opt,name=status,proto3,enum=jumpstarter.v1.ExporterStatus" json:"status,omitempty"` - Message *string `protobuf:"bytes,2,opt,name=message,proto3,oneof" json:"message,omitempty"` // Optional human-readable status message - ReleaseLease *bool `protobuf:"varint,3,opt,name=release_lease,json=releaseLease,proto3,oneof" json:"release_lease,omitempty"` // When true, controller should release the active lease + Status ExporterStatus `protobuf:"varint,1,opt,name=status,proto3,enum=jumpstarter.v1.ExporterStatus" json:"status,omitempty"` // Current exporter status. + Message *string `protobuf:"bytes,2,opt,name=message,proto3,oneof" json:"message,omitempty"` // Optional human-readable status message. + ReleaseLease *bool `protobuf:"varint,3,opt,name=release_lease,json=releaseLease,proto3,oneof" json:"release_lease,omitempty"` // When true, controller should release the active lease. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -702,6 +708,7 @@ func (x *ReportStatusRequest) GetReleaseLease() bool { return false } +// Response to a status report request. type ReportStatusResponse struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -738,15 +745,13 @@ func (*ReportStatusResponse) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{13} } +// Response containing the exporter driver report. type GetReportResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Labels map[string]string `protobuf:"bytes,2,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - // standard labels: - // jumpstarter.dev/hostname= - // jumpstarter.dev/name= - Reports []*DriverInstanceReport `protobuf:"bytes,3,rep,name=reports,proto3" json:"reports,omitempty"` - AlternativeEndpoints []*Endpoint `protobuf:"bytes,4,rep,name=alternative_endpoints,json=alternativeEndpoints,proto3" json:"alternative_endpoints,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // Exporter UUID. + Labels map[string]string `protobuf:"bytes,2,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Key-value metadata labels. + Reports []*DriverInstanceReport `protobuf:"bytes,3,rep,name=reports,proto3" json:"reports,omitempty"` // Driver instance reports. + AlternativeEndpoints []*Endpoint `protobuf:"bytes,4,rep,name=alternative_endpoints,json=alternativeEndpoints,proto3" json:"alternative_endpoints,omitempty"` // Alternative connection endpoints. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -809,12 +814,13 @@ func (x *GetReportResponse) GetAlternativeEndpoints() []*Endpoint { return nil } +// Connection endpoint with TLS credentials. type Endpoint struct { state protoimpl.MessageState `protogen:"open.v1"` - Endpoint string `protobuf:"bytes,1,opt,name=endpoint,proto3" json:"endpoint,omitempty"` - Certificate string `protobuf:"bytes,2,opt,name=certificate,proto3" json:"certificate,omitempty"` - ClientCertificate string `protobuf:"bytes,3,opt,name=client_certificate,json=clientCertificate,proto3" json:"client_certificate,omitempty"` - ClientPrivateKey string `protobuf:"bytes,4,opt,name=client_private_key,json=clientPrivateKey,proto3" json:"client_private_key,omitempty"` + Endpoint string `protobuf:"bytes,1,opt,name=endpoint,proto3" json:"endpoint,omitempty"` // The endpoint URL. + Certificate string `protobuf:"bytes,2,opt,name=certificate,proto3" json:"certificate,omitempty"` // Server TLS certificate. + ClientCertificate string `protobuf:"bytes,3,opt,name=client_certificate,json=clientCertificate,proto3" json:"client_certificate,omitempty"` // Client TLS certificate. + ClientPrivateKey string `protobuf:"bytes,4,opt,name=client_private_key,json=clientPrivateKey,proto3" json:"client_private_key,omitempty"` // Client TLS private key. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -877,11 +883,12 @@ func (x *Endpoint) GetClientPrivateKey() string { return "" } +// Request to invoke a method on a driver instance. type DriverCallRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` - Args []*structpb.Value `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // UUID of the driver instance. + Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` // Method name to invoke. + Args []*structpb.Value `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` // Arguments for the method call. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -937,10 +944,11 @@ func (x *DriverCallRequest) GetArgs() []*structpb.Value { return nil } +// Response from a driver method invocation. type DriverCallResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Result *structpb.Value `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // UUID of the driver instance. + Result *structpb.Value `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` // Return value from the method call. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -989,11 +997,12 @@ func (x *DriverCallResponse) GetResult() *structpb.Value { return nil } +// Request to invoke a streaming method on a driver instance. type StreamingDriverCallRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` - Args []*structpb.Value `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // UUID of the driver instance. + Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"` // Method name to invoke. + Args []*structpb.Value `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` // Arguments for the method call. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1049,10 +1058,11 @@ func (x *StreamingDriverCallRequest) GetArgs() []*structpb.Value { return nil } +// Response from a streaming driver method invocation. type StreamingDriverCallResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Result *structpb.Value `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // UUID of the driver instance. + Result *structpb.Value `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` // Return value from the method call. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1101,12 +1111,13 @@ func (x *StreamingDriverCallResponse) GetResult() *structpb.Value { return nil } +// A log message from the exporter log stream. type LogStreamResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` - Severity string `protobuf:"bytes,2,opt,name=severity,proto3" json:"severity,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - Source *LogSource `protobuf:"varint,4,opt,name=source,proto3,enum=jumpstarter.v1.LogSource,oneof" json:"source,omitempty"` // New optional field + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // UUID of the driver instance. + Severity string `protobuf:"bytes,2,opt,name=severity,proto3" json:"severity,omitempty"` // Log severity level. + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` // Log message content. + Source *LogSource `protobuf:"varint,4,opt,name=source,proto3,enum=jumpstarter.v1.LogSource,oneof" json:"source,omitempty"` // Source of the log message. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1169,6 +1180,7 @@ func (x *LogStreamResponse) GetSource() LogSource { return LogSource_LOG_SOURCE_UNSPECIFIED } +// Request to reset the exporter connection. type ResetRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1205,6 +1217,7 @@ func (*ResetRequest) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{21} } +// Response to a reset request. type ResetResponse struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1241,9 +1254,10 @@ func (*ResetResponse) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{22} } +// Request to retrieve a lease by name. type GetLeaseRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Name of the lease to retrieve. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1285,14 +1299,15 @@ func (x *GetLeaseRequest) GetName() string { return "" } +// Response containing lease details. type GetLeaseResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Duration *durationpb.Duration `protobuf:"bytes,1,opt,name=duration,proto3" json:"duration,omitempty"` - Selector *LabelSelector `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` - BeginTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=begin_time,json=beginTime,proto3,oneof" json:"begin_time,omitempty"` - EndTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=end_time,json=endTime,proto3,oneof" json:"end_time,omitempty"` - ExporterUuid *string `protobuf:"bytes,5,opt,name=exporter_uuid,json=exporterUuid,proto3,oneof" json:"exporter_uuid,omitempty"` - Conditions []*Condition `protobuf:"bytes,6,rep,name=conditions,proto3" json:"conditions,omitempty"` + Duration *durationpb.Duration `protobuf:"bytes,1,opt,name=duration,proto3" json:"duration,omitempty"` // Requested lease duration. + Selector *LabelSelector `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` // Label selector for matching exporters. + BeginTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=begin_time,json=beginTime,proto3,oneof" json:"begin_time,omitempty"` // Lease start time, if active. + EndTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=end_time,json=endTime,proto3,oneof" json:"end_time,omitempty"` // Lease end time, if active. + ExporterUuid *string `protobuf:"bytes,5,opt,name=exporter_uuid,json=exporterUuid,proto3,oneof" json:"exporter_uuid,omitempty"` // UUID of the assigned exporter, if any. + Conditions []*Condition `protobuf:"bytes,6,rep,name=conditions,proto3" json:"conditions,omitempty"` // Lease status conditions. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1369,10 +1384,11 @@ func (x *GetLeaseResponse) GetConditions() []*Condition { return nil } +// Request to create a new lease for an exporter. type RequestLeaseRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Duration *durationpb.Duration `protobuf:"bytes,1,opt,name=duration,proto3" json:"duration,omitempty"` - Selector *LabelSelector `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` + Duration *durationpb.Duration `protobuf:"bytes,1,opt,name=duration,proto3" json:"duration,omitempty"` // Desired lease duration. + Selector *LabelSelector `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` // Label selector for matching exporters. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1421,9 +1437,10 @@ func (x *RequestLeaseRequest) GetSelector() *LabelSelector { return nil } +// Response containing the name of the created lease. type RequestLeaseResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Name of the created lease. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1465,9 +1482,10 @@ func (x *RequestLeaseResponse) GetName() string { return "" } +// Request to release an active lease. type ReleaseLeaseRequest struct { state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Name of the lease to release. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1509,6 +1527,7 @@ func (x *ReleaseLeaseRequest) GetName() string { return "" } +// Response to a release lease request. type ReleaseLeaseResponse struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1545,6 +1564,7 @@ func (*ReleaseLeaseResponse) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{28} } +// Request to list all leases. type ListLeasesRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1581,9 +1601,10 @@ func (*ListLeasesRequest) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{29} } +// Response containing the list of lease names. type ListLeasesResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` + Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` // Names of all leases. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1625,6 +1646,7 @@ func (x *ListLeasesResponse) GetNames() []string { return nil } +// Request to retrieve the current exporter status. type GetStatusRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1661,12 +1683,13 @@ func (*GetStatusRequest) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{31} } +// Response containing the current exporter status. type GetStatusResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Status ExporterStatus `protobuf:"varint,1,opt,name=status,proto3,enum=jumpstarter.v1.ExporterStatus" json:"status,omitempty"` - Message *string `protobuf:"bytes,2,opt,name=message,proto3,oneof" json:"message,omitempty"` - StatusVersion uint64 `protobuf:"varint,3,opt,name=status_version,json=statusVersion,proto3" json:"status_version,omitempty"` // Monotonic counter, increments on each status change - PreviousStatus *ExporterStatus `protobuf:"varint,4,opt,name=previous_status,json=previousStatus,proto3,enum=jumpstarter.v1.ExporterStatus,oneof" json:"previous_status,omitempty"` // Previous status for transition tracking + Status ExporterStatus `protobuf:"varint,1,opt,name=status,proto3,enum=jumpstarter.v1.ExporterStatus" json:"status,omitempty"` // Current exporter status. + Message *string `protobuf:"bytes,2,opt,name=message,proto3,oneof" json:"message,omitempty"` // Human-readable status message. + StatusVersion uint64 `protobuf:"varint,3,opt,name=status_version,json=statusVersion,proto3" json:"status_version,omitempty"` // Monotonic counter, increments on each status change. + PreviousStatus *ExporterStatus `protobuf:"varint,4,opt,name=previous_status,json=previousStatus,proto3,enum=jumpstarter.v1.ExporterStatus,oneof" json:"previous_status,omitempty"` // Previous status for transition tracking. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1729,6 +1752,7 @@ func (x *GetStatusResponse) GetPreviousStatus() ExporterStatus { return ExporterStatus_EXPORTER_STATUS_UNSPECIFIED } +// Request to end the current exporter session. type EndSessionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1765,10 +1789,11 @@ func (*EndSessionRequest) Descriptor() ([]byte, []int) { return file_jumpstarter_v1_jumpstarter_proto_rawDescGZIP(), []int{33} } +// Response to an end session request. type EndSessionResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` - Message *string `protobuf:"bytes,2,opt,name=message,proto3,oneof" json:"message,omitempty"` + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` // Whether the session ended successfully. + Message *string `protobuf:"bytes,2,opt,name=message,proto3,oneof" json:"message,omitempty"` // Human-readable result message. unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } diff --git a/controller/internal/protocol/jumpstarter/v1/jumpstarter_grpc.pb.go b/controller/internal/protocol/jumpstarter/v1/jumpstarter_grpc.pb.go index 744b91fa5..8b0501409 100644 --- a/controller/internal/protocol/jumpstarter/v1/jumpstarter_grpc.pb.go +++ b/controller/internal/protocol/jumpstarter/v1/jumpstarter_grpc.pb.go @@ -39,38 +39,34 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // -// A service where a exporter can connect to make itself available +// A service where an exporter can connect to make itself available. type ControllerServiceClient interface { - // Exporter registration + // Register an exporter with the controller. Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) - // Exporter disconnection - // Disconnecting with bye will invalidate any existing router tokens - // we will eventually have a mechanism to tell the router this token - // has been invalidated + // Unregister an exporter from the controller. + // Disconnecting will invalidate any existing router tokens. Unregister(ctx context.Context, in *UnregisterRequest, opts ...grpc.CallOption) (*UnregisterResponse, error) - // Exporter status report - // Allows exporters to report their own status to the controller + // Report exporter status to the controller. ReportStatus(ctx context.Context, in *ReportStatusRequest, opts ...grpc.CallOption) (*ReportStatusResponse, error) - // Exporter listening - // Returns stream tokens for accepting incoming client connections + // Listen for incoming client connections on a lease. + // Returns stream tokens for accepting incoming client connections. Listen(ctx context.Context, in *ListenRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ListenResponse], error) - // Exporter status - // Returns lease status for the exporter + // Stream lease status updates for the exporter. Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StatusResponse], error) - // Client connecting - // Returns stream token for connecting to the desired exporter - // Leases are checked before token issuance + // Dial an exporter through the router. + // Returns a stream token for connecting to the desired exporter. + // Leases are checked before token issuance. Dial(ctx context.Context, in *DialRequest, opts ...grpc.CallOption) (*DialResponse, error) - // Audit events from the exporters - // audit events are used to track the exporter's activity + // Stream audit events from the exporters. + // Audit events are used to track the exporter activity. AuditStream(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[AuditStreamRequest, emptypb.Empty], error) - // Get Lease + // Retrieve a lease by name. GetLease(ctx context.Context, in *GetLeaseRequest, opts ...grpc.CallOption) (*GetLeaseResponse, error) - // Request Lease + // Request a new lease for an exporter. RequestLease(ctx context.Context, in *RequestLeaseRequest, opts ...grpc.CallOption) (*RequestLeaseResponse, error) - // Release Lease + // Release an active lease. ReleaseLease(ctx context.Context, in *ReleaseLeaseRequest, opts ...grpc.CallOption) (*ReleaseLeaseResponse, error) - // List Leases + // List all leases. ListLeases(ctx context.Context, in *ListLeasesRequest, opts ...grpc.CallOption) (*ListLeasesResponse, error) } @@ -217,38 +213,34 @@ func (c *controllerServiceClient) ListLeases(ctx context.Context, in *ListLeases // All implementations must embed UnimplementedControllerServiceServer // for forward compatibility. // -// A service where a exporter can connect to make itself available +// A service where an exporter can connect to make itself available. type ControllerServiceServer interface { - // Exporter registration + // Register an exporter with the controller. Register(context.Context, *RegisterRequest) (*RegisterResponse, error) - // Exporter disconnection - // Disconnecting with bye will invalidate any existing router tokens - // we will eventually have a mechanism to tell the router this token - // has been invalidated + // Unregister an exporter from the controller. + // Disconnecting will invalidate any existing router tokens. Unregister(context.Context, *UnregisterRequest) (*UnregisterResponse, error) - // Exporter status report - // Allows exporters to report their own status to the controller + // Report exporter status to the controller. ReportStatus(context.Context, *ReportStatusRequest) (*ReportStatusResponse, error) - // Exporter listening - // Returns stream tokens for accepting incoming client connections + // Listen for incoming client connections on a lease. + // Returns stream tokens for accepting incoming client connections. Listen(*ListenRequest, grpc.ServerStreamingServer[ListenResponse]) error - // Exporter status - // Returns lease status for the exporter + // Stream lease status updates for the exporter. Status(*StatusRequest, grpc.ServerStreamingServer[StatusResponse]) error - // Client connecting - // Returns stream token for connecting to the desired exporter - // Leases are checked before token issuance + // Dial an exporter through the router. + // Returns a stream token for connecting to the desired exporter. + // Leases are checked before token issuance. Dial(context.Context, *DialRequest) (*DialResponse, error) - // Audit events from the exporters - // audit events are used to track the exporter's activity + // Stream audit events from the exporters. + // Audit events are used to track the exporter activity. AuditStream(grpc.ClientStreamingServer[AuditStreamRequest, emptypb.Empty]) error - // Get Lease + // Retrieve a lease by name. GetLease(context.Context, *GetLeaseRequest) (*GetLeaseResponse, error) - // Request Lease + // Request a new lease for an exporter. RequestLease(context.Context, *RequestLeaseRequest) (*RequestLeaseResponse, error) - // Release Lease + // Release an active lease. ReleaseLease(context.Context, *ReleaseLeaseRequest) (*ReleaseLeaseResponse, error) - // List Leases + // List all leases. ListLeases(context.Context, *ListLeasesRequest) (*ListLeasesResponse, error) mustEmbedUnimplementedControllerServiceServer() } @@ -561,19 +553,24 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // -// A service a exporter can share locally to be used without a server -// Channel/Call credentials are used to authenticate the client, and routing to the right exporter +// A service an exporter can share locally to be used without a server. +// Channel and call credentials are used to authenticate the client and route to the right exporter. type ExporterServiceClient interface { - // Exporter registration + // Retrieve the exporter driver report. GetReport(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetReportResponse, error) + // Invoke a method on a driver instance. DriverCall(ctx context.Context, in *DriverCallRequest, opts ...grpc.CallOption) (*DriverCallResponse, error) + // Invoke a streaming method on a driver instance. StreamingDriverCall(ctx context.Context, in *StreamingDriverCallRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StreamingDriverCallResponse], error) + // Stream log messages from the exporter. LogStream(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogStreamResponse], error) + // Reset the exporter connection. Reset(ctx context.Context, in *ResetRequest, opts ...grpc.CallOption) (*ResetResponse, error) + // Retrieve the current exporter status. GetStatus(ctx context.Context, in *GetStatusRequest, opts ...grpc.CallOption) (*GetStatusResponse, error) - // End the current session, triggering the afterLease hook - // The client should keep the connection open to receive hook logs via LogStream - // Returns after the afterLease hook completes + // End the current session, triggering the afterLease hook. + // The client should keep the connection open to receive hook logs via LogStream. + // Returns after the afterLease hook completes. EndSession(ctx context.Context, in *EndSessionRequest, opts ...grpc.CallOption) (*EndSessionResponse, error) } @@ -677,19 +674,24 @@ func (c *exporterServiceClient) EndSession(ctx context.Context, in *EndSessionRe // All implementations must embed UnimplementedExporterServiceServer // for forward compatibility. // -// A service a exporter can share locally to be used without a server -// Channel/Call credentials are used to authenticate the client, and routing to the right exporter +// A service an exporter can share locally to be used without a server. +// Channel and call credentials are used to authenticate the client and route to the right exporter. type ExporterServiceServer interface { - // Exporter registration + // Retrieve the exporter driver report. GetReport(context.Context, *emptypb.Empty) (*GetReportResponse, error) + // Invoke a method on a driver instance. DriverCall(context.Context, *DriverCallRequest) (*DriverCallResponse, error) + // Invoke a streaming method on a driver instance. StreamingDriverCall(*StreamingDriverCallRequest, grpc.ServerStreamingServer[StreamingDriverCallResponse]) error + // Stream log messages from the exporter. LogStream(*emptypb.Empty, grpc.ServerStreamingServer[LogStreamResponse]) error + // Reset the exporter connection. Reset(context.Context, *ResetRequest) (*ResetResponse, error) + // Retrieve the current exporter status. GetStatus(context.Context, *GetStatusRequest) (*GetStatusResponse, error) - // End the current session, triggering the afterLease hook - // The client should keep the connection open to receive hook logs via LogStream - // Returns after the afterLease hook completes + // End the current session, triggering the afterLease hook. + // The client should keep the connection open to receive hook logs via LogStream. + // Returns after the afterLease hook completes. EndSession(context.Context, *EndSessionRequest) (*EndSessionResponse, error) mustEmbedUnimplementedExporterServiceServer() } diff --git a/controller/internal/protocol/jumpstarter/v1/kubernetes.pb.go b/controller/internal/protocol/jumpstarter/v1/kubernetes.pb.go index f4d0dde1c..905484c0e 100644 --- a/controller/internal/protocol/jumpstarter/v1/kubernetes.pb.go +++ b/controller/internal/protocol/jumpstarter/v1/kubernetes.pb.go @@ -23,11 +23,15 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// A label selector requirement with key, operator, and values. type LabelSelectorRequirement struct { - state protoimpl.MessageState `protogen:"open.v1"` - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Operator string `protobuf:"bytes,2,opt,name=operator,proto3" json:"operator,omitempty"` - Values []string `protobuf:"bytes,3,rep,name=values,proto3" json:"values,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The label key that the selector applies to. + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // The operator (In, NotIn, Exists, DoesNotExist) relating the key to values. + Operator string `protobuf:"bytes,2,opt,name=operator,proto3" json:"operator,omitempty"` + // The set of values for the operator to match against. + Values []string `protobuf:"bytes,3,rep,name=values,proto3" json:"values,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -85,11 +89,13 @@ func (x *LabelSelectorRequirement) GetValues() []string { // Reference: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/label-selector/ type LabelSelector struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState `protogen:"open.v1"` + // A list of label selector requirements combined by AND. MatchExpressions []*LabelSelectorRequirement `protobuf:"bytes,1,rep,name=match_expressions,json=matchExpressions,proto3" json:"match_expressions,omitempty"` - MatchLabels map[string]string `protobuf:"bytes,2,rep,name=match_labels,json=matchLabels,proto3" json:"match_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // A map of key-value pairs that must match exactly. + MatchLabels map[string]string `protobuf:"bytes,2,rep,name=match_labels,json=matchLabels,proto3" json:"match_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *LabelSelector) Reset() { @@ -136,11 +142,14 @@ func (x *LabelSelector) GetMatchLabels() map[string]string { return nil } +// Timestamp in seconds and nanoseconds since the Unix epoch. // Reference: https://github.com/kubernetes/kubernetes/blob/v1.31.1/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto type Time struct { - state protoimpl.MessageState `protogen:"open.v1"` - Seconds *int64 `protobuf:"varint,1,opt,name=seconds,proto3,oneof" json:"seconds,omitempty"` - Nanos *int32 `protobuf:"varint,2,opt,name=nanos,proto3,oneof" json:"nanos,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // Seconds since the Unix epoch. + Seconds *int64 `protobuf:"varint,1,opt,name=seconds,proto3,oneof" json:"seconds,omitempty"` + // Non-negative fractions of a second at nanosecond resolution. + Nanos *int32 `protobuf:"varint,2,opt,name=nanos,proto3,oneof" json:"nanos,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -189,16 +198,23 @@ func (x *Time) GetNanos() int32 { return 0 } +// A Kubernetes-style status condition. type Condition struct { - state protoimpl.MessageState `protogen:"open.v1"` - Type *string `protobuf:"bytes,1,opt,name=type,proto3,oneof" json:"type,omitempty"` - Status *string `protobuf:"bytes,2,opt,name=status,proto3,oneof" json:"status,omitempty"` - ObservedGeneration *int64 `protobuf:"varint,3,opt,name=observedGeneration,proto3,oneof" json:"observedGeneration,omitempty"` - LastTransitionTime *Time `protobuf:"bytes,4,opt,name=lastTransitionTime,proto3,oneof" json:"lastTransitionTime,omitempty"` - Reason *string `protobuf:"bytes,5,opt,name=reason,proto3,oneof" json:"reason,omitempty"` - Message *string `protobuf:"bytes,6,opt,name=message,proto3,oneof" json:"message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + // The type of condition. + Type *string `protobuf:"bytes,1,opt,name=type,proto3,oneof" json:"type,omitempty"` + // The status of the condition (True, False, Unknown). + Status *string `protobuf:"bytes,2,opt,name=status,proto3,oneof" json:"status,omitempty"` + // The generation observed by the controller. + ObservedGeneration *int64 `protobuf:"varint,3,opt,name=observedGeneration,proto3,oneof" json:"observedGeneration,omitempty"` + // The last time the condition transitioned. + LastTransitionTime *Time `protobuf:"bytes,4,opt,name=lastTransitionTime,proto3,oneof" json:"lastTransitionTime,omitempty"` + // A machine-readable reason for the condition. + Reason *string `protobuf:"bytes,5,opt,name=reason,proto3,oneof" json:"reason,omitempty"` + // A human-readable description of the condition. + Message *string `protobuf:"bytes,6,opt,name=message,proto3,oneof" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Condition) Reset() { diff --git a/controller/internal/protocol/jumpstarter/v1/router.pb.go b/controller/internal/protocol/jumpstarter/v1/router.pb.go index be6fd8eff..96f5a710b 100644 --- a/controller/internal/protocol/jumpstarter/v1/router.pb.go +++ b/controller/internal/protocol/jumpstarter/v1/router.pb.go @@ -23,13 +23,18 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// Frame types for the stream protocol. type FrameType int32 const ( - FrameType_FRAME_TYPE_DATA FrameType = 0 + // Data frame carrying payload bytes. + FrameType_FRAME_TYPE_DATA FrameType = 0 + // Reset stream signal. FrameType_FRAME_TYPE_RST_STREAM FrameType = 3 - FrameType_FRAME_TYPE_PING FrameType = 6 - FrameType_FRAME_TYPE_GOAWAY FrameType = 7 + // Keepalive ping frame. + FrameType_FRAME_TYPE_PING FrameType = 6 + // Graceful shutdown signal. + FrameType_FRAME_TYPE_GOAWAY FrameType = 7 ) // Enum value maps for FrameType. @@ -75,10 +80,13 @@ func (FrameType) EnumDescriptor() ([]byte, []int) { return file_jumpstarter_v1_router_proto_rawDescGZIP(), []int{0} } +// Request message for bidirectional stream communication. type StreamRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` - FrameType FrameType `protobuf:"varint,2,opt,name=frame_type,json=frameType,proto3,enum=jumpstarter.v1.FrameType" json:"frame_type,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The raw bytes of the stream frame. + Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` + // The type of frame being sent. + FrameType FrameType `protobuf:"varint,2,opt,name=frame_type,json=frameType,proto3,enum=jumpstarter.v1.FrameType" json:"frame_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -127,10 +135,13 @@ func (x *StreamRequest) GetFrameType() FrameType { return FrameType_FRAME_TYPE_DATA } +// Response message for bidirectional stream communication. type StreamResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` - FrameType FrameType `protobuf:"varint,2,opt,name=frame_type,json=frameType,proto3,enum=jumpstarter.v1.FrameType" json:"frame_type,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + // The raw bytes of the stream frame. + Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` + // The type of frame being received. + FrameType FrameType `protobuf:"varint,2,opt,name=frame_type,json=frameType,proto3,enum=jumpstarter.v1.FrameType" json:"frame_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } diff --git a/controller/internal/protocol/jumpstarter/v1/router_grpc.pb.go b/controller/internal/protocol/jumpstarter/v1/router_grpc.pb.go index 97eef72db..418963f8e 100644 --- a/controller/internal/protocol/jumpstarter/v1/router_grpc.pb.go +++ b/controller/internal/protocol/jumpstarter/v1/router_grpc.pb.go @@ -28,14 +28,14 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // -// StreamService +// Router service for multiplexing bidirectional streams between clients and exporters. // Claims: // iss: jumpstarter controller // aud: jumpstarter router // sub: jumpstarter client/exporter -// stream: stream id +// stream: stream id. type RouterServiceClient interface { - // Stream connects caller to another caller of the same stream + // Stream connects caller to another caller of the same stream. Stream(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[StreamRequest, StreamResponse], error) } @@ -64,14 +64,14 @@ type RouterService_StreamClient = grpc.BidiStreamingClient[StreamRequest, Stream // All implementations must embed UnimplementedRouterServiceServer // for forward compatibility. // -// StreamService +// Router service for multiplexing bidirectional streams between clients and exporters. // Claims: // iss: jumpstarter controller // aud: jumpstarter router // sub: jumpstarter client/exporter -// stream: stream id +// stream: stream id. type RouterServiceServer interface { - // Stream connects caller to another caller of the same stream + // Stream connects caller to another caller of the same stream. Stream(grpc.BidiStreamingServer[StreamRequest, StreamResponse]) error mustEmbedUnimplementedRouterServiceServer() } diff --git a/controller/internal/service/client/v1/client_service.go b/controller/internal/service/client/v1/client_service.go index fba28ebc3..484d78214 100644 --- a/controller/internal/service/client/v1/client_service.go +++ b/controller/internal/service/client/v1/client_service.go @@ -19,9 +19,9 @@ package v1 import ( "context" "fmt" + "sync" "github.com/golang-jwt/jwt/v5" - "github.com/google/uuid" jumpstarterdevv1alpha1 "github.com/jumpstarter-dev/jumpstarter-controller/api/v1alpha1" "github.com/jumpstarter-dev/jumpstarter-controller/internal/oidc" cpb "github.com/jumpstarter-dev/jumpstarter-controller/internal/protocol/jumpstarter/client/v1" @@ -43,8 +43,16 @@ type ClientService struct { cpb.UnimplementedClientServiceServer kclient.Client auth.Auth - MaxTags int32 - Signer *oidc.Signer + MaxTags int32 + Signer *oidc.Signer + leaseAliasLocks sync.Map +} + +func (s *ClientService) lockAlias(alias string) *sync.Mutex { + v, _ := s.leaseAliasLocks.LoadOrStore(alias, &sync.Mutex{}) + mu := v.(*sync.Mutex) + mu.Lock() + return mu } func NewClientService(client kclient.Client, auth auth.Auth, maxTags int32, signer *oidc.Signer) *ClientService { @@ -110,6 +118,77 @@ func (s *ClientService) ListExporters( return jexporters.ToProtobuf(), nil } +func (s *ClientService) resolveLeaseByNameOrAlias(ctx context.Context, namespace, nameOrAlias string) (*jumpstarterdevv1alpha1.Lease, error) { + var jlease jumpstarterdevv1alpha1.Lease + if err := s.Get(ctx, types.NamespacedName{Namespace: namespace, Name: nameOrAlias}, &jlease); err == nil { + return &jlease, nil + } + + aliasReq, err := labels.NewRequirement( + string(jumpstarterdevv1alpha1.LeaseLabelName), + selection.Equals, + []string{nameOrAlias}, + ) + if err != nil { + return nil, err + } + activeReq, err := labels.NewRequirement( + string(jumpstarterdevv1alpha1.LeaseLabelEnded), + selection.DoesNotExist, + []string{}, + ) + if err != nil { + return nil, err + } + + var jleases jumpstarterdevv1alpha1.LeaseList + if err := s.List(ctx, &jleases, + kclient.InNamespace(namespace), + kclient.MatchingLabelsSelector{Selector: labels.Everything().Add(*aliasReq).Add(*activeReq)}, + kclient.Limit(2), + ); err != nil { + return nil, err + } + + switch len(jleases.Items) { + case 0: + return nil, status.Errorf(codes.NotFound, "lease %q not found", nameOrAlias) + case 1: + return &jleases.Items[0], nil + default: + return nil, status.Errorf(codes.FailedPrecondition, "multiple active leases match name %q, use exact lease name", nameOrAlias) + } +} + +func (s *ClientService) hasActiveLeaseWithAlias(ctx context.Context, namespace, alias string) (bool, error) { + aliasReq, err := labels.NewRequirement( + string(jumpstarterdevv1alpha1.LeaseLabelName), + selection.Equals, + []string{alias}, + ) + if err != nil { + return false, err + } + activeReq, err := labels.NewRequirement( + string(jumpstarterdevv1alpha1.LeaseLabelEnded), + selection.DoesNotExist, + []string{}, + ) + if err != nil { + return false, err + } + + var jleases jumpstarterdevv1alpha1.LeaseList + if err := s.List(ctx, &jleases, + kclient.InNamespace(namespace), + kclient.MatchingLabelsSelector{Selector: labels.Everything().Add(*aliasReq).Add(*activeReq)}, + kclient.Limit(1), + ); err != nil { + return false, err + } + return len(jleases.Items) > 0, nil +} + func (s *ClientService) GetLease(ctx context.Context, req *cpb.GetLeaseRequest) (*cpb.Lease, error) { key, err := utils.ParseLeaseIdentifier(req.Name) if err != nil { @@ -121,8 +200,8 @@ func (s *ClientService) GetLease(ctx context.Context, req *cpb.GetLeaseRequest) return nil, err } - var jlease jumpstarterdevv1alpha1.Lease - if err := s.Get(ctx, *key, &jlease); err != nil { + jlease, err := s.resolveLeaseByNameOrAlias(ctx, key.Namespace, key.Name) + if err != nil { return nil, err } @@ -228,19 +307,8 @@ func (s *ClientService) CreateLease(ctx context.Context, req *cpb.CreateLeaseReq return nil, err } - // Use provided lease_id if specified, otherwise generate a UUIDv7 - name := req.LeaseId - if name == "" { - id, err := uuid.NewV7() - if err != nil { - return nil, err - } - name = id.String() - } - jlease, err := jumpstarterdevv1alpha1.LeaseFromProtobuf(req.Lease, types.NamespacedName{ Namespace: namespace, - Name: name, }, corev1.LocalObjectReference{ Name: jclient.Name, }) @@ -248,8 +316,29 @@ func (s *ClientService) CreateLease(ctx context.Context, req *cpb.CreateLeaseReq return nil, err } - if err := s.Create(ctx, jlease); err != nil { - return nil, err + if req.LeaseId != "" { + mu := s.lockAlias(req.LeaseId) + defer mu.Unlock() + exists, err := s.hasActiveLeaseWithAlias(ctx, namespace, req.LeaseId) + if err != nil { + return nil, err + } + if exists { + return nil, status.Errorf(codes.AlreadyExists, "an active lease with name %q already exists", req.LeaseId) + } + jlease.GenerateName = req.LeaseId + "-" + if jlease.Labels == nil { + jlease.Labels = make(map[string]string) + } + jlease.Labels[string(jumpstarterdevv1alpha1.LeaseLabelName)] = req.LeaseId + if err := s.Create(ctx, jlease); err != nil { + return nil, err + } + } else { + jlease.GenerateName = "lease-" + if err := s.Create(ctx, jlease); err != nil { + return nil, err + } } return jlease.ToProtobuf(), nil @@ -280,10 +369,11 @@ func (s *ClientService) UpdateLease(ctx context.Context, req *cpb.UpdateLeaseReq return nil, err } - var jlease jumpstarterdevv1alpha1.Lease - if err := s.Get(ctx, *key, &jlease); err != nil { + resolved, err := s.resolveLeaseByNameOrAlias(ctx, key.Namespace, key.Name) + if err != nil { return nil, err } + jlease := *resolved if jlease.Spec.ClientRef.Name != jclient.Name { return nil, fmt.Errorf("UpdateLease permission denied") @@ -293,7 +383,8 @@ func (s *ClientService) UpdateLease(ctx context.Context, req *cpb.UpdateLeaseReq // Only parse time fields from protobuf if any are being updated if req.Lease.BeginTime != nil || req.Lease.Duration != nil || req.Lease.EndTime != nil { - desired, err := jumpstarterdevv1alpha1.LeaseFromProtobuf(req.Lease, *key, + resolvedKey := types.NamespacedName{Namespace: jlease.Namespace, Name: jlease.Name} + desired, err := jumpstarterdevv1alpha1.LeaseFromProtobuf(req.Lease, resolvedKey, corev1.LocalObjectReference{ Name: jclient.Name, }, @@ -369,8 +460,8 @@ func (s *ClientService) DeleteLease(ctx context.Context, req *cpb.DeleteLeaseReq return nil, err } - var jlease jumpstarterdevv1alpha1.Lease - if err := s.Get(ctx, *key, &jlease); err != nil { + jlease, err := s.resolveLeaseByNameOrAlias(ctx, key.Namespace, key.Name) + if err != nil { return nil, err } @@ -386,7 +477,7 @@ func (s *ClientService) DeleteLease(ctx context.Context, req *cpb.DeleteLeaseReq jlease.Spec.Release = true - if err := s.Patch(ctx, &jlease, original); err != nil { + if err := s.Patch(ctx, jlease, original); err != nil { return nil, err } diff --git a/e2e/test/hooks_test.go b/e2e/test/hooks_test.go index 5da4e447f..59a69997e 100644 --- a/e2e/test/hooks_test.go +++ b/e2e/test/hooks_test.go @@ -260,7 +260,7 @@ var _ = Describe("Hooks E2E Tests", Label("hooks"), Ordered, func() { "--selector", "example.com/board=hooks", "j", "power", "on") Expect(err).NotTo(HaveOccurred(), out) Expect(out).To(ContainSubstring("BEFORE_HOOK:")) - Expect(out).To(MatchRegexp(`lease=[0-9a-f-]+`)) + Expect(out).To(MatchRegexp(`lease=[a-z0-9-]+`)) Expect(out).To(MatchRegexp(`client=`)) }) }) diff --git a/protocol/proto/jumpstarter/client/v1/client.proto b/protocol/proto/jumpstarter/client/v1/client.proto index 1eb76a719..71d8ca6bc 100644 --- a/protocol/proto/jumpstarter/client/v1/client.proto +++ b/protocol/proto/jumpstarter/client/v1/client.proto @@ -141,6 +141,8 @@ message Lease { optional string exporter_name = 12 [(google.api.field_behavior) = IMMUTABLE]; // The set of tags associated with the lease. map tags = 13 [(google.api.field_behavior) = IMMUTABLE]; + // The user-provided alias for this lease (from lease_id at creation time). + optional string alias = 14 [(google.api.field_behavior) = OUTPUT_ONLY]; } // Request to retrieve an exporter. diff --git a/python/packages/jumpstarter-cli/jumpstarter_cli/shell.py b/python/packages/jumpstarter-cli/jumpstarter_cli/shell.py index f02fe5e9a..04eb95c91 100644 --- a/python/packages/jumpstarter-cli/jumpstarter_cli/shell.py +++ b/python/packages/jumpstarter-cli/jumpstarter_cli/shell.py @@ -497,6 +497,8 @@ async def _shell_with_signal_handling( # noqa: C901 def _format_lease_display(lease) -> str: parts = [] + if getattr(lease, "alias", None): + parts.append(f"alias={lease.alias}") if lease.exporter: parts.append(f"exporter={lease.exporter}") if lease.selector: diff --git a/python/packages/jumpstarter-cli/jumpstarter_cli/shell_test.py b/python/packages/jumpstarter-cli/jumpstarter_cli/shell_test.py index 12bcd18ee..1da3438b7 100644 --- a/python/packages/jumpstarter-cli/jumpstarter_cli/shell_test.py +++ b/python/packages/jumpstarter-cli/jumpstarter_cli/shell_test.py @@ -14,6 +14,7 @@ from jumpstarter_cli.shell import ( _attempt_token_recovery, + _format_lease_display, _monitor_token_expiry, _resolve_lease_from_active_async, _run_shell_with_lease_async, @@ -977,3 +978,16 @@ async def fake_run_shell(*_args): ): with pytest.raises((ExporterOfflineError, BaseExceptionGroup)): await _shell_with_signal_handling(config, None, None, None, timedelta(minutes=1), False, (), None) + + +def test_format_lease_display_includes_alias(): + lease = _make_lease("demo-x7k2q") + lease.alias = "demo" + result = _format_lease_display(lease) + assert "alias=demo" in result + + +def test_format_lease_display_no_alias(): + lease = _make_lease("lease-m9p3r") + result = _format_lease_display(lease) + assert "alias" not in result diff --git a/python/packages/jumpstarter-mcp/jumpstarter_mcp/server_test.py b/python/packages/jumpstarter-mcp/jumpstarter_mcp/server_test.py index afb646232..06e0cc5b1 100644 --- a/python/packages/jumpstarter-mcp/jumpstarter_mcp/server_test.py +++ b/python/packages/jumpstarter-mcp/jumpstarter_mcp/server_test.py @@ -26,7 +26,7 @@ _setup_logging, create_server, ) -from jumpstarter_mcp.tools.leases import _lease_status +from jumpstarter_mcp.tools.leases import _lease_status, list_leases # --------------------------------------------------------------------------- # Helpers / fixtures @@ -270,6 +270,40 @@ def test_unknown_when_not_true(self): assert _lease_status(lease) == "unknown" +# --------------------------------------------------------------------------- +# list_leases (unit, mocked config) +# --------------------------------------------------------------------------- + + +@dataclass +class FakeLeaseEntry: + name: str + client: str + exporter: str + selector: str + conditions: list + effective_begin_time: datetime | None = None + effective_end_time: datetime | None = None + duration: None = None + alias: str | None = None + + +@dataclass +class FakeLeaseListResult: + leases: list + + +@pytest.mark.asyncio +async def test_list_leases_includes_alias_when_present(): + lease_with = FakeLeaseEntry(name="demo-x7k2q", client="c", exporter="e", selector="s", conditions=[], alias="demo") + lease_without = FakeLeaseEntry(name="lease-m9p3r", client="c", exporter="e", selector="s", conditions=[]) + config = AsyncMock() + config.list_leases.return_value = FakeLeaseListResult(leases=[lease_with, lease_without]) + result = await list_leases(config) + assert result[0]["alias"] == "demo" + assert "alias" not in result[1] + + # --------------------------------------------------------------------------- # ConnectionManager (unit, no real connections) # --------------------------------------------------------------------------- diff --git a/python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py b/python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py index 63cd798b3..710173461 100644 --- a/python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py +++ b/python/packages/jumpstarter-mcp/jumpstarter_mcp/tools/leases.py @@ -55,7 +55,7 @@ async def list_leases( result = await config.list_leases(filter=selector, only_active=not show_all) leases = [] for lease in result.leases: - leases.append({ + entry = { "name": lease.name, "client": lease.client, "exporter": lease.exporter, @@ -64,7 +64,10 @@ async def list_leases( "begin_time": lease.effective_begin_time.isoformat() if lease.effective_begin_time else None, "end_time": lease.effective_end_time.isoformat() if lease.effective_end_time else None, "duration": str(lease.duration) if lease.duration else None, - }) + } + if getattr(lease, "alias", None): + entry["alias"] = lease.alias + leases.append(entry) return leases diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py index 54c241779..ecfd8a465 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py @@ -34,7 +34,7 @@ from ...v1 import common_pb2 as jumpstarter_dot_v1_dot_common__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"jumpstarter/client/v1/client.proto\x12\x15jumpstarter.client.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1fjumpstarter/v1/kubernetes.proto\x1a\x1bjumpstarter/v1/common.proto\"\x8c\x03\n\x08\x45xporter\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x08R\x04name\x12\x43\n\x06labels\x18\x02 \x03(\x0b\x32+.jumpstarter.client.v1.Exporter.LabelsEntryR\x06labels\x12\x1d\n\x06online\x18\x03 \x01(\x08\x42\x05\x18\x01\xe0\x41\x03R\x06online\x12;\n\x06status\x18\x04 \x01(\x0e\x32\x1e.jumpstarter.v1.ExporterStatusB\x03\xe0\x41\x03R\x06status\x12*\n\x0estatus_message\x18\x05 \x01(\tB\x03\xe0\x41\x03R\rstatusMessage\x1a\x39\n\x0bLabelsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01:_\xea\x41\\\n\x18jumpstarter.dev/Exporter\x12+namespaces/{namespace}/exporters/{exporter}*\texporters2\x08\x65xporter\"\xb5\x08\n\x05Lease\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x08R\x04name\x12\"\n\x08selector\x18\x02 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05R\x08selector\x12:\n\x08\x64uration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00R\x08\x64uration\x88\x01\x01\x12M\n\x12\x65\x66\x66\x65\x63tive_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x03\xe0\x41\x03R\x11\x65\x66\x66\x65\x63tiveDuration\x12>\n\nbegin_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01R\tbeginTime\x88\x01\x01\x12V\n\x14\x65\x66\x66\x65\x63tive_begin_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02R\x12\x65\x66\x66\x65\x63tiveBeginTime\x88\x01\x01\x12:\n\x08\x65nd_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x03R\x07\x65ndTime\x88\x01\x01\x12R\n\x12\x65\x66\x66\x65\x63tive_end_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x04R\x10\x65\x66\x66\x65\x63tiveEndTime\x88\x01\x01\x12;\n\x06\x63lient\x18\t \x01(\tB\x1e\xe0\x41\x03\xfa\x41\x18\n\x16jumpstarter.dev/ClientH\x05R\x06\x63lient\x88\x01\x01\x12\x41\n\x08\x65xporter\x18\n \x01(\tB \xe0\x41\x03\xfa\x41\x1a\n\x18jumpstarter.dev/ExporterH\x06R\x08\x65xporter\x88\x01\x01\x12>\n\nconditions\x18\x0b \x03(\x0b\x32\x19.jumpstarter.v1.ConditionB\x03\xe0\x41\x03R\nconditions\x12-\n\rexporter_name\x18\x0c \x01(\tB\x03\xe0\x41\x05H\x07R\x0c\x65xporterName\x88\x01\x01\x12?\n\x04tags\x18\r \x03(\x0b\x32&.jumpstarter.client.v1.Lease.TagsEntryB\x03\xe0\x41\x05R\x04tags\x1a\x37\n\tTagsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01:P\xea\x41M\n\x15jumpstarter.dev/Lease\x12%namespaces/{namespace}/leases/{lease}*\x06leases2\x05leaseB\x0b\n\t_durationB\r\n\x0b_begin_timeB\x17\n\x15_effective_begin_timeB\x0b\n\t_end_timeB\x15\n\x13_effective_end_timeB\t\n\x07_clientB\x0b\n\t_exporterB\x10\n\x0e_exporter_name\"J\n\x12GetExporterRequest\x12\x34\n\x04name\x18\x01 \x01(\tB \xe0\x41\x02\xfa\x41\x1a\n\x18jumpstarter.dev/ExporterR\x04name\"\xb3\x01\n\x14ListExportersRequest\x12\x38\n\x06parent\x18\x01 \x01(\tB \xe0\x41\x02\xfa\x41\x1a\x12\x18jumpstarter.dev/ExporterR\x06parent\x12 \n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x1b\n\x06\x66ilter\x18\x04 \x01(\tB\x03\xe0\x41\x01R\x06\x66ilter\"~\n\x15ListExportersResponse\x12=\n\texporters\x18\x01 \x03(\x0b\x32\x1f.jumpstarter.client.v1.ExporterR\texporters\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"D\n\x0fGetLeaseRequest\x12\x31\n\x04name\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\n\x15jumpstarter.dev/LeaseR\x04name\"\x8c\x02\n\x11ListLeasesRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\x12\x15jumpstarter.dev/LeaseR\x06parent\x12 \n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x1b\n\x06\x66ilter\x18\x04 \x01(\tB\x03\xe0\x41\x01R\x06\x66ilter\x12)\n\x0bonly_active\x18\x05 \x01(\x08\x42\x03\xe0\x41\x01H\x00R\nonlyActive\x88\x01\x01\x12\"\n\ntag_filter\x18\x06 \x01(\tB\x03\xe0\x41\x01R\ttagFilterB\x0e\n\x0c_only_active\"r\n\x12ListLeasesResponse\x12\x34\n\x06leases\x18\x01 \x03(\x0b\x32\x1c.jumpstarter.client.v1.LeaseR\x06leases\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\xa4\x01\n\x12\x43reateLeaseRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\x12\x15jumpstarter.dev/LeaseR\x06parent\x12\x1e\n\x08lease_id\x18\x02 \x01(\tB\x03\xe0\x41\x01R\x07leaseId\x12\x37\n\x05lease\x18\x03 \x01(\x0b\x32\x1c.jumpstarter.client.v1.LeaseB\x03\xe0\x41\x02R\x05lease\"\x8f\x01\n\x12UpdateLeaseRequest\x12\x37\n\x05lease\x18\x01 \x01(\x0b\x32\x1c.jumpstarter.client.v1.LeaseB\x03\xe0\x41\x02R\x05lease\x12@\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x01R\nupdateMask\"G\n\x12\x44\x65leteLeaseRequest\x12\x31\n\x04name\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\n\x15jumpstarter.dev/LeaseR\x04name\"L\n\x12RotateTokenRequest\x12\x36\n\x06parent\x18\x01 \x01(\tB\x1e\xe0\x41\x02\xfa\x41\x18\x12\x16jumpstarter.dev/ClientR\x06parent\"_\n\x13RotateTokenResponse\x12\x14\n\x05token\x18\x01 \x01(\tR\x05token\x12\x32\n\x06\x65xpiry\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x06\x65xpiry2\xca\t\n\rClientService\x12\x8d\x01\n\x0bGetExporter\x12).jumpstarter.client.v1.GetExporterRequest\x1a\x1f.jumpstarter.client.v1.Exporter\"2\xda\x41\x04name\x82\xd3\xe4\x93\x02%\x12#/v1/{name=namespaces/*/exporters/*}\x12\xa0\x01\n\rListExporters\x12+.jumpstarter.client.v1.ListExportersRequest\x1a,.jumpstarter.client.v1.ListExportersResponse\"4\xda\x41\x06parent\x82\xd3\xe4\x93\x02%\x12#/v1/{parent=namespaces/*}/exporters\x12\x81\x01\n\x08GetLease\x12&.jumpstarter.client.v1.GetLeaseRequest\x1a\x1c.jumpstarter.client.v1.Lease\"/\xda\x41\x04name\x82\xd3\xe4\x93\x02\"\x12 /v1/{name=namespaces/*/leases/*}\x12\x94\x01\n\nListLeases\x12(.jumpstarter.client.v1.ListLeasesRequest\x1a).jumpstarter.client.v1.ListLeasesResponse\"1\xda\x41\x06parent\x82\xd3\xe4\x93\x02\"\x12 /v1/{parent=namespaces/*}/leases\x12\x9f\x01\n\x0b\x43reateLease\x12).jumpstarter.client.v1.CreateLeaseRequest\x1a\x1c.jumpstarter.client.v1.Lease\"G\xda\x41\x15parent,lease,lease_id\x82\xd3\xe4\x93\x02)\" /v1/{parent=namespaces/*}/leases:\x05lease\x12\xa1\x01\n\x0bUpdateLease\x12).jumpstarter.client.v1.UpdateLeaseRequest\x1a\x1c.jumpstarter.client.v1.Lease\"I\xda\x41\x11lease,update_mask\x82\xd3\xe4\x93\x02/2&/v1/{lease.name=namespaces/*/leases/*}:\x05lease\x12\x81\x01\n\x0b\x44\x65leteLease\x12).jumpstarter.client.v1.DeleteLeaseRequest\x1a\x16.google.protobuf.Empty\"/\xda\x41\x04name\x82\xd3\xe4\x93\x02\"* /v1/{name=namespaces/*/leases/*}\x12\xa0\x01\n\x0bRotateToken\x12).jumpstarter.client.v1.RotateTokenRequest\x1a*.jumpstarter.client.v1.RotateTokenResponse\":\xda\x41\x06parent\x82\xd3\xe4\x93\x02+\"&/v1/{parent=namespaces/*}/rotate-token:\x01*B\x9e\x01\n\x19\x63om.jumpstarter.client.v1B\x0b\x43lientProtoP\x01\xa2\x02\x03JCX\xaa\x02\x15Jumpstarter.Client.V1\xca\x02\x15Jumpstarter\\Client\\V1\xe2\x02!Jumpstarter\\Client\\V1\\GPBMetadata\xea\x02\x17Jumpstarter::Client::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"jumpstarter/client/v1/client.proto\x12\x15jumpstarter.client.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1fjumpstarter/v1/kubernetes.proto\x1a\x1bjumpstarter/v1/common.proto\"\x8c\x03\n\x08\x45xporter\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x08R\x04name\x12\x43\n\x06labels\x18\x02 \x03(\x0b\x32+.jumpstarter.client.v1.Exporter.LabelsEntryR\x06labels\x12\x1d\n\x06online\x18\x03 \x01(\x08\x42\x05\x18\x01\xe0\x41\x03R\x06online\x12;\n\x06status\x18\x04 \x01(\x0e\x32\x1e.jumpstarter.v1.ExporterStatusB\x03\xe0\x41\x03R\x06status\x12*\n\x0estatus_message\x18\x05 \x01(\tB\x03\xe0\x41\x03R\rstatusMessage\x1a\x39\n\x0bLabelsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01:_\xea\x41\\\n\x18jumpstarter.dev/Exporter\x12+namespaces/{namespace}/exporters/{exporter}*\texporters2\x08\x65xporter\"\xdf\x08\n\x05Lease\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x08R\x04name\x12\"\n\x08selector\x18\x02 \x01(\tB\x06\xe0\x41\x02\xe0\x41\x05R\x08selector\x12:\n\x08\x64uration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.DurationH\x00R\x08\x64uration\x88\x01\x01\x12M\n\x12\x65\x66\x66\x65\x63tive_duration\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x03\xe0\x41\x03R\x11\x65\x66\x66\x65\x63tiveDuration\x12>\n\nbegin_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01R\tbeginTime\x88\x01\x01\x12V\n\x14\x65\x66\x66\x65\x63tive_begin_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x02R\x12\x65\x66\x66\x65\x63tiveBeginTime\x88\x01\x01\x12:\n\x08\x65nd_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x03R\x07\x65ndTime\x88\x01\x01\x12R\n\x12\x65\x66\x66\x65\x63tive_end_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03H\x04R\x10\x65\x66\x66\x65\x63tiveEndTime\x88\x01\x01\x12;\n\x06\x63lient\x18\t \x01(\tB\x1e\xe0\x41\x03\xfa\x41\x18\n\x16jumpstarter.dev/ClientH\x05R\x06\x63lient\x88\x01\x01\x12\x41\n\x08\x65xporter\x18\n \x01(\tB \xe0\x41\x03\xfa\x41\x1a\n\x18jumpstarter.dev/ExporterH\x06R\x08\x65xporter\x88\x01\x01\x12>\n\nconditions\x18\x0b \x03(\x0b\x32\x19.jumpstarter.v1.ConditionB\x03\xe0\x41\x03R\nconditions\x12-\n\rexporter_name\x18\x0c \x01(\tB\x03\xe0\x41\x05H\x07R\x0c\x65xporterName\x88\x01\x01\x12?\n\x04tags\x18\r \x03(\x0b\x32&.jumpstarter.client.v1.Lease.TagsEntryB\x03\xe0\x41\x05R\x04tags\x12\x1e\n\x05\x61lias\x18\x0e \x01(\tB\x03\xe0\x41\x03H\x08R\x05\x61lias\x88\x01\x01\x1a\x37\n\tTagsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01:P\xea\x41M\n\x15jumpstarter.dev/Lease\x12%namespaces/{namespace}/leases/{lease}*\x06leases2\x05leaseB\x0b\n\t_durationB\r\n\x0b_begin_timeB\x17\n\x15_effective_begin_timeB\x0b\n\t_end_timeB\x15\n\x13_effective_end_timeB\t\n\x07_clientB\x0b\n\t_exporterB\x10\n\x0e_exporter_nameB\x08\n\x06_alias\"J\n\x12GetExporterRequest\x12\x34\n\x04name\x18\x01 \x01(\tB \xe0\x41\x02\xfa\x41\x1a\n\x18jumpstarter.dev/ExporterR\x04name\"\xb3\x01\n\x14ListExportersRequest\x12\x38\n\x06parent\x18\x01 \x01(\tB \xe0\x41\x02\xfa\x41\x1a\x12\x18jumpstarter.dev/ExporterR\x06parent\x12 \n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x1b\n\x06\x66ilter\x18\x04 \x01(\tB\x03\xe0\x41\x01R\x06\x66ilter\"~\n\x15ListExportersResponse\x12=\n\texporters\x18\x01 \x03(\x0b\x32\x1f.jumpstarter.client.v1.ExporterR\texporters\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"D\n\x0fGetLeaseRequest\x12\x31\n\x04name\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\n\x15jumpstarter.dev/LeaseR\x04name\"\x8c\x02\n\x11ListLeasesRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\x12\x15jumpstarter.dev/LeaseR\x06parent\x12 \n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x1b\n\x06\x66ilter\x18\x04 \x01(\tB\x03\xe0\x41\x01R\x06\x66ilter\x12)\n\x0bonly_active\x18\x05 \x01(\x08\x42\x03\xe0\x41\x01H\x00R\nonlyActive\x88\x01\x01\x12\"\n\ntag_filter\x18\x06 \x01(\tB\x03\xe0\x41\x01R\ttagFilterB\x0e\n\x0c_only_active\"r\n\x12ListLeasesResponse\x12\x34\n\x06leases\x18\x01 \x03(\x0b\x32\x1c.jumpstarter.client.v1.LeaseR\x06leases\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\xa4\x01\n\x12\x43reateLeaseRequest\x12\x35\n\x06parent\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\x12\x15jumpstarter.dev/LeaseR\x06parent\x12\x1e\n\x08lease_id\x18\x02 \x01(\tB\x03\xe0\x41\x01R\x07leaseId\x12\x37\n\x05lease\x18\x03 \x01(\x0b\x32\x1c.jumpstarter.client.v1.LeaseB\x03\xe0\x41\x02R\x05lease\"\x8f\x01\n\x12UpdateLeaseRequest\x12\x37\n\x05lease\x18\x01 \x01(\x0b\x32\x1c.jumpstarter.client.v1.LeaseB\x03\xe0\x41\x02R\x05lease\x12@\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x01R\nupdateMask\"G\n\x12\x44\x65leteLeaseRequest\x12\x31\n\x04name\x18\x01 \x01(\tB\x1d\xe0\x41\x02\xfa\x41\x17\n\x15jumpstarter.dev/LeaseR\x04name\"L\n\x12RotateTokenRequest\x12\x36\n\x06parent\x18\x01 \x01(\tB\x1e\xe0\x41\x02\xfa\x41\x18\x12\x16jumpstarter.dev/ClientR\x06parent\"_\n\x13RotateTokenResponse\x12\x14\n\x05token\x18\x01 \x01(\tR\x05token\x12\x32\n\x06\x65xpiry\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x06\x65xpiry2\xca\t\n\rClientService\x12\x8d\x01\n\x0bGetExporter\x12).jumpstarter.client.v1.GetExporterRequest\x1a\x1f.jumpstarter.client.v1.Exporter\"2\xda\x41\x04name\x82\xd3\xe4\x93\x02%\x12#/v1/{name=namespaces/*/exporters/*}\x12\xa0\x01\n\rListExporters\x12+.jumpstarter.client.v1.ListExportersRequest\x1a,.jumpstarter.client.v1.ListExportersResponse\"4\xda\x41\x06parent\x82\xd3\xe4\x93\x02%\x12#/v1/{parent=namespaces/*}/exporters\x12\x81\x01\n\x08GetLease\x12&.jumpstarter.client.v1.GetLeaseRequest\x1a\x1c.jumpstarter.client.v1.Lease\"/\xda\x41\x04name\x82\xd3\xe4\x93\x02\"\x12 /v1/{name=namespaces/*/leases/*}\x12\x94\x01\n\nListLeases\x12(.jumpstarter.client.v1.ListLeasesRequest\x1a).jumpstarter.client.v1.ListLeasesResponse\"1\xda\x41\x06parent\x82\xd3\xe4\x93\x02\"\x12 /v1/{parent=namespaces/*}/leases\x12\x9f\x01\n\x0b\x43reateLease\x12).jumpstarter.client.v1.CreateLeaseRequest\x1a\x1c.jumpstarter.client.v1.Lease\"G\xda\x41\x15parent,lease,lease_id\x82\xd3\xe4\x93\x02)\" /v1/{parent=namespaces/*}/leases:\x05lease\x12\xa1\x01\n\x0bUpdateLease\x12).jumpstarter.client.v1.UpdateLeaseRequest\x1a\x1c.jumpstarter.client.v1.Lease\"I\xda\x41\x11lease,update_mask\x82\xd3\xe4\x93\x02/2&/v1/{lease.name=namespaces/*/leases/*}:\x05lease\x12\x81\x01\n\x0b\x44\x65leteLease\x12).jumpstarter.client.v1.DeleteLeaseRequest\x1a\x16.google.protobuf.Empty\"/\xda\x41\x04name\x82\xd3\xe4\x93\x02\"* /v1/{name=namespaces/*/leases/*}\x12\xa0\x01\n\x0bRotateToken\x12).jumpstarter.client.v1.RotateTokenRequest\x1a*.jumpstarter.client.v1.RotateTokenResponse\":\xda\x41\x06parent\x82\xd3\xe4\x93\x02+\"&/v1/{parent=namespaces/*}/rotate-token:\x01*B\x9e\x01\n\x19\x63om.jumpstarter.client.v1B\x0b\x43lientProtoP\x01\xa2\x02\x03JCX\xaa\x02\x15Jumpstarter.Client.V1\xca\x02\x15Jumpstarter\\Client\\V1\xe2\x02!Jumpstarter\\Client\\V1\\GPBMetadata\xea\x02\x17Jumpstarter::Client::V1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -76,6 +76,8 @@ _globals['_LEASE'].fields_by_name['exporter_name']._serialized_options = b'\340A\005' _globals['_LEASE'].fields_by_name['tags']._loaded_options = None _globals['_LEASE'].fields_by_name['tags']._serialized_options = b'\340A\005' + _globals['_LEASE'].fields_by_name['alias']._loaded_options = None + _globals['_LEASE'].fields_by_name['alias']._serialized_options = b'\340A\003' _globals['_LEASE']._loaded_options = None _globals['_LEASE']._serialized_options = b'\352AM\n\025jumpstarter.dev/Lease\022%namespaces/{namespace}/leases/{lease}*\006leases2\005lease' _globals['_GETEXPORTERREQUEST'].fields_by_name['name']._loaded_options = None @@ -137,31 +139,31 @@ _globals['_EXPORTER_LABELSENTRY']._serialized_start=609 _globals['_EXPORTER_LABELSENTRY']._serialized_end=666 _globals['_LEASE']._serialized_start=766 - _globals['_LEASE']._serialized_end=1843 - _globals['_LEASE_TAGSENTRY']._serialized_start=1575 - _globals['_LEASE_TAGSENTRY']._serialized_end=1630 - _globals['_GETEXPORTERREQUEST']._serialized_start=1845 - _globals['_GETEXPORTERREQUEST']._serialized_end=1919 - _globals['_LISTEXPORTERSREQUEST']._serialized_start=1922 - _globals['_LISTEXPORTERSREQUEST']._serialized_end=2101 - _globals['_LISTEXPORTERSRESPONSE']._serialized_start=2103 - _globals['_LISTEXPORTERSRESPONSE']._serialized_end=2229 - _globals['_GETLEASEREQUEST']._serialized_start=2231 - _globals['_GETLEASEREQUEST']._serialized_end=2299 - _globals['_LISTLEASESREQUEST']._serialized_start=2302 - _globals['_LISTLEASESREQUEST']._serialized_end=2570 - _globals['_LISTLEASESRESPONSE']._serialized_start=2572 - _globals['_LISTLEASESRESPONSE']._serialized_end=2686 - _globals['_CREATELEASEREQUEST']._serialized_start=2689 - _globals['_CREATELEASEREQUEST']._serialized_end=2853 - _globals['_UPDATELEASEREQUEST']._serialized_start=2856 - _globals['_UPDATELEASEREQUEST']._serialized_end=2999 - _globals['_DELETELEASEREQUEST']._serialized_start=3001 - _globals['_DELETELEASEREQUEST']._serialized_end=3072 - _globals['_ROTATETOKENREQUEST']._serialized_start=3074 - _globals['_ROTATETOKENREQUEST']._serialized_end=3150 - _globals['_ROTATETOKENRESPONSE']._serialized_start=3152 - _globals['_ROTATETOKENRESPONSE']._serialized_end=3247 - _globals['_CLIENTSERVICE']._serialized_start=3250 - _globals['_CLIENTSERVICE']._serialized_end=4476 + _globals['_LEASE']._serialized_end=1885 + _globals['_LEASE_TAGSENTRY']._serialized_start=1607 + _globals['_LEASE_TAGSENTRY']._serialized_end=1662 + _globals['_GETEXPORTERREQUEST']._serialized_start=1887 + _globals['_GETEXPORTERREQUEST']._serialized_end=1961 + _globals['_LISTEXPORTERSREQUEST']._serialized_start=1964 + _globals['_LISTEXPORTERSREQUEST']._serialized_end=2143 + _globals['_LISTEXPORTERSRESPONSE']._serialized_start=2145 + _globals['_LISTEXPORTERSRESPONSE']._serialized_end=2271 + _globals['_GETLEASEREQUEST']._serialized_start=2273 + _globals['_GETLEASEREQUEST']._serialized_end=2341 + _globals['_LISTLEASESREQUEST']._serialized_start=2344 + _globals['_LISTLEASESREQUEST']._serialized_end=2612 + _globals['_LISTLEASESRESPONSE']._serialized_start=2614 + _globals['_LISTLEASESRESPONSE']._serialized_end=2728 + _globals['_CREATELEASEREQUEST']._serialized_start=2731 + _globals['_CREATELEASEREQUEST']._serialized_end=2895 + _globals['_UPDATELEASEREQUEST']._serialized_start=2898 + _globals['_UPDATELEASEREQUEST']._serialized_end=3041 + _globals['_DELETELEASEREQUEST']._serialized_start=3043 + _globals['_DELETELEASEREQUEST']._serialized_end=3114 + _globals['_ROTATETOKENREQUEST']._serialized_start=3116 + _globals['_ROTATETOKENREQUEST']._serialized_end=3192 + _globals['_ROTATETOKENRESPONSE']._serialized_start=3194 + _globals['_ROTATETOKENRESPONSE']._serialized_end=3289 + _globals['_CLIENTSERVICE']._serialized_start=3292 + _globals['_CLIENTSERVICE']._serialized_end=4518 # @@protoc_insertion_point(module_scope) diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi index 0ba6559be..425930cb9 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.pyi @@ -31,6 +31,8 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor @typing.final class Exporter(google.protobuf.message.Message): + """An exporter resource representing a registered device provider.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor @typing.final @@ -55,11 +57,17 @@ class Exporter(google.protobuf.message.Message): STATUS_FIELD_NUMBER: builtins.int STATUS_MESSAGE_FIELD_NUMBER: builtins.int name: builtins.str + """The resource name of the exporter.""" online: builtins.bool + """Whether the exporter is currently online. Deprecated in favor of the status field.""" status: jumpstarter.v1.common_pb2.ExporterStatus.ValueType + """The current status of the exporter.""" status_message: builtins.str + """A human-readable message providing details about the exporter status.""" @property - def labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ... + def labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """The set of labels associated with the exporter.""" + def __init__( self, *, @@ -75,6 +83,8 @@ Global___Exporter: typing_extensions.TypeAlias = Exporter @typing.final class Lease(google.protobuf.message.Message): + """A lease resource representing a reservation of an exporter.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor @typing.final @@ -106,27 +116,51 @@ class Lease(google.protobuf.message.Message): CONDITIONS_FIELD_NUMBER: builtins.int EXPORTER_NAME_FIELD_NUMBER: builtins.int TAGS_FIELD_NUMBER: builtins.int + ALIAS_FIELD_NUMBER: builtins.int name: builtins.str + """The resource name of the lease.""" selector: builtins.str + """The label selector expression used to match an exporter.""" client: builtins.str + """The resource name of the client that owns this lease.""" exporter: builtins.str + """The resource name of the exporter assigned to this lease.""" exporter_name: builtins.str + """The name of a specific exporter to target for the lease.""" + alias: builtins.str + """The user-provided alias for this lease (from lease_id at creation time).""" @property - def duration(self) -> google.protobuf.duration_pb2.Duration: ... + def duration(self) -> google.protobuf.duration_pb2.Duration: + """The requested duration of the lease.""" + @property - def effective_duration(self) -> google.protobuf.duration_pb2.Duration: ... + def effective_duration(self) -> google.protobuf.duration_pb2.Duration: + """The server-computed effective duration of the lease.""" + @property - def begin_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def begin_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The requested begin time of the lease.""" + @property - def effective_begin_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def effective_begin_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The server-computed effective begin time of the lease.""" + @property - def end_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def end_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The requested end time of the lease.""" + @property - def effective_end_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def effective_end_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The server-computed effective end time of the lease.""" + @property - def conditions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[jumpstarter.v1.kubernetes_pb2.Condition]: ... + def conditions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[jumpstarter.v1.kubernetes_pb2.Condition]: + """The list of conditions reflecting the current state of the lease.""" + @property - def tags(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ... + def tags(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """The set of tags associated with the lease.""" + def __init__( self, *, @@ -143,9 +177,12 @@ class Lease(google.protobuf.message.Message): conditions: collections.abc.Iterable[jumpstarter.v1.kubernetes_pb2.Condition] | None = ..., exporter_name: builtins.str | None = ..., tags: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., + alias: builtins.str | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["_begin_time", b"_begin_time", "_client", b"_client", "_duration", b"_duration", "_effective_begin_time", b"_effective_begin_time", "_effective_end_time", b"_effective_end_time", "_end_time", b"_end_time", "_exporter", b"_exporter", "_exporter_name", b"_exporter_name", "begin_time", b"begin_time", "client", b"client", "duration", b"duration", "effective_begin_time", b"effective_begin_time", "effective_duration", b"effective_duration", "effective_end_time", b"effective_end_time", "end_time", b"end_time", "exporter", b"exporter", "exporter_name", b"exporter_name"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["_begin_time", b"_begin_time", "_client", b"_client", "_duration", b"_duration", "_effective_begin_time", b"_effective_begin_time", "_effective_end_time", b"_effective_end_time", "_end_time", b"_end_time", "_exporter", b"_exporter", "_exporter_name", b"_exporter_name", "begin_time", b"begin_time", "client", b"client", "conditions", b"conditions", "duration", b"duration", "effective_begin_time", b"effective_begin_time", "effective_duration", b"effective_duration", "effective_end_time", b"effective_end_time", "end_time", b"end_time", "exporter", b"exporter", "exporter_name", b"exporter_name", "name", b"name", "selector", b"selector", "tags", b"tags"]) -> None: ... + def HasField(self, field_name: typing.Literal["_alias", b"_alias", "_begin_time", b"_begin_time", "_client", b"_client", "_duration", b"_duration", "_effective_begin_time", b"_effective_begin_time", "_effective_end_time", b"_effective_end_time", "_end_time", b"_end_time", "_exporter", b"_exporter", "_exporter_name", b"_exporter_name", "alias", b"alias", "begin_time", b"begin_time", "client", b"client", "duration", b"duration", "effective_begin_time", b"effective_begin_time", "effective_duration", b"effective_duration", "effective_end_time", b"effective_end_time", "end_time", b"end_time", "exporter", b"exporter", "exporter_name", b"exporter_name"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_alias", b"_alias", "_begin_time", b"_begin_time", "_client", b"_client", "_duration", b"_duration", "_effective_begin_time", b"_effective_begin_time", "_effective_end_time", b"_effective_end_time", "_end_time", b"_end_time", "_exporter", b"_exporter", "_exporter_name", b"_exporter_name", "alias", b"alias", "begin_time", b"begin_time", "client", b"client", "conditions", b"conditions", "duration", b"duration", "effective_begin_time", b"effective_begin_time", "effective_duration", b"effective_duration", "effective_end_time", b"effective_end_time", "end_time", b"end_time", "exporter", b"exporter", "exporter_name", b"exporter_name", "name", b"name", "selector", b"selector", "tags", b"tags"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_alias", b"_alias"]) -> typing.Literal["alias"] | None: ... @typing.overload def WhichOneof(self, oneof_group: typing.Literal["_begin_time", b"_begin_time"]) -> typing.Literal["begin_time"] | None: ... @typing.overload @@ -167,10 +204,13 @@ Global___Lease: typing_extensions.TypeAlias = Lease @typing.final class GetExporterRequest(google.protobuf.message.Message): + """Request to retrieve an exporter.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAME_FIELD_NUMBER: builtins.int name: builtins.str + """The resource name of the exporter.""" def __init__( self, *, @@ -182,6 +222,8 @@ Global___GetExporterRequest: typing_extensions.TypeAlias = GetExporterRequest @typing.final class ListExportersRequest(google.protobuf.message.Message): + """Request to list exporters.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor PARENT_FIELD_NUMBER: builtins.int @@ -189,9 +231,13 @@ class ListExportersRequest(google.protobuf.message.Message): PAGE_TOKEN_FIELD_NUMBER: builtins.int FILTER_FIELD_NUMBER: builtins.int parent: builtins.str + """The parent resource name (namespace).""" page_size: builtins.int + """Maximum number of results to return.""" page_token: builtins.str + """Token for retrieving the next page of results.""" filter: builtins.str + """Filter expression for the results.""" def __init__( self, *, @@ -206,13 +252,18 @@ Global___ListExportersRequest: typing_extensions.TypeAlias = ListExportersReques @typing.final class ListExportersResponse(google.protobuf.message.Message): + """Response containing a list of exporters.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor EXPORTERS_FIELD_NUMBER: builtins.int NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int next_page_token: builtins.str + """Token for the next page of results.""" @property - def exporters(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___Exporter]: ... + def exporters(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___Exporter]: + """The list of exporters.""" + def __init__( self, *, @@ -225,10 +276,13 @@ Global___ListExportersResponse: typing_extensions.TypeAlias = ListExportersRespo @typing.final class GetLeaseRequest(google.protobuf.message.Message): + """Request to retrieve a lease.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAME_FIELD_NUMBER: builtins.int name: builtins.str + """The resource name of the lease.""" def __init__( self, *, @@ -240,6 +294,8 @@ Global___GetLeaseRequest: typing_extensions.TypeAlias = GetLeaseRequest @typing.final class ListLeasesRequest(google.protobuf.message.Message): + """Request to list leases.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor PARENT_FIELD_NUMBER: builtins.int @@ -249,11 +305,17 @@ class ListLeasesRequest(google.protobuf.message.Message): ONLY_ACTIVE_FIELD_NUMBER: builtins.int TAG_FILTER_FIELD_NUMBER: builtins.int parent: builtins.str + """The parent resource name (namespace).""" page_size: builtins.int + """Maximum number of results to return.""" page_token: builtins.str + """Token for retrieving the next page of results.""" filter: builtins.str + """Filter expression for the results.""" only_active: builtins.bool + """If true, return only active leases.""" tag_filter: builtins.str + """Filter expression for lease tags.""" def __init__( self, *, @@ -272,13 +334,18 @@ Global___ListLeasesRequest: typing_extensions.TypeAlias = ListLeasesRequest @typing.final class ListLeasesResponse(google.protobuf.message.Message): + """Response containing a list of leases.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor LEASES_FIELD_NUMBER: builtins.int NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int next_page_token: builtins.str + """Token for the next page of results.""" @property - def leases(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___Lease]: ... + def leases(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___Lease]: + """The list of leases.""" + def __init__( self, *, @@ -291,15 +358,21 @@ Global___ListLeasesResponse: typing_extensions.TypeAlias = ListLeasesResponse @typing.final class CreateLeaseRequest(google.protobuf.message.Message): + """Request to create a lease.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor PARENT_FIELD_NUMBER: builtins.int LEASE_ID_FIELD_NUMBER: builtins.int LEASE_FIELD_NUMBER: builtins.int parent: builtins.str + """The parent resource name (namespace).""" lease_id: builtins.str + """The client-assigned identifier for the lease.""" @property - def lease(self) -> Global___Lease: ... + def lease(self) -> Global___Lease: + """The lease resource to create.""" + def __init__( self, *, @@ -314,14 +387,20 @@ Global___CreateLeaseRequest: typing_extensions.TypeAlias = CreateLeaseRequest @typing.final class UpdateLeaseRequest(google.protobuf.message.Message): + """Request to update a lease.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor LEASE_FIELD_NUMBER: builtins.int UPDATE_MASK_FIELD_NUMBER: builtins.int @property - def lease(self) -> Global___Lease: ... + def lease(self) -> Global___Lease: + """The lease resource with updated fields.""" + @property - def update_mask(self) -> google.protobuf.field_mask_pb2.FieldMask: ... + def update_mask(self) -> google.protobuf.field_mask_pb2.FieldMask: + """The set of fields to update.""" + def __init__( self, *, @@ -335,10 +414,13 @@ Global___UpdateLeaseRequest: typing_extensions.TypeAlias = UpdateLeaseRequest @typing.final class DeleteLeaseRequest(google.protobuf.message.Message): + """Request to delete a lease.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAME_FIELD_NUMBER: builtins.int name: builtins.str + """The resource name of the lease.""" def __init__( self, *, @@ -350,10 +432,13 @@ Global___DeleteLeaseRequest: typing_extensions.TypeAlias = DeleteLeaseRequest @typing.final class RotateTokenRequest(google.protobuf.message.Message): + """Request to rotate the authentication token for a client.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor PARENT_FIELD_NUMBER: builtins.int parent: builtins.str + """The parent resource name (namespace).""" def __init__( self, *, @@ -365,13 +450,18 @@ Global___RotateTokenRequest: typing_extensions.TypeAlias = RotateTokenRequest @typing.final class RotateTokenResponse(google.protobuf.message.Message): + """Response containing the newly rotated token.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor TOKEN_FIELD_NUMBER: builtins.int EXPIRY_FIELD_NUMBER: builtins.int token: builtins.str + """The new authentication token.""" @property - def expiry(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def expiry(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The expiration time of the new token.""" + def __init__( self, *, diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.py b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.py index ea4309ae7..88e3e0239 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.py +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.py @@ -7,7 +7,8 @@ class ClientServiceStub(object): - """Missing associated documentation comment in .proto file.""" + """Client-facing API service for managing exporters and leases. + """ def __init__(self, channel): """Constructor. @@ -58,52 +59,61 @@ def __init__(self, channel): class ClientServiceServicer(object): - """Missing associated documentation comment in .proto file.""" + """Client-facing API service for managing exporters and leases. + """ def GetExporter(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Retrieve a single exporter by resource name. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ListExporters(self, request, context): - """Missing associated documentation comment in .proto file.""" + """List exporters in a namespace with optional filtering. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetLease(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Retrieve a single lease by resource name. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ListLeases(self, request, context): - """Missing associated documentation comment in .proto file.""" + """List leases in a namespace with optional filtering. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def CreateLease(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Create a new lease for an exporter. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def UpdateLease(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Update an existing lease. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def DeleteLease(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Delete a lease by resource name. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RotateToken(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Rotate the authentication token for the client. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') @@ -160,7 +170,8 @@ def add_ClientServiceServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. class ClientService(object): - """Missing associated documentation comment in .proto file.""" + """Client-facing API service for managing exporters and leases. + """ @staticmethod def GetExporter(request, diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.pyi index f32e431fa..a79461db3 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2_grpc.pyi @@ -161,6 +161,8 @@ _ClientServiceRotateTokenType = typing_extensions.TypeVar( ) class ClientServiceStub(typing.Generic[_ClientServiceGetExporterType, _ClientServiceListExportersType, _ClientServiceGetLeaseType, _ClientServiceListLeasesType, _ClientServiceCreateLeaseType, _ClientServiceUpdateLeaseType, _ClientServiceDeleteLeaseType, _ClientServiceRotateTokenType]): + """Client-facing API service for managing exporters and leases.""" + @typing.overload def __init__(self: ClientServiceStub[ grpc.UnaryUnaryMultiCallable[ @@ -234,20 +236,28 @@ class ClientServiceStub(typing.Generic[_ClientServiceGetExporterType, _ClientSer ], channel: grpc.aio.Channel) -> None: ... GetExporter: _ClientServiceGetExporterType + """Retrieve a single exporter by resource name.""" ListExporters: _ClientServiceListExportersType + """List exporters in a namespace with optional filtering.""" GetLease: _ClientServiceGetLeaseType + """Retrieve a single lease by resource name.""" ListLeases: _ClientServiceListLeasesType + """List leases in a namespace with optional filtering.""" CreateLease: _ClientServiceCreateLeaseType + """Create a new lease for an exporter.""" UpdateLease: _ClientServiceUpdateLeaseType + """Update an existing lease.""" DeleteLease: _ClientServiceDeleteLeaseType + """Delete a lease by resource name.""" RotateToken: _ClientServiceRotateTokenType + """Rotate the authentication token for the client.""" ClientServiceAsyncStub: typing_extensions.TypeAlias = ClientServiceStub[ grpc.aio.UnaryUnaryMultiCallable[ @@ -285,60 +295,70 @@ ClientServiceAsyncStub: typing_extensions.TypeAlias = ClientServiceStub[ ] class ClientServiceServicer(metaclass=abc.ABCMeta): + """Client-facing API service for managing exporters and leases.""" + @abc.abstractmethod def GetExporter( self, request: jumpstarter.client.v1.client_pb2.GetExporterRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.client.v1.client_pb2.Exporter, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Exporter]]: ... + ) -> typing.Union[jumpstarter.client.v1.client_pb2.Exporter, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Exporter]]: + """Retrieve a single exporter by resource name.""" @abc.abstractmethod def ListExporters( self, request: jumpstarter.client.v1.client_pb2.ListExportersRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.client.v1.client_pb2.ListExportersResponse, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.ListExportersResponse]]: ... + ) -> typing.Union[jumpstarter.client.v1.client_pb2.ListExportersResponse, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.ListExportersResponse]]: + """List exporters in a namespace with optional filtering.""" @abc.abstractmethod def GetLease( self, request: jumpstarter.client.v1.client_pb2.GetLeaseRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.client.v1.client_pb2.Lease, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Lease]]: ... + ) -> typing.Union[jumpstarter.client.v1.client_pb2.Lease, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Lease]]: + """Retrieve a single lease by resource name.""" @abc.abstractmethod def ListLeases( self, request: jumpstarter.client.v1.client_pb2.ListLeasesRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.client.v1.client_pb2.ListLeasesResponse, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.ListLeasesResponse]]: ... + ) -> typing.Union[jumpstarter.client.v1.client_pb2.ListLeasesResponse, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.ListLeasesResponse]]: + """List leases in a namespace with optional filtering.""" @abc.abstractmethod def CreateLease( self, request: jumpstarter.client.v1.client_pb2.CreateLeaseRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.client.v1.client_pb2.Lease, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Lease]]: ... + ) -> typing.Union[jumpstarter.client.v1.client_pb2.Lease, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Lease]]: + """Create a new lease for an exporter.""" @abc.abstractmethod def UpdateLease( self, request: jumpstarter.client.v1.client_pb2.UpdateLeaseRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.client.v1.client_pb2.Lease, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Lease]]: ... + ) -> typing.Union[jumpstarter.client.v1.client_pb2.Lease, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.Lease]]: + """Update an existing lease.""" @abc.abstractmethod def DeleteLease( self, request: jumpstarter.client.v1.client_pb2.DeleteLeaseRequest, context: _ServicerContext, - ) -> typing.Union[google.protobuf.empty_pb2.Empty, collections.abc.Awaitable[google.protobuf.empty_pb2.Empty]]: ... + ) -> typing.Union[google.protobuf.empty_pb2.Empty, collections.abc.Awaitable[google.protobuf.empty_pb2.Empty]]: + """Delete a lease by resource name.""" @abc.abstractmethod def RotateToken( self, request: jumpstarter.client.v1.client_pb2.RotateTokenRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.client.v1.client_pb2.RotateTokenResponse, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.RotateTokenResponse]]: ... + ) -> typing.Union[jumpstarter.client.v1.client_pb2.RotateTokenResponse, collections.abc.Awaitable[jumpstarter.client.v1.client_pb2.RotateTokenResponse]]: + """Rotate the authentication token for the client.""" def add_ClientServiceServicer_to_server(servicer: ClientServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/common_pb2.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/common_pb2.pyi index f433f1db2..c108b5bff 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/common_pb2.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/common_pb2.pyi @@ -23,44 +23,44 @@ class _ExporterStatus: class _ExporterStatusEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_ExporterStatus.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor EXPORTER_STATUS_UNSPECIFIED: _ExporterStatus.ValueType # 0 - """Unspecified exporter status""" + """Unspecified exporter status.""" EXPORTER_STATUS_OFFLINE: _ExporterStatus.ValueType # 1 - """Exporter is offline""" + """Exporter is offline.""" EXPORTER_STATUS_AVAILABLE: _ExporterStatus.ValueType # 2 - """Exporter is available to be leased""" + """Exporter is available to be leased.""" EXPORTER_STATUS_BEFORE_LEASE_HOOK: _ExporterStatus.ValueType # 3 - """Exporter is executing before lease hook(s)""" + """Exporter is executing before lease hook(s).""" EXPORTER_STATUS_LEASE_READY: _ExporterStatus.ValueType # 4 - """Exporter is leased and ready to accept commands""" + """Exporter is leased and ready to accept commands.""" EXPORTER_STATUS_AFTER_LEASE_HOOK: _ExporterStatus.ValueType # 5 - """Exporter is executing after lease hook(s)""" + """Exporter is executing after lease hook(s).""" EXPORTER_STATUS_BEFORE_LEASE_HOOK_FAILED: _ExporterStatus.ValueType # 6 - """Exporter before lease hook failed""" + """Exporter before lease hook failed.""" EXPORTER_STATUS_AFTER_LEASE_HOOK_FAILED: _ExporterStatus.ValueType # 7 - """Exporter after lease hook failed""" + """Exporter after lease hook failed.""" class ExporterStatus(_ExporterStatus, metaclass=_ExporterStatusEnumTypeWrapper): - """Shared types used across multiple Jumpstarter services + """Shared types used across multiple Jumpstarter services. - Exporter status information + Exporter status information. """ EXPORTER_STATUS_UNSPECIFIED: ExporterStatus.ValueType # 0 -"""Unspecified exporter status""" +"""Unspecified exporter status.""" EXPORTER_STATUS_OFFLINE: ExporterStatus.ValueType # 1 -"""Exporter is offline""" +"""Exporter is offline.""" EXPORTER_STATUS_AVAILABLE: ExporterStatus.ValueType # 2 -"""Exporter is available to be leased""" +"""Exporter is available to be leased.""" EXPORTER_STATUS_BEFORE_LEASE_HOOK: ExporterStatus.ValueType # 3 -"""Exporter is executing before lease hook(s)""" +"""Exporter is executing before lease hook(s).""" EXPORTER_STATUS_LEASE_READY: ExporterStatus.ValueType # 4 -"""Exporter is leased and ready to accept commands""" +"""Exporter is leased and ready to accept commands.""" EXPORTER_STATUS_AFTER_LEASE_HOOK: ExporterStatus.ValueType # 5 -"""Exporter is executing after lease hook(s)""" +"""Exporter is executing after lease hook(s).""" EXPORTER_STATUS_BEFORE_LEASE_HOOK_FAILED: ExporterStatus.ValueType # 6 -"""Exporter before lease hook failed""" +"""Exporter before lease hook failed.""" EXPORTER_STATUS_AFTER_LEASE_HOOK_FAILED: ExporterStatus.ValueType # 7 -"""Exporter after lease hook failed""" +"""Exporter after lease hook failed.""" Global___ExporterStatus: typing_extensions.TypeAlias = ExporterStatus class _LogSource: @@ -70,27 +70,27 @@ class _LogSource: class _LogSourceEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_LogSource.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor LOG_SOURCE_UNSPECIFIED: _LogSource.ValueType # 0 - """Unspecified log source""" + """Unspecified log source.""" LOG_SOURCE_DRIVER: _LogSource.ValueType # 1 - """Driver/device logs""" + """Driver/device logs.""" LOG_SOURCE_BEFORE_LEASE_HOOK: _LogSource.ValueType # 2 - """beforeLease hook execution logs""" + """beforeLease hook execution logs.""" LOG_SOURCE_AFTER_LEASE_HOOK: _LogSource.ValueType # 3 - """afterLease hook execution logs""" + """afterLease hook execution logs.""" LOG_SOURCE_SYSTEM: _LogSource.ValueType # 4 - """System/exporter logs""" + """System/exporter logs.""" class LogSource(_LogSource, metaclass=_LogSourceEnumTypeWrapper): - """Source of log stream messages""" + """Source of log stream messages.""" LOG_SOURCE_UNSPECIFIED: LogSource.ValueType # 0 -"""Unspecified log source""" +"""Unspecified log source.""" LOG_SOURCE_DRIVER: LogSource.ValueType # 1 -"""Driver/device logs""" +"""Driver/device logs.""" LOG_SOURCE_BEFORE_LEASE_HOOK: LogSource.ValueType # 2 -"""beforeLease hook execution logs""" +"""beforeLease hook execution logs.""" LOG_SOURCE_AFTER_LEASE_HOOK: LogSource.ValueType # 3 -"""afterLease hook execution logs""" +"""afterLease hook execution logs.""" LOG_SOURCE_SYSTEM: LogSource.ValueType # 4 -"""System/exporter logs""" +"""System/exporter logs.""" Global___LogSource: typing_extensions.TypeAlias = LogSource diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.pyi index adcb658cd..8c1c4fc7c 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.pyi @@ -25,6 +25,8 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor @typing.final class RegisterRequest(google.protobuf.message.Message): + """Registration request sent by an exporter to the controller.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor @typing.final @@ -47,16 +49,11 @@ class RegisterRequest(google.protobuf.message.Message): REPORTS_FIELD_NUMBER: builtins.int @property def labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: - """additional context: - - token/authentication mechanism - """ + """Key-value metadata labels.""" @property def reports(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___DriverInstanceReport]: - """standard labels: - jumpstarter.dev/hostname= - jumpstarter.dev/name= - """ + """Driver instance reports for this exporter.""" def __init__( self, @@ -70,6 +67,8 @@ Global___RegisterRequest: typing_extensions.TypeAlias = RegisterRequest @typing.final class DriverInstanceReport(google.protobuf.message.Message): + """Report describing a single driver instance on an exporter.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor @typing.final @@ -110,16 +109,18 @@ class DriverInstanceReport(google.protobuf.message.Message): DESCRIPTION_FIELD_NUMBER: builtins.int METHODS_DESCRIPTION_FIELD_NUMBER: builtins.int uuid: builtins.str - """a unique id within the exporter""" + """Unique identifier within the exporter.""" parent_uuid: builtins.str - """optional, if device has a parent device""" + """Parent device UUID, if this is a child device.""" description: builtins.str - """optional custom driver description for CLI""" + """Custom driver description for CLI display.""" @property - def labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ... + def labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """Key-value metadata labels.""" + @property def methods_description(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: - """method name -> help text for CLI""" + """Method name to help text mapping for CLI.""" def __init__( self, @@ -141,10 +142,13 @@ Global___DriverInstanceReport: typing_extensions.TypeAlias = DriverInstanceRepor @typing.final class RegisterResponse(google.protobuf.message.Message): + """Registration response returned by the controller.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor UUID_FIELD_NUMBER: builtins.int uuid: builtins.str + """Assigned exporter UUID.""" def __init__( self, *, @@ -156,10 +160,13 @@ Global___RegisterResponse: typing_extensions.TypeAlias = RegisterResponse @typing.final class UnregisterRequest(google.protobuf.message.Message): + """Request to unregister an exporter from the controller.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor REASON_FIELD_NUMBER: builtins.int reason: builtins.str + """Reason for unregistering.""" def __init__( self, *, @@ -171,6 +178,8 @@ Global___UnregisterRequest: typing_extensions.TypeAlias = UnregisterRequest @typing.final class UnregisterResponse(google.protobuf.message.Message): + """Response to an unregister request.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -181,10 +190,13 @@ Global___UnregisterResponse: typing_extensions.TypeAlias = UnregisterResponse @typing.final class ListenRequest(google.protobuf.message.Message): + """Request to listen for incoming client connections on a lease.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor LEASE_NAME_FIELD_NUMBER: builtins.int lease_name: builtins.str + """Name of the lease to listen on.""" def __init__( self, *, @@ -196,12 +208,16 @@ Global___ListenRequest: typing_extensions.TypeAlias = ListenRequest @typing.final class ListenResponse(google.protobuf.message.Message): + """Response containing router connection details for an incoming client.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor ROUTER_ENDPOINT_FIELD_NUMBER: builtins.int ROUTER_TOKEN_FIELD_NUMBER: builtins.int router_endpoint: builtins.str + """The router gRPC endpoint URL.""" router_token: builtins.str + """Authentication token for the router.""" def __init__( self, *, @@ -214,6 +230,8 @@ Global___ListenResponse: typing_extensions.TypeAlias = ListenResponse @typing.final class StatusRequest(google.protobuf.message.Message): + """Request to subscribe to exporter lease status updates.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -224,14 +242,19 @@ Global___StatusRequest: typing_extensions.TypeAlias = StatusRequest @typing.final class StatusResponse(google.protobuf.message.Message): + """Lease status update for an exporter.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor LEASED_FIELD_NUMBER: builtins.int LEASE_NAME_FIELD_NUMBER: builtins.int CLIENT_NAME_FIELD_NUMBER: builtins.int leased: builtins.bool + """Whether the exporter is currently leased.""" lease_name: builtins.str + """Name of the active lease, if any.""" client_name: builtins.str + """Name of the connected client, if any.""" def __init__( self, *, @@ -250,10 +273,13 @@ Global___StatusResponse: typing_extensions.TypeAlias = StatusResponse @typing.final class DialRequest(google.protobuf.message.Message): + """Request to dial an exporter through the router.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor LEASE_NAME_FIELD_NUMBER: builtins.int lease_name: builtins.str + """Name of the lease to connect through.""" def __init__( self, *, @@ -265,12 +291,16 @@ Global___DialRequest: typing_extensions.TypeAlias = DialRequest @typing.final class DialResponse(google.protobuf.message.Message): + """Response containing router connection details for the dialed exporter.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor ROUTER_ENDPOINT_FIELD_NUMBER: builtins.int ROUTER_TOKEN_FIELD_NUMBER: builtins.int router_endpoint: builtins.str + """The router gRPC endpoint URL.""" router_token: builtins.str + """Authentication token for the router.""" def __init__( self, *, @@ -283,6 +313,8 @@ Global___DialResponse: typing_extensions.TypeAlias = DialResponse @typing.final class AuditStreamRequest(google.protobuf.message.Message): + """An audit event sent from an exporter to the controller.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor EXPORTER_UUID_FIELD_NUMBER: builtins.int @@ -290,12 +322,13 @@ class AuditStreamRequest(google.protobuf.message.Message): SEVERITY_FIELD_NUMBER: builtins.int MESSAGE_FIELD_NUMBER: builtins.int exporter_uuid: builtins.str - """additional context: - - token/authentication mechanism - """ + """UUID of the exporter.""" driver_instance_uuid: builtins.str + """UUID of the driver instance.""" severity: builtins.str + """Severity level of the event.""" message: builtins.str + """Human-readable event message.""" def __init__( self, *, @@ -310,16 +343,19 @@ Global___AuditStreamRequest: typing_extensions.TypeAlias = AuditStreamRequest @typing.final class ReportStatusRequest(google.protobuf.message.Message): + """Request to report exporter status to the controller.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor STATUS_FIELD_NUMBER: builtins.int MESSAGE_FIELD_NUMBER: builtins.int RELEASE_LEASE_FIELD_NUMBER: builtins.int status: jumpstarter.v1.common_pb2.ExporterStatus.ValueType + """Current exporter status.""" message: builtins.str - """Optional human-readable status message""" + """Optional human-readable status message.""" release_lease: builtins.bool - """When true, controller should release the active lease""" + """When true, controller should release the active lease.""" def __init__( self, *, @@ -338,6 +374,8 @@ Global___ReportStatusRequest: typing_extensions.TypeAlias = ReportStatusRequest @typing.final class ReportStatusResponse(google.protobuf.message.Message): + """Response to a status report request.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -348,6 +386,8 @@ Global___ReportStatusResponse: typing_extensions.TypeAlias = ReportStatusRespons @typing.final class GetReportResponse(google.protobuf.message.Message): + """Response containing the exporter driver report.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor @typing.final @@ -371,17 +411,19 @@ class GetReportResponse(google.protobuf.message.Message): REPORTS_FIELD_NUMBER: builtins.int ALTERNATIVE_ENDPOINTS_FIELD_NUMBER: builtins.int uuid: builtins.str + """Exporter UUID.""" @property - def labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ... + def labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """Key-value metadata labels.""" + @property def reports(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___DriverInstanceReport]: - """standard labels: - jumpstarter.dev/hostname= - jumpstarter.dev/name= - """ + """Driver instance reports.""" @property - def alternative_endpoints(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___Endpoint]: ... + def alternative_endpoints(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___Endpoint]: + """Alternative connection endpoints.""" + def __init__( self, *, @@ -396,6 +438,8 @@ Global___GetReportResponse: typing_extensions.TypeAlias = GetReportResponse @typing.final class Endpoint(google.protobuf.message.Message): + """Connection endpoint with TLS credentials.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor ENDPOINT_FIELD_NUMBER: builtins.int @@ -403,9 +447,13 @@ class Endpoint(google.protobuf.message.Message): CLIENT_CERTIFICATE_FIELD_NUMBER: builtins.int CLIENT_PRIVATE_KEY_FIELD_NUMBER: builtins.int endpoint: builtins.str + """The endpoint URL.""" certificate: builtins.str + """Server TLS certificate.""" client_certificate: builtins.str + """Client TLS certificate.""" client_private_key: builtins.str + """Client TLS private key.""" def __init__( self, *, @@ -420,15 +468,21 @@ Global___Endpoint: typing_extensions.TypeAlias = Endpoint @typing.final class DriverCallRequest(google.protobuf.message.Message): + """Request to invoke a method on a driver instance.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor UUID_FIELD_NUMBER: builtins.int METHOD_FIELD_NUMBER: builtins.int ARGS_FIELD_NUMBER: builtins.int uuid: builtins.str + """UUID of the driver instance.""" method: builtins.str + """Method name to invoke.""" @property - def args(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[google.protobuf.struct_pb2.Value]: ... + def args(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[google.protobuf.struct_pb2.Value]: + """Arguments for the method call.""" + def __init__( self, *, @@ -442,13 +496,18 @@ Global___DriverCallRequest: typing_extensions.TypeAlias = DriverCallRequest @typing.final class DriverCallResponse(google.protobuf.message.Message): + """Response from a driver method invocation.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor UUID_FIELD_NUMBER: builtins.int RESULT_FIELD_NUMBER: builtins.int uuid: builtins.str + """UUID of the driver instance.""" @property - def result(self) -> google.protobuf.struct_pb2.Value: ... + def result(self) -> google.protobuf.struct_pb2.Value: + """Return value from the method call.""" + def __init__( self, *, @@ -462,15 +521,21 @@ Global___DriverCallResponse: typing_extensions.TypeAlias = DriverCallResponse @typing.final class StreamingDriverCallRequest(google.protobuf.message.Message): + """Request to invoke a streaming method on a driver instance.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor UUID_FIELD_NUMBER: builtins.int METHOD_FIELD_NUMBER: builtins.int ARGS_FIELD_NUMBER: builtins.int uuid: builtins.str + """UUID of the driver instance.""" method: builtins.str + """Method name to invoke.""" @property - def args(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[google.protobuf.struct_pb2.Value]: ... + def args(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[google.protobuf.struct_pb2.Value]: + """Arguments for the method call.""" + def __init__( self, *, @@ -484,13 +549,18 @@ Global___StreamingDriverCallRequest: typing_extensions.TypeAlias = StreamingDriv @typing.final class StreamingDriverCallResponse(google.protobuf.message.Message): + """Response from a streaming driver method invocation.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor UUID_FIELD_NUMBER: builtins.int RESULT_FIELD_NUMBER: builtins.int uuid: builtins.str + """UUID of the driver instance.""" @property - def result(self) -> google.protobuf.struct_pb2.Value: ... + def result(self) -> google.protobuf.struct_pb2.Value: + """Return value from the method call.""" + def __init__( self, *, @@ -504,6 +574,8 @@ Global___StreamingDriverCallResponse: typing_extensions.TypeAlias = StreamingDri @typing.final class LogStreamResponse(google.protobuf.message.Message): + """A log message from the exporter log stream.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor UUID_FIELD_NUMBER: builtins.int @@ -511,10 +583,13 @@ class LogStreamResponse(google.protobuf.message.Message): MESSAGE_FIELD_NUMBER: builtins.int SOURCE_FIELD_NUMBER: builtins.int uuid: builtins.str + """UUID of the driver instance.""" severity: builtins.str + """Log severity level.""" message: builtins.str + """Log message content.""" source: jumpstarter.v1.common_pb2.LogSource.ValueType - """New optional field""" + """Source of the log message.""" def __init__( self, *, @@ -531,6 +606,8 @@ Global___LogStreamResponse: typing_extensions.TypeAlias = LogStreamResponse @typing.final class ResetRequest(google.protobuf.message.Message): + """Request to reset the exporter connection.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -541,6 +618,8 @@ Global___ResetRequest: typing_extensions.TypeAlias = ResetRequest @typing.final class ResetResponse(google.protobuf.message.Message): + """Response to a reset request.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -551,10 +630,13 @@ Global___ResetResponse: typing_extensions.TypeAlias = ResetResponse @typing.final class GetLeaseRequest(google.protobuf.message.Message): + """Request to retrieve a lease by name.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAME_FIELD_NUMBER: builtins.int name: builtins.str + """Name of the lease to retrieve.""" def __init__( self, *, @@ -566,6 +648,8 @@ Global___GetLeaseRequest: typing_extensions.TypeAlias = GetLeaseRequest @typing.final class GetLeaseResponse(google.protobuf.message.Message): + """Response containing lease details.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor DURATION_FIELD_NUMBER: builtins.int @@ -575,16 +659,27 @@ class GetLeaseResponse(google.protobuf.message.Message): EXPORTER_UUID_FIELD_NUMBER: builtins.int CONDITIONS_FIELD_NUMBER: builtins.int exporter_uuid: builtins.str + """UUID of the assigned exporter, if any.""" @property - def duration(self) -> google.protobuf.duration_pb2.Duration: ... + def duration(self) -> google.protobuf.duration_pb2.Duration: + """Requested lease duration.""" + @property - def selector(self) -> jumpstarter.v1.kubernetes_pb2.LabelSelector: ... + def selector(self) -> jumpstarter.v1.kubernetes_pb2.LabelSelector: + """Label selector for matching exporters.""" + @property - def begin_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def begin_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Lease start time, if active.""" + @property - def end_time(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + def end_time(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Lease end time, if active.""" + @property - def conditions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[jumpstarter.v1.kubernetes_pb2.Condition]: ... + def conditions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[jumpstarter.v1.kubernetes_pb2.Condition]: + """Lease status conditions.""" + def __init__( self, *, @@ -608,14 +703,20 @@ Global___GetLeaseResponse: typing_extensions.TypeAlias = GetLeaseResponse @typing.final class RequestLeaseRequest(google.protobuf.message.Message): + """Request to create a new lease for an exporter.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor DURATION_FIELD_NUMBER: builtins.int SELECTOR_FIELD_NUMBER: builtins.int @property - def duration(self) -> google.protobuf.duration_pb2.Duration: ... + def duration(self) -> google.protobuf.duration_pb2.Duration: + """Desired lease duration.""" + @property - def selector(self) -> jumpstarter.v1.kubernetes_pb2.LabelSelector: ... + def selector(self) -> jumpstarter.v1.kubernetes_pb2.LabelSelector: + """Label selector for matching exporters.""" + def __init__( self, *, @@ -629,10 +730,13 @@ Global___RequestLeaseRequest: typing_extensions.TypeAlias = RequestLeaseRequest @typing.final class RequestLeaseResponse(google.protobuf.message.Message): + """Response containing the name of the created lease.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAME_FIELD_NUMBER: builtins.int name: builtins.str + """Name of the created lease.""" def __init__( self, *, @@ -644,10 +748,13 @@ Global___RequestLeaseResponse: typing_extensions.TypeAlias = RequestLeaseRespons @typing.final class ReleaseLeaseRequest(google.protobuf.message.Message): + """Request to release an active lease.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAME_FIELD_NUMBER: builtins.int name: builtins.str + """Name of the lease to release.""" def __init__( self, *, @@ -659,6 +766,8 @@ Global___ReleaseLeaseRequest: typing_extensions.TypeAlias = ReleaseLeaseRequest @typing.final class ReleaseLeaseResponse(google.protobuf.message.Message): + """Response to a release lease request.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -669,6 +778,8 @@ Global___ReleaseLeaseResponse: typing_extensions.TypeAlias = ReleaseLeaseRespons @typing.final class ListLeasesRequest(google.protobuf.message.Message): + """Request to list all leases.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -679,11 +790,15 @@ Global___ListLeasesRequest: typing_extensions.TypeAlias = ListLeasesRequest @typing.final class ListLeasesResponse(google.protobuf.message.Message): + """Response containing the list of lease names.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor NAMES_FIELD_NUMBER: builtins.int @property - def names(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + def names(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Names of all leases.""" + def __init__( self, *, @@ -695,6 +810,8 @@ Global___ListLeasesResponse: typing_extensions.TypeAlias = ListLeasesResponse @typing.final class GetStatusRequest(google.protobuf.message.Message): + """Request to retrieve the current exporter status.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -705,6 +822,8 @@ Global___GetStatusRequest: typing_extensions.TypeAlias = GetStatusRequest @typing.final class GetStatusResponse(google.protobuf.message.Message): + """Response containing the current exporter status.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor STATUS_FIELD_NUMBER: builtins.int @@ -712,11 +831,13 @@ class GetStatusResponse(google.protobuf.message.Message): STATUS_VERSION_FIELD_NUMBER: builtins.int PREVIOUS_STATUS_FIELD_NUMBER: builtins.int status: jumpstarter.v1.common_pb2.ExporterStatus.ValueType + """Current exporter status.""" message: builtins.str + """Human-readable status message.""" status_version: builtins.int - """Monotonic counter, increments on each status change""" + """Monotonic counter, increments on each status change.""" previous_status: jumpstarter.v1.common_pb2.ExporterStatus.ValueType - """Previous status for transition tracking""" + """Previous status for transition tracking.""" def __init__( self, *, @@ -736,6 +857,8 @@ Global___GetStatusResponse: typing_extensions.TypeAlias = GetStatusResponse @typing.final class EndSessionRequest(google.protobuf.message.Message): + """Request to end the current exporter session.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor def __init__( @@ -746,12 +869,16 @@ Global___EndSessionRequest: typing_extensions.TypeAlias = EndSessionRequest @typing.final class EndSessionResponse(google.protobuf.message.Message): + """Response to an end session request.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor SUCCESS_FIELD_NUMBER: builtins.int MESSAGE_FIELD_NUMBER: builtins.int success: builtins.bool + """Whether the session ended successfully.""" message: builtins.str + """Human-readable result message.""" def __init__( self, *, diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py index 8360da0c7..a223cde6f 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py @@ -7,7 +7,7 @@ class ControllerServiceStub(object): - """A service where a exporter can connect to make itself available + """A service where an exporter can connect to make itself available. """ def __init__(self, channel): @@ -74,90 +74,86 @@ def __init__(self, channel): class ControllerServiceServicer(object): - """A service where a exporter can connect to make itself available + """A service where an exporter can connect to make itself available. """ def Register(self, request, context): - """Exporter registration + """Register an exporter with the controller. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Unregister(self, request, context): - """Exporter disconnection - Disconnecting with bye will invalidate any existing router tokens - we will eventually have a mechanism to tell the router this token - has been invalidated + """Unregister an exporter from the controller. + Disconnecting will invalidate any existing router tokens. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ReportStatus(self, request, context): - """Exporter status report - Allows exporters to report their own status to the controller + """Report exporter status to the controller. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Listen(self, request, context): - """Exporter listening - Returns stream tokens for accepting incoming client connections + """Listen for incoming client connections on a lease. + Returns stream tokens for accepting incoming client connections. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Status(self, request, context): - """Exporter status - Returns lease status for the exporter + """Stream lease status updates for the exporter. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Dial(self, request, context): - """Client connecting - Returns stream token for connecting to the desired exporter - Leases are checked before token issuance + """Dial an exporter through the router. + Returns a stream token for connecting to the desired exporter. + Leases are checked before token issuance. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def AuditStream(self, request_iterator, context): - """Audit events from the exporters - audit events are used to track the exporter's activity + """Stream audit events from the exporters. + Audit events are used to track the exporter activity. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetLease(self, request, context): - """Get Lease + """Retrieve a lease by name. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def RequestLease(self, request, context): - """Request Lease + """Request a new lease for an exporter. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ReleaseLease(self, request, context): - """Release Lease + """Release an active lease. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ListLeases(self, request, context): - """List Leases + """List all leases. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -230,7 +226,7 @@ def add_ControllerServiceServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. class ControllerService(object): - """A service where a exporter can connect to make itself available + """A service where an exporter can connect to make itself available. """ @staticmethod @@ -532,8 +528,8 @@ def ListLeases(request, class ExporterServiceStub(object): - """A service a exporter can share locally to be used without a server - Channel/Call credentials are used to authenticate the client, and routing to the right exporter + """A service an exporter can share locally to be used without a server. + Channel and call credentials are used to authenticate the client and route to the right exporter. """ def __init__(self, channel): @@ -580,51 +576,56 @@ def __init__(self, channel): class ExporterServiceServicer(object): - """A service a exporter can share locally to be used without a server - Channel/Call credentials are used to authenticate the client, and routing to the right exporter + """A service an exporter can share locally to be used without a server. + Channel and call credentials are used to authenticate the client and route to the right exporter. """ def GetReport(self, request, context): - """Exporter registration + """Retrieve the exporter driver report. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def DriverCall(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Invoke a method on a driver instance. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def StreamingDriverCall(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Invoke a streaming method on a driver instance. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def LogStream(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Stream log messages from the exporter. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def Reset(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Reset the exporter connection. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetStatus(self, request, context): - """Missing associated documentation comment in .proto file.""" + """Retrieve the current exporter status. + """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def EndSession(self, request, context): - """End the current session, triggering the afterLease hook - The client should keep the connection open to receive hook logs via LogStream - Returns after the afterLease hook completes + """End the current session, triggering the afterLease hook. + The client should keep the connection open to receive hook logs via LogStream. + Returns after the afterLease hook completes. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -677,8 +678,8 @@ def add_ExporterServiceServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. class ExporterService(object): - """A service a exporter can share locally to be used without a server - Channel/Call credentials are used to authenticate the client, and routing to the right exporter + """A service an exporter can share locally to be used without a server. + Channel and call credentials are used to authenticate the client and route to the right exporter. """ @staticmethod diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.pyi index 8352c5f46..3879bc147 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.pyi @@ -203,7 +203,7 @@ _ControllerServiceListLeasesType = typing_extensions.TypeVar( ) class ControllerServiceStub(typing.Generic[_ControllerServiceRegisterType, _ControllerServiceUnregisterType, _ControllerServiceReportStatusType, _ControllerServiceListenType, _ControllerServiceStatusType, _ControllerServiceDialType, _ControllerServiceAuditStreamType, _ControllerServiceGetLeaseType, _ControllerServiceRequestLeaseType, _ControllerServiceReleaseLeaseType, _ControllerServiceListLeasesType]): - """A service where a exporter can connect to make itself available""" + """A service where an exporter can connect to make itself available.""" @typing.overload def __init__(self: ControllerServiceStub[ @@ -302,52 +302,46 @@ class ControllerServiceStub(typing.Generic[_ControllerServiceRegisterType, _Cont ], channel: grpc.aio.Channel) -> None: ... Register: _ControllerServiceRegisterType - """Exporter registration""" + """Register an exporter with the controller.""" Unregister: _ControllerServiceUnregisterType - """Exporter disconnection - Disconnecting with bye will invalidate any existing router tokens - we will eventually have a mechanism to tell the router this token - has been invalidated + """Unregister an exporter from the controller. + Disconnecting will invalidate any existing router tokens. """ ReportStatus: _ControllerServiceReportStatusType - """Exporter status report - Allows exporters to report their own status to the controller - """ + """Report exporter status to the controller.""" Listen: _ControllerServiceListenType - """Exporter listening - Returns stream tokens for accepting incoming client connections + """Listen for incoming client connections on a lease. + Returns stream tokens for accepting incoming client connections. """ Status: _ControllerServiceStatusType - """Exporter status - Returns lease status for the exporter - """ + """Stream lease status updates for the exporter.""" Dial: _ControllerServiceDialType - """Client connecting - Returns stream token for connecting to the desired exporter - Leases are checked before token issuance + """Dial an exporter through the router. + Returns a stream token for connecting to the desired exporter. + Leases are checked before token issuance. """ AuditStream: _ControllerServiceAuditStreamType - """Audit events from the exporters - audit events are used to track the exporter's activity + """Stream audit events from the exporters. + Audit events are used to track the exporter activity. """ GetLease: _ControllerServiceGetLeaseType - """Get Lease""" + """Retrieve a lease by name.""" RequestLease: _ControllerServiceRequestLeaseType - """Request Lease""" + """Request a new lease for an exporter.""" ReleaseLease: _ControllerServiceReleaseLeaseType - """Release Lease""" + """Release an active lease.""" ListLeases: _ControllerServiceListLeasesType - """List Leases""" + """List all leases.""" ControllerServiceAsyncStub: typing_extensions.TypeAlias = ControllerServiceStub[ grpc.aio.UnaryUnaryMultiCallable[ @@ -397,7 +391,7 @@ ControllerServiceAsyncStub: typing_extensions.TypeAlias = ControllerServiceStub[ ] class ControllerServiceServicer(metaclass=abc.ABCMeta): - """A service where a exporter can connect to make itself available""" + """A service where an exporter can connect to make itself available.""" @abc.abstractmethod def Register( @@ -405,7 +399,7 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.RegisterRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.RegisterResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.RegisterResponse]]: - """Exporter registration""" + """Register an exporter with the controller.""" @abc.abstractmethod def Unregister( @@ -413,10 +407,8 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.UnregisterRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.UnregisterResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.UnregisterResponse]]: - """Exporter disconnection - Disconnecting with bye will invalidate any existing router tokens - we will eventually have a mechanism to tell the router this token - has been invalidated + """Unregister an exporter from the controller. + Disconnecting will invalidate any existing router tokens. """ @abc.abstractmethod @@ -425,9 +417,7 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.ReportStatusRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.ReportStatusResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.ReportStatusResponse]]: - """Exporter status report - Allows exporters to report their own status to the controller - """ + """Report exporter status to the controller.""" @abc.abstractmethod def Listen( @@ -435,8 +425,8 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.ListenRequest, context: _ServicerContext, ) -> typing.Union[collections.abc.Iterator[jumpstarter.v1.jumpstarter_pb2.ListenResponse], collections.abc.AsyncIterator[jumpstarter.v1.jumpstarter_pb2.ListenResponse]]: - """Exporter listening - Returns stream tokens for accepting incoming client connections + """Listen for incoming client connections on a lease. + Returns stream tokens for accepting incoming client connections. """ @abc.abstractmethod @@ -445,9 +435,7 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.StatusRequest, context: _ServicerContext, ) -> typing.Union[collections.abc.Iterator[jumpstarter.v1.jumpstarter_pb2.StatusResponse], collections.abc.AsyncIterator[jumpstarter.v1.jumpstarter_pb2.StatusResponse]]: - """Exporter status - Returns lease status for the exporter - """ + """Stream lease status updates for the exporter.""" @abc.abstractmethod def Dial( @@ -455,9 +443,9 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.DialRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.DialResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.DialResponse]]: - """Client connecting - Returns stream token for connecting to the desired exporter - Leases are checked before token issuance + """Dial an exporter through the router. + Returns a stream token for connecting to the desired exporter. + Leases are checked before token issuance. """ @abc.abstractmethod @@ -466,8 +454,8 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request_iterator: _MaybeAsyncIterator[jumpstarter.v1.jumpstarter_pb2.AuditStreamRequest], context: _ServicerContext, ) -> typing.Union[google.protobuf.empty_pb2.Empty, collections.abc.Awaitable[google.protobuf.empty_pb2.Empty]]: - """Audit events from the exporters - audit events are used to track the exporter's activity + """Stream audit events from the exporters. + Audit events are used to track the exporter activity. """ @abc.abstractmethod @@ -476,7 +464,7 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.GetLeaseRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.GetLeaseResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.GetLeaseResponse]]: - """Get Lease""" + """Retrieve a lease by name.""" @abc.abstractmethod def RequestLease( @@ -484,7 +472,7 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.RequestLeaseRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.RequestLeaseResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.RequestLeaseResponse]]: - """Request Lease""" + """Request a new lease for an exporter.""" @abc.abstractmethod def ReleaseLease( @@ -492,7 +480,7 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.ReleaseLeaseRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.ReleaseLeaseResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.ReleaseLeaseResponse]]: - """Release Lease""" + """Release an active lease.""" @abc.abstractmethod def ListLeases( @@ -500,7 +488,7 @@ class ControllerServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.ListLeasesRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.ListLeasesResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.ListLeasesResponse]]: - """List Leases""" + """List all leases.""" def add_ControllerServiceServicer_to_server(servicer: ControllerServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... @@ -617,8 +605,8 @@ _ExporterServiceEndSessionType = typing_extensions.TypeVar( ) class ExporterServiceStub(typing.Generic[_ExporterServiceGetReportType, _ExporterServiceDriverCallType, _ExporterServiceStreamingDriverCallType, _ExporterServiceLogStreamType, _ExporterServiceResetType, _ExporterServiceGetStatusType, _ExporterServiceEndSessionType]): - """A service a exporter can share locally to be used without a server - Channel/Call credentials are used to authenticate the client, and routing to the right exporter + """A service an exporter can share locally to be used without a server. + Channel and call credentials are used to authenticate the client and route to the right exporter. """ @typing.overload @@ -686,22 +674,27 @@ class ExporterServiceStub(typing.Generic[_ExporterServiceGetReportType, _Exporte ], channel: grpc.aio.Channel) -> None: ... GetReport: _ExporterServiceGetReportType - """Exporter registration""" + """Retrieve the exporter driver report.""" DriverCall: _ExporterServiceDriverCallType + """Invoke a method on a driver instance.""" StreamingDriverCall: _ExporterServiceStreamingDriverCallType + """Invoke a streaming method on a driver instance.""" LogStream: _ExporterServiceLogStreamType + """Stream log messages from the exporter.""" Reset: _ExporterServiceResetType + """Reset the exporter connection.""" GetStatus: _ExporterServiceGetStatusType + """Retrieve the current exporter status.""" EndSession: _ExporterServiceEndSessionType - """End the current session, triggering the afterLease hook - The client should keep the connection open to receive hook logs via LogStream - Returns after the afterLease hook completes + """End the current session, triggering the afterLease hook. + The client should keep the connection open to receive hook logs via LogStream. + Returns after the afterLease hook completes. """ ExporterServiceAsyncStub: typing_extensions.TypeAlias = ExporterServiceStub[ @@ -736,8 +729,8 @@ ExporterServiceAsyncStub: typing_extensions.TypeAlias = ExporterServiceStub[ ] class ExporterServiceServicer(metaclass=abc.ABCMeta): - """A service a exporter can share locally to be used without a server - Channel/Call credentials are used to authenticate the client, and routing to the right exporter + """A service an exporter can share locally to be used without a server. + Channel and call credentials are used to authenticate the client and route to the right exporter. """ @abc.abstractmethod @@ -746,42 +739,47 @@ class ExporterServiceServicer(metaclass=abc.ABCMeta): request: google.protobuf.empty_pb2.Empty, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.GetReportResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.GetReportResponse]]: - """Exporter registration""" + """Retrieve the exporter driver report.""" @abc.abstractmethod def DriverCall( self, request: jumpstarter.v1.jumpstarter_pb2.DriverCallRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.DriverCallResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.DriverCallResponse]]: ... + ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.DriverCallResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.DriverCallResponse]]: + """Invoke a method on a driver instance.""" @abc.abstractmethod def StreamingDriverCall( self, request: jumpstarter.v1.jumpstarter_pb2.StreamingDriverCallRequest, context: _ServicerContext, - ) -> typing.Union[collections.abc.Iterator[jumpstarter.v1.jumpstarter_pb2.StreamingDriverCallResponse], collections.abc.AsyncIterator[jumpstarter.v1.jumpstarter_pb2.StreamingDriverCallResponse]]: ... + ) -> typing.Union[collections.abc.Iterator[jumpstarter.v1.jumpstarter_pb2.StreamingDriverCallResponse], collections.abc.AsyncIterator[jumpstarter.v1.jumpstarter_pb2.StreamingDriverCallResponse]]: + """Invoke a streaming method on a driver instance.""" @abc.abstractmethod def LogStream( self, request: google.protobuf.empty_pb2.Empty, context: _ServicerContext, - ) -> typing.Union[collections.abc.Iterator[jumpstarter.v1.jumpstarter_pb2.LogStreamResponse], collections.abc.AsyncIterator[jumpstarter.v1.jumpstarter_pb2.LogStreamResponse]]: ... + ) -> typing.Union[collections.abc.Iterator[jumpstarter.v1.jumpstarter_pb2.LogStreamResponse], collections.abc.AsyncIterator[jumpstarter.v1.jumpstarter_pb2.LogStreamResponse]]: + """Stream log messages from the exporter.""" @abc.abstractmethod def Reset( self, request: jumpstarter.v1.jumpstarter_pb2.ResetRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.ResetResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.ResetResponse]]: ... + ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.ResetResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.ResetResponse]]: + """Reset the exporter connection.""" @abc.abstractmethod def GetStatus( self, request: jumpstarter.v1.jumpstarter_pb2.GetStatusRequest, context: _ServicerContext, - ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.GetStatusResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.GetStatusResponse]]: ... + ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.GetStatusResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.GetStatusResponse]]: + """Retrieve the current exporter status.""" @abc.abstractmethod def EndSession( @@ -789,9 +787,9 @@ class ExporterServiceServicer(metaclass=abc.ABCMeta): request: jumpstarter.v1.jumpstarter_pb2.EndSessionRequest, context: _ServicerContext, ) -> typing.Union[jumpstarter.v1.jumpstarter_pb2.EndSessionResponse, collections.abc.Awaitable[jumpstarter.v1.jumpstarter_pb2.EndSessionResponse]]: - """End the current session, triggering the afterLease hook - The client should keep the connection open to receive hook logs via LogStream - Returns after the afterLease hook completes + """End the current session, triggering the afterLease hook. + The client should keep the connection open to receive hook logs via LogStream. + Returns after the afterLease hook completes. """ def add_ExporterServiceServicer_to_server(servicer: ExporterServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.pyi index e07fb6250..0fd4d591e 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.pyi @@ -20,15 +20,21 @@ DESCRIPTOR: google.protobuf.descriptor.FileDescriptor @typing.final class LabelSelectorRequirement(google.protobuf.message.Message): + """A label selector requirement with key, operator, and values.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor KEY_FIELD_NUMBER: builtins.int OPERATOR_FIELD_NUMBER: builtins.int VALUES_FIELD_NUMBER: builtins.int key: builtins.str + """The label key that the selector applies to.""" operator: builtins.str + """The operator (In, NotIn, Exists, DoesNotExist) relating the key to values.""" @property - def values(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + def values(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """The set of values for the operator to match against.""" + def __init__( self, *, @@ -65,9 +71,13 @@ class LabelSelector(google.protobuf.message.Message): MATCH_EXPRESSIONS_FIELD_NUMBER: builtins.int MATCH_LABELS_FIELD_NUMBER: builtins.int @property - def match_expressions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___LabelSelectorRequirement]: ... + def match_expressions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___LabelSelectorRequirement]: + """A list of label selector requirements combined by AND.""" + @property - def match_labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ... + def match_labels(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: + """A map of key-value pairs that must match exactly.""" + def __init__( self, *, @@ -80,14 +90,18 @@ Global___LabelSelector: typing_extensions.TypeAlias = LabelSelector @typing.final class Time(google.protobuf.message.Message): - """Reference: https://github.com/kubernetes/kubernetes/blob/v1.31.1/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto""" + """Timestamp in seconds and nanoseconds since the Unix epoch. + Reference: https://github.com/kubernetes/kubernetes/blob/v1.31.1/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto + """ DESCRIPTOR: google.protobuf.descriptor.Descriptor SECONDS_FIELD_NUMBER: builtins.int NANOS_FIELD_NUMBER: builtins.int seconds: builtins.int + """Seconds since the Unix epoch.""" nanos: builtins.int + """Non-negative fractions of a second at nanosecond resolution.""" def __init__( self, *, @@ -105,6 +119,8 @@ Global___Time: typing_extensions.TypeAlias = Time @typing.final class Condition(google.protobuf.message.Message): + """A Kubernetes-style status condition.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor TYPE_FIELD_NUMBER: builtins.int @@ -114,12 +130,19 @@ class Condition(google.protobuf.message.Message): REASON_FIELD_NUMBER: builtins.int MESSAGE_FIELD_NUMBER: builtins.int type: builtins.str + """The type of condition.""" status: builtins.str + """The status of the condition (True, False, Unknown).""" observedGeneration: builtins.int + """The generation observed by the controller.""" reason: builtins.str + """A machine-readable reason for the condition.""" message: builtins.str + """A human-readable description of the condition.""" @property - def lastTransitionTime(self) -> Global___Time: ... + def lastTransitionTime(self) -> Global___Time: + """The last time the condition transitioned.""" + def __init__( self, *, diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.pyi index 905fc6b88..1aa620e61 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.pyi @@ -24,26 +24,39 @@ class _FrameType: class _FrameTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_FrameType.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor FRAME_TYPE_DATA: _FrameType.ValueType # 0 + """Data frame carrying payload bytes.""" FRAME_TYPE_RST_STREAM: _FrameType.ValueType # 3 + """Reset stream signal.""" FRAME_TYPE_PING: _FrameType.ValueType # 6 + """Keepalive ping frame.""" FRAME_TYPE_GOAWAY: _FrameType.ValueType # 7 + """Graceful shutdown signal.""" -class FrameType(_FrameType, metaclass=_FrameTypeEnumTypeWrapper): ... +class FrameType(_FrameType, metaclass=_FrameTypeEnumTypeWrapper): + """Frame types for the stream protocol.""" FRAME_TYPE_DATA: FrameType.ValueType # 0 +"""Data frame carrying payload bytes.""" FRAME_TYPE_RST_STREAM: FrameType.ValueType # 3 +"""Reset stream signal.""" FRAME_TYPE_PING: FrameType.ValueType # 6 +"""Keepalive ping frame.""" FRAME_TYPE_GOAWAY: FrameType.ValueType # 7 +"""Graceful shutdown signal.""" Global___FrameType: typing_extensions.TypeAlias = FrameType @typing.final class StreamRequest(google.protobuf.message.Message): + """Request message for bidirectional stream communication.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor PAYLOAD_FIELD_NUMBER: builtins.int FRAME_TYPE_FIELD_NUMBER: builtins.int payload: builtins.bytes + """The raw bytes of the stream frame.""" frame_type: Global___FrameType.ValueType + """The type of frame being sent.""" def __init__( self, *, @@ -56,12 +69,16 @@ Global___StreamRequest: typing_extensions.TypeAlias = StreamRequest @typing.final class StreamResponse(google.protobuf.message.Message): + """Response message for bidirectional stream communication.""" + DESCRIPTOR: google.protobuf.descriptor.Descriptor PAYLOAD_FIELD_NUMBER: builtins.int FRAME_TYPE_FIELD_NUMBER: builtins.int payload: builtins.bytes + """The raw bytes of the stream frame.""" frame_type: Global___FrameType.ValueType + """The type of frame being received.""" def __init__( self, *, diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py index 81393a572..74e9b4fab 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.py @@ -6,12 +6,12 @@ class RouterServiceStub(object): - """StreamService + """Router service for multiplexing bidirectional streams between clients and exporters. Claims: iss: jumpstarter controller aud: jumpstarter router sub: jumpstarter client/exporter - stream: stream id + stream: stream id. """ def __init__(self, channel): @@ -28,16 +28,16 @@ def __init__(self, channel): class RouterServiceServicer(object): - """StreamService + """Router service for multiplexing bidirectional streams between clients and exporters. Claims: iss: jumpstarter controller aud: jumpstarter router sub: jumpstarter client/exporter - stream: stream id + stream: stream id. """ def Stream(self, request_iterator, context): - """Stream connects caller to another caller of the same stream + """Stream connects caller to another caller of the same stream. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -60,12 +60,12 @@ def add_RouterServiceServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. class RouterService(object): - """StreamService + """Router service for multiplexing bidirectional streams between clients and exporters. Claims: iss: jumpstarter controller aud: jumpstarter router sub: jumpstarter client/exporter - stream: stream id + stream: stream id. """ @staticmethod diff --git a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.pyi b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.pyi index 032778846..856c0e9eb 100644 --- a/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.pyi +++ b/python/packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2_grpc.pyi @@ -42,12 +42,12 @@ _RouterServiceStreamType = typing_extensions.TypeVar( ) class RouterServiceStub(typing.Generic[_RouterServiceStreamType]): - """StreamService + """Router service for multiplexing bidirectional streams between clients and exporters. Claims: iss: jumpstarter controller aud: jumpstarter router sub: jumpstarter client/exporter - stream: stream id + stream: stream id. """ @typing.overload @@ -67,7 +67,7 @@ class RouterServiceStub(typing.Generic[_RouterServiceStreamType]): ], channel: grpc.aio.Channel) -> None: ... Stream: _RouterServiceStreamType - """Stream connects caller to another caller of the same stream""" + """Stream connects caller to another caller of the same stream.""" RouterServiceAsyncStub: typing_extensions.TypeAlias = RouterServiceStub[ grpc.aio.StreamStreamMultiCallable[ @@ -77,12 +77,12 @@ RouterServiceAsyncStub: typing_extensions.TypeAlias = RouterServiceStub[ ] class RouterServiceServicer(metaclass=abc.ABCMeta): - """StreamService + """Router service for multiplexing bidirectional streams between clients and exporters. Claims: iss: jumpstarter controller aud: jumpstarter router sub: jumpstarter client/exporter - stream: stream id + stream: stream id. """ @abc.abstractmethod @@ -91,6 +91,6 @@ class RouterServiceServicer(metaclass=abc.ABCMeta): request_iterator: _MaybeAsyncIterator[jumpstarter.v1.router_pb2.StreamRequest], context: _ServicerContext, ) -> typing.Union[collections.abc.Iterator[jumpstarter.v1.router_pb2.StreamResponse], collections.abc.AsyncIterator[jumpstarter.v1.router_pb2.StreamResponse]]: - """Stream connects caller to another caller of the same stream""" + """Stream connects caller to another caller of the same stream.""" def add_RouterServiceServicer_to_server(servicer: RouterServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... diff --git a/python/packages/jumpstarter/jumpstarter/client/grpc.py b/python/packages/jumpstarter/jumpstarter/client/grpc.py index 6e2b575cf..9e13adcfd 100644 --- a/python/packages/jumpstarter/jumpstarter/client/grpc.py +++ b/python/packages/jumpstarter/jumpstarter/client/grpc.py @@ -132,6 +132,7 @@ def rich_add_names(self, names): class Lease(BaseModel): namespace: str name: str + alias: str | None = None selector: str exporter_name: str | None = None tags: dict[str, str] = Field(default_factory=dict) @@ -185,9 +186,12 @@ def from_protobuf(cls, data: client_pb2.Lease) -> Lease: tzinfo=datetime.now().astimezone().tzinfo, ) + alias = data.alias if data.HasField("alias") else None + return cls( namespace=namespace, name=name, + alias=alias, selector=data.selector, exporter_name=data.exporter_name if data.exporter_name else None, tags=dict(data.tags) if data.tags else {}, @@ -248,7 +252,7 @@ def rich_add_rows(self, table): tags_str = ",".join(f"{k}={v}" for k, v in sorted(self.tags.items())) table.add_row( - self.name, + self.alias or self.name, self.selector, expires_at_str, remaining_str,