From 1ae06781d6115d7c259924a64bb598f34e8bddf9 Mon Sep 17 00:00:00 2001 From: Tanishq Dubey Date: Sat, 10 May 2025 18:18:58 -0400 Subject: [PATCH] [Aider] Phase 0 --- Makefile | 33 + api/v1alpha1/kat.pb.go | 3458 +++++++++++++++++ api/v1alpha1/kat.proto | 345 ++ examples/cluster.kat | 18 + .../simple-service/virtualLoadBalancer.kat | 15 + examples/simple-service/workload.kat | 21 + go.mod | 6 +- go.sum | 10 + internal/config/parse.go | 323 ++ internal/config/parse_test.go | 80 +- internal/config/types.go | 23 + internal/utils/tar.go | 87 + internal/utils/tar_test.go | 27 +- scripts/gen-proto.sh | 47 + 14 files changed, 4438 insertions(+), 55 deletions(-) create mode 100644 Makefile create mode 100644 api/v1alpha1/kat.pb.go create mode 100644 api/v1alpha1/kat.proto create mode 100644 examples/cluster.kat create mode 100644 examples/simple-service/virtualLoadBalancer.kat create mode 100644 examples/simple-service/workload.kat create mode 100644 go.sum create mode 100644 internal/config/parse.go create mode 100644 internal/config/types.go create mode 100644 internal/utils/tar.go create mode 100755 scripts/gen-proto.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..24cde5e --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +# File: Makefile +.PHONY: all generate clean test + +# Variables +GOLANGCI_LINT_VERSION := v1.55.2 # Or your preferred version + +all: generate test + +generate: + @echo "Generating Go code from Protobuf definitions..." + @./scripts/gen-proto.sh + +# Placeholder for future commands +clean: + @echo "Cleaning up generated files and build artifacts..." + @rm -f ./api/v1alpha1/*.pb.go + @rm -f kat-agent katcall + +test: + @echo "Running tests..." + @go test ./... + +lint: + @echo "Running linter..." + @if ! command -v golangci-lint &> /dev/null; then \ + echo "golangci-lint not found. Installing..."; \ + go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION); \ + fi + @golangci-lint run + +# Add to go.mod if not already present by go install +# go get google.golang.org/protobuf/cmd/protoc-gen-go +# go get google.golang.org/grpc/cmd/protoc-gen-go-grpc (if you plan to use gRPC services soon) \ No newline at end of file diff --git a/api/v1alpha1/kat.pb.go b/api/v1alpha1/kat.pb.go new file mode 100644 index 0000000..d93948c --- /dev/null +++ b/api/v1alpha1/kat.pb.go @@ -0,0 +1,3458 @@ +// File: api/v1alpha1/kat.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v6.31.0--rc2 +// source: kat.proto + +package kat + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Workload (RFC 3.2) +type WorkloadType int32 + +const ( + WorkloadType_WORKLOAD_TYPE_UNSPECIFIED WorkloadType = 0 + WorkloadType_SERVICE WorkloadType = 1 + WorkloadType_JOB WorkloadType = 2 + WorkloadType_DAEMON_SERVICE WorkloadType = 3 +) + +// Enum value maps for WorkloadType. +var ( + WorkloadType_name = map[int32]string{ + 0: "WORKLOAD_TYPE_UNSPECIFIED", + 1: "SERVICE", + 2: "JOB", + 3: "DAEMON_SERVICE", + } + WorkloadType_value = map[string]int32{ + "WORKLOAD_TYPE_UNSPECIFIED": 0, + "SERVICE": 1, + "JOB": 2, + "DAEMON_SERVICE": 3, + } +) + +func (x WorkloadType) Enum() *WorkloadType { + p := new(WorkloadType) + *p = x + return p +} + +func (x WorkloadType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (WorkloadType) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[0].Descriptor() +} + +func (WorkloadType) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[0] +} + +func (x WorkloadType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use WorkloadType.Descriptor instead. +func (WorkloadType) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{0} +} + +type UpdateStrategyType int32 + +const ( + UpdateStrategyType_UPDATE_STRATEGY_TYPE_UNSPECIFIED UpdateStrategyType = 0 + UpdateStrategyType_ROLLING UpdateStrategyType = 1 + UpdateStrategyType_SIMULTANEOUS UpdateStrategyType = 2 +) + +// Enum value maps for UpdateStrategyType. +var ( + UpdateStrategyType_name = map[int32]string{ + 0: "UPDATE_STRATEGY_TYPE_UNSPECIFIED", + 1: "ROLLING", + 2: "SIMULTANEOUS", + } + UpdateStrategyType_value = map[string]int32{ + "UPDATE_STRATEGY_TYPE_UNSPECIFIED": 0, + "ROLLING": 1, + "SIMULTANEOUS": 2, + } +) + +func (x UpdateStrategyType) Enum() *UpdateStrategyType { + p := new(UpdateStrategyType) + *p = x + return p +} + +func (x UpdateStrategyType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UpdateStrategyType) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[1].Descriptor() +} + +func (UpdateStrategyType) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[1] +} + +func (x UpdateStrategyType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UpdateStrategyType.Descriptor instead. +func (UpdateStrategyType) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{1} +} + +type RestartCondition int32 + +const ( + RestartCondition_RESTART_CONDITION_UNSPECIFIED RestartCondition = 0 + RestartCondition_NEVER RestartCondition = 1 + RestartCondition_MAX_COUNT RestartCondition = 2 + RestartCondition_ALWAYS RestartCondition = 3 +) + +// Enum value maps for RestartCondition. +var ( + RestartCondition_name = map[int32]string{ + 0: "RESTART_CONDITION_UNSPECIFIED", + 1: "NEVER", + 2: "MAX_COUNT", + 3: "ALWAYS", + } + RestartCondition_value = map[string]int32{ + "RESTART_CONDITION_UNSPECIFIED": 0, + "NEVER": 1, + "MAX_COUNT": 2, + "ALWAYS": 3, + } +) + +func (x RestartCondition) Enum() *RestartCondition { + p := new(RestartCondition) + *p = x + return p +} + +func (x RestartCondition) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RestartCondition) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[2].Descriptor() +} + +func (RestartCondition) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[2] +} + +func (x RestartCondition) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RestartCondition.Descriptor instead. +func (RestartCondition) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{2} +} + +type GPUDriver int32 + +const ( + GPUDriver_GPU_DRIVER_UNSPECIFIED GPUDriver = 0 + GPUDriver_ANY GPUDriver = 1 + GPUDriver_NVIDIA GPUDriver = 2 + GPUDriver_AMD GPUDriver = 3 +) + +// Enum value maps for GPUDriver. +var ( + GPUDriver_name = map[int32]string{ + 0: "GPU_DRIVER_UNSPECIFIED", + 1: "ANY", + 2: "NVIDIA", + 3: "AMD", + } + GPUDriver_value = map[string]int32{ + "GPU_DRIVER_UNSPECIFIED": 0, + "ANY": 1, + "NVIDIA": 2, + "AMD": 3, + } +) + +func (x GPUDriver) Enum() *GPUDriver { + p := new(GPUDriver) + *p = x + return p +} + +func (x GPUDriver) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (GPUDriver) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[3].Descriptor() +} + +func (GPUDriver) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[3] +} + +func (x GPUDriver) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use GPUDriver.Descriptor instead. +func (GPUDriver) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{3} +} + +type HostPathType int32 + +const ( + HostPathType_HOST_PATH_TYPE_UNSPECIFIED HostPathType = 0 // No check, mount whatever is there or fail + HostPathType_DIRECTORY_OR_CREATE HostPathType = 1 + HostPathType_DIRECTORY HostPathType = 2 + HostPathType_FILE_OR_CREATE HostPathType = 3 + HostPathType_FILE HostPathType = 4 + HostPathType_SOCKET HostPathType = 5 +) + +// Enum value maps for HostPathType. +var ( + HostPathType_name = map[int32]string{ + 0: "HOST_PATH_TYPE_UNSPECIFIED", + 1: "DIRECTORY_OR_CREATE", + 2: "DIRECTORY", + 3: "FILE_OR_CREATE", + 4: "FILE", + 5: "SOCKET", + } + HostPathType_value = map[string]int32{ + "HOST_PATH_TYPE_UNSPECIFIED": 0, + "DIRECTORY_OR_CREATE": 1, + "DIRECTORY": 2, + "FILE_OR_CREATE": 3, + "FILE": 4, + "SOCKET": 5, + } +) + +func (x HostPathType) Enum() *HostPathType { + p := new(HostPathType) + *p = x + return p +} + +func (x HostPathType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HostPathType) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[4].Descriptor() +} + +func (HostPathType) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[4] +} + +func (x HostPathType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HostPathType.Descriptor instead. +func (HostPathType) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{4} +} + +type Toleration_Operator int32 + +const ( + Toleration_OPERATOR_UNSPECIFIED Toleration_Operator = 0 + Toleration_EXISTS Toleration_Operator = 1 + Toleration_EQUAL Toleration_Operator = 2 +) + +// Enum value maps for Toleration_Operator. +var ( + Toleration_Operator_name = map[int32]string{ + 0: "OPERATOR_UNSPECIFIED", + 1: "EXISTS", + 2: "EQUAL", + } + Toleration_Operator_value = map[string]int32{ + "OPERATOR_UNSPECIFIED": 0, + "EXISTS": 1, + "EQUAL": 2, + } +) + +func (x Toleration_Operator) Enum() *Toleration_Operator { + p := new(Toleration_Operator) + *p = x + return p +} + +func (x Toleration_Operator) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Toleration_Operator) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[5].Descriptor() +} + +func (Toleration_Operator) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[5] +} + +func (x Toleration_Operator) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Toleration_Operator.Descriptor instead. +func (Toleration_Operator) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{6, 0} +} + +type Toleration_Effect int32 + +const ( + Toleration_EFFECT_UNSPECIFIED Toleration_Effect = 0 + Toleration_NO_SCHEDULE Toleration_Effect = 1 + Toleration_PREFER_NO_SCHEDULE Toleration_Effect = 2 // NO_EXECUTE (not in RFC v1 scope for tolerations, but common) +) + +// Enum value maps for Toleration_Effect. +var ( + Toleration_Effect_name = map[int32]string{ + 0: "EFFECT_UNSPECIFIED", + 1: "NO_SCHEDULE", + 2: "PREFER_NO_SCHEDULE", + } + Toleration_Effect_value = map[string]int32{ + "EFFECT_UNSPECIFIED": 0, + "NO_SCHEDULE": 1, + "PREFER_NO_SCHEDULE": 2, + } +) + +func (x Toleration_Effect) Enum() *Toleration_Effect { + p := new(Toleration_Effect) + *p = x + return p +} + +func (x Toleration_Effect) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Toleration_Effect) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[6].Descriptor() +} + +func (Toleration_Effect) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[6] +} + +func (x Toleration_Effect) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Toleration_Effect.Descriptor instead. +func (Toleration_Effect) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{6, 1} +} + +type Taint_Effect int32 + +const ( + Taint_EFFECT_UNSPECIFIED Taint_Effect = 0 + Taint_NO_SCHEDULE Taint_Effect = 1 + Taint_PREFER_NO_SCHEDULE Taint_Effect = 2 // NO_EXECUTE (not in RFC v1 scope for taints, but common) +) + +// Enum value maps for Taint_Effect. +var ( + Taint_Effect_name = map[int32]string{ + 0: "EFFECT_UNSPECIFIED", + 1: "NO_SCHEDULE", + 2: "PREFER_NO_SCHEDULE", + } + Taint_Effect_value = map[string]int32{ + "EFFECT_UNSPECIFIED": 0, + "NO_SCHEDULE": 1, + "PREFER_NO_SCHEDULE": 2, + } +) + +func (x Taint_Effect) Enum() *Taint_Effect { + p := new(Taint_Effect) + *p = x + return p +} + +func (x Taint_Effect) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Taint_Effect) Descriptor() protoreflect.EnumDescriptor { + return file_kat_proto_enumTypes[7].Descriptor() +} + +func (Taint_Effect) Type() protoreflect.EnumType { + return &file_kat_proto_enumTypes[7] +} + +func (x Taint_Effect) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Taint_Effect.Descriptor instead. +func (Taint_Effect) EnumDescriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{36, 0} +} + +// Common Metadata (RFC 3.2, Phase 0 Docs) +type ObjectMeta struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Uid string `protobuf:"bytes,3,opt,name=uid,proto3" json:"uid,omitempty"` + Generation int64 `protobuf:"varint,4,opt,name=generation,proto3" json:"generation,omitempty"` + ResourceVersion string `protobuf:"bytes,5,opt,name=resource_version,json=resourceVersion,proto3" json:"resource_version,omitempty"` // e.g., etcd ModRevision + CreationTimestamp *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=creation_timestamp,json=creationTimestamp,proto3" json:"creation_timestamp,omitempty"` + Labels map[string]string `protobuf:"bytes,7,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Annotations map[string]string `protobuf:"bytes,8,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ObjectMeta) Reset() { + *x = ObjectMeta{} + mi := &file_kat_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ObjectMeta) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ObjectMeta) ProtoMessage() {} + +func (x *ObjectMeta) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ObjectMeta.ProtoReflect.Descriptor instead. +func (*ObjectMeta) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{0} +} + +func (x *ObjectMeta) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ObjectMeta) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ObjectMeta) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +func (x *ObjectMeta) GetGeneration() int64 { + if x != nil { + return x.Generation + } + return 0 +} + +func (x *ObjectMeta) GetResourceVersion() string { + if x != nil { + return x.ResourceVersion + } + return "" +} + +func (x *ObjectMeta) GetCreationTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.CreationTimestamp + } + return nil +} + +func (x *ObjectMeta) GetLabels() map[string]string { + if x != nil { + return x.Labels + } + return nil +} + +func (x *ObjectMeta) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + +type GitSource struct { + state protoimpl.MessageState `protogen:"open.v1"` + Repository string `protobuf:"bytes,1,opt,name=repository,proto3" json:"repository,omitempty"` + Branch string `protobuf:"bytes,2,opt,name=branch,proto3" json:"branch,omitempty"` + Tag string `protobuf:"bytes,3,opt,name=tag,proto3" json:"tag,omitempty"` + Commit string `protobuf:"bytes,4,opt,name=commit,proto3" json:"commit,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GitSource) Reset() { + *x = GitSource{} + mi := &file_kat_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GitSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GitSource) ProtoMessage() {} + +func (x *GitSource) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GitSource.ProtoReflect.Descriptor instead. +func (*GitSource) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{1} +} + +func (x *GitSource) GetRepository() string { + if x != nil { + return x.Repository + } + return "" +} + +func (x *GitSource) GetBranch() string { + if x != nil { + return x.Branch + } + return "" +} + +func (x *GitSource) GetTag() string { + if x != nil { + return x.Tag + } + return "" +} + +func (x *GitSource) GetCommit() string { + if x != nil { + return x.Commit + } + return "" +} + +type WorkloadSource struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to SourceType: + // + // *WorkloadSource_Image + // *WorkloadSource_Git + SourceType isWorkloadSource_SourceType `protobuf_oneof:"source_type"` + CacheImage string `protobuf:"bytes,3,opt,name=cache_image,json=cacheImage,proto3" json:"cache_image,omitempty"` // Optional: Registry path for build cache layers (used with git source) + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkloadSource) Reset() { + *x = WorkloadSource{} + mi := &file_kat_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkloadSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadSource) ProtoMessage() {} + +func (x *WorkloadSource) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadSource.ProtoReflect.Descriptor instead. +func (*WorkloadSource) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{2} +} + +func (x *WorkloadSource) GetSourceType() isWorkloadSource_SourceType { + if x != nil { + return x.SourceType + } + return nil +} + +func (x *WorkloadSource) GetImage() string { + if x != nil { + if x, ok := x.SourceType.(*WorkloadSource_Image); ok { + return x.Image + } + } + return "" +} + +func (x *WorkloadSource) GetGit() *GitSource { + if x != nil { + if x, ok := x.SourceType.(*WorkloadSource_Git); ok { + return x.Git + } + } + return nil +} + +func (x *WorkloadSource) GetCacheImage() string { + if x != nil { + return x.CacheImage + } + return "" +} + +type isWorkloadSource_SourceType interface { + isWorkloadSource_SourceType() +} + +type WorkloadSource_Image struct { + Image string `protobuf:"bytes,1,opt,name=image,proto3,oneof"` // Direct image reference +} + +type WorkloadSource_Git struct { + Git *GitSource `protobuf:"bytes,2,opt,name=git,proto3,oneof"` // Build from Git +} + +func (*WorkloadSource_Image) isWorkloadSource_SourceType() {} + +func (*WorkloadSource_Git) isWorkloadSource_SourceType() {} + +type RollingUpdateStrategy struct { + state protoimpl.MessageState `protogen:"open.v1"` + MaxSurge string `protobuf:"bytes,1,opt,name=max_surge,json=maxSurge,proto3" json:"max_surge,omitempty"` // Can be int or percentage string e.g., "1" or "10%" + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RollingUpdateStrategy) Reset() { + *x = RollingUpdateStrategy{} + mi := &file_kat_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RollingUpdateStrategy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RollingUpdateStrategy) ProtoMessage() {} + +func (x *RollingUpdateStrategy) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RollingUpdateStrategy.ProtoReflect.Descriptor instead. +func (*RollingUpdateStrategy) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{3} +} + +func (x *RollingUpdateStrategy) GetMaxSurge() string { + if x != nil { + return x.MaxSurge + } + return "" +} + +type UpdateStrategy struct { + state protoimpl.MessageState `protogen:"open.v1"` + Type UpdateStrategyType `protobuf:"varint,1,opt,name=type,proto3,enum=v1alpha1.UpdateStrategyType" json:"type,omitempty"` + Rolling *RollingUpdateStrategy `protobuf:"bytes,2,opt,name=rolling,proto3" json:"rolling,omitempty"` // Relevant if type is ROLLING + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateStrategy) Reset() { + *x = UpdateStrategy{} + mi := &file_kat_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateStrategy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateStrategy) ProtoMessage() {} + +func (x *UpdateStrategy) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateStrategy.ProtoReflect.Descriptor instead. +func (*UpdateStrategy) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{4} +} + +func (x *UpdateStrategy) GetType() UpdateStrategyType { + if x != nil { + return x.Type + } + return UpdateStrategyType_UPDATE_STRATEGY_TYPE_UNSPECIFIED +} + +func (x *UpdateStrategy) GetRolling() *RollingUpdateStrategy { + if x != nil { + return x.Rolling + } + return nil +} + +type RestartPolicy struct { + state protoimpl.MessageState `protogen:"open.v1"` + Condition RestartCondition `protobuf:"varint,1,opt,name=condition,proto3,enum=v1alpha1.RestartCondition" json:"condition,omitempty"` + MaxRestarts int32 `protobuf:"varint,2,opt,name=max_restarts,json=maxRestarts,proto3" json:"max_restarts,omitempty"` // Used if condition=MAX_COUNT + ResetSeconds int32 `protobuf:"varint,3,opt,name=reset_seconds,json=resetSeconds,proto3" json:"reset_seconds,omitempty"` // Used if condition=MAX_COUNT + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RestartPolicy) Reset() { + *x = RestartPolicy{} + mi := &file_kat_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RestartPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RestartPolicy) ProtoMessage() {} + +func (x *RestartPolicy) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RestartPolicy.ProtoReflect.Descriptor instead. +func (*RestartPolicy) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{5} +} + +func (x *RestartPolicy) GetCondition() RestartCondition { + if x != nil { + return x.Condition + } + return RestartCondition_RESTART_CONDITION_UNSPECIFIED +} + +func (x *RestartPolicy) GetMaxRestarts() int32 { + if x != nil { + return x.MaxRestarts + } + return 0 +} + +func (x *RestartPolicy) GetResetSeconds() int32 { + if x != nil { + return x.ResetSeconds + } + return 0 +} + +type Toleration struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Operator Toleration_Operator `protobuf:"varint,2,opt,name=operator,proto3,enum=v1alpha1.Toleration_Operator" json:"operator,omitempty"` + Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` // Needed if operator=EQUAL + Effect Toleration_Effect `protobuf:"varint,4,opt,name=effect,proto3,enum=v1alpha1.Toleration_Effect" json:"effect,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Toleration) Reset() { + *x = Toleration{} + mi := &file_kat_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Toleration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Toleration) ProtoMessage() {} + +func (x *Toleration) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Toleration.ProtoReflect.Descriptor instead. +func (*Toleration) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{6} +} + +func (x *Toleration) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Toleration) GetOperator() Toleration_Operator { + if x != nil { + return x.Operator + } + return Toleration_OPERATOR_UNSPECIFIED +} + +func (x *Toleration) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *Toleration) GetEffect() Toleration_Effect { + if x != nil { + return x.Effect + } + return Toleration_EFFECT_UNSPECIFIED +} + +type EnvVar struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EnvVar) Reset() { + *x = EnvVar{} + mi := &file_kat_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EnvVar) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnvVar) ProtoMessage() {} + +func (x *EnvVar) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnvVar.ProtoReflect.Descriptor instead. +func (*EnvVar) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{7} +} + +func (x *EnvVar) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *EnvVar) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type VolumeMount struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Volume name from spec.volumes + MountPath string `protobuf:"bytes,2,opt,name=mount_path,json=mountPath,proto3" json:"mount_path,omitempty"` // Path inside container + SubPath string `protobuf:"bytes,3,opt,name=sub_path,json=subPath,proto3" json:"sub_path,omitempty"` // Optional: Mount sub-directory + ReadOnly bool `protobuf:"varint,4,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` // Optional: Default false + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VolumeMount) Reset() { + *x = VolumeMount{} + mi := &file_kat_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VolumeMount) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VolumeMount) ProtoMessage() {} + +func (x *VolumeMount) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VolumeMount.ProtoReflect.Descriptor instead. +func (*VolumeMount) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{8} +} + +func (x *VolumeMount) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *VolumeMount) GetMountPath() string { + if x != nil { + return x.MountPath + } + return "" +} + +func (x *VolumeMount) GetSubPath() string { + if x != nil { + return x.SubPath + } + return "" +} + +func (x *VolumeMount) GetReadOnly() bool { + if x != nil { + return x.ReadOnly + } + return false +} + +type ResourceRequests struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cpu string `protobuf:"bytes,1,opt,name=cpu,proto3" json:"cpu,omitempty"` // e.g., "100m" + Memory string `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` // e.g., "64Mi" + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceRequests) Reset() { + *x = ResourceRequests{} + mi := &file_kat_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceRequests) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceRequests) ProtoMessage() {} + +func (x *ResourceRequests) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResourceRequests.ProtoReflect.Descriptor instead. +func (*ResourceRequests) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{9} +} + +func (x *ResourceRequests) GetCpu() string { + if x != nil { + return x.Cpu + } + return "" +} + +func (x *ResourceRequests) GetMemory() string { + if x != nil { + return x.Memory + } + return "" +} + +type ResourceLimits struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cpu string `protobuf:"bytes,1,opt,name=cpu,proto3" json:"cpu,omitempty"` // e.g., "1" + Memory string `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` // e.g., "256Mi" + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceLimits) Reset() { + *x = ResourceLimits{} + mi := &file_kat_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceLimits) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceLimits) ProtoMessage() {} + +func (x *ResourceLimits) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResourceLimits.ProtoReflect.Descriptor instead. +func (*ResourceLimits) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{10} +} + +func (x *ResourceLimits) GetCpu() string { + if x != nil { + return x.Cpu + } + return "" +} + +func (x *ResourceLimits) GetMemory() string { + if x != nil { + return x.Memory + } + return "" +} + +type GPUSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Driver GPUDriver `protobuf:"varint,1,opt,name=driver,proto3,enum=v1alpha1.GPUDriver" json:"driver,omitempty"` + MinVramMb int32 `protobuf:"varint,2,opt,name=min_vram_mb,json=minVramMb,proto3" json:"min_vram_mb,omitempty"` // Minimum GPU memory required + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GPUSpec) Reset() { + *x = GPUSpec{} + mi := &file_kat_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GPUSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GPUSpec) ProtoMessage() {} + +func (x *GPUSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GPUSpec.ProtoReflect.Descriptor instead. +func (*GPUSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{11} +} + +func (x *GPUSpec) GetDriver() GPUDriver { + if x != nil { + return x.Driver + } + return GPUDriver_GPU_DRIVER_UNSPECIFIED +} + +func (x *GPUSpec) GetMinVramMb() int32 { + if x != nil { + return x.MinVramMb + } + return 0 +} + +type ContainerResources struct { + state protoimpl.MessageState `protogen:"open.v1"` + Requests *ResourceRequests `protobuf:"bytes,1,opt,name=requests,proto3" json:"requests,omitempty"` + Limits *ResourceLimits `protobuf:"bytes,2,opt,name=limits,proto3" json:"limits,omitempty"` + Gpu *GPUSpec `protobuf:"bytes,3,opt,name=gpu,proto3" json:"gpu,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ContainerResources) Reset() { + *x = ContainerResources{} + mi := &file_kat_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ContainerResources) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ContainerResources) ProtoMessage() {} + +func (x *ContainerResources) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ContainerResources.ProtoReflect.Descriptor instead. +func (*ContainerResources) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{12} +} + +func (x *ContainerResources) GetRequests() *ResourceRequests { + if x != nil { + return x.Requests + } + return nil +} + +func (x *ContainerResources) GetLimits() *ResourceLimits { + if x != nil { + return x.Limits + } + return nil +} + +func (x *ContainerResources) GetGpu() *GPUSpec { + if x != nil { + return x.Gpu + } + return nil +} + +type Container struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Optional: Informational name + Command []string `protobuf:"bytes,2,rep,name=command,proto3" json:"command,omitempty"` + Args []string `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` + Env []*EnvVar `protobuf:"bytes,4,rep,name=env,proto3" json:"env,omitempty"` + VolumeMounts []*VolumeMount `protobuf:"bytes,5,rep,name=volume_mounts,json=volumeMounts,proto3" json:"volume_mounts,omitempty"` + Resources *ContainerResources `protobuf:"bytes,6,opt,name=resources,proto3" json:"resources,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Container) Reset() { + *x = Container{} + mi := &file_kat_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Container) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Container) ProtoMessage() {} + +func (x *Container) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Container.ProtoReflect.Descriptor instead. +func (*Container) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{13} +} + +func (x *Container) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Container) GetCommand() []string { + if x != nil { + return x.Command + } + return nil +} + +func (x *Container) GetArgs() []string { + if x != nil { + return x.Args + } + return nil +} + +func (x *Container) GetEnv() []*EnvVar { + if x != nil { + return x.Env + } + return nil +} + +func (x *Container) GetVolumeMounts() []*VolumeMount { + if x != nil { + return x.VolumeMounts + } + return nil +} + +func (x *Container) GetResources() *ContainerResources { + if x != nil { + return x.Resources + } + return nil +} + +type SimpleClusterStorageVolumeSource struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SimpleClusterStorageVolumeSource) Reset() { + *x = SimpleClusterStorageVolumeSource{} + mi := &file_kat_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SimpleClusterStorageVolumeSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SimpleClusterStorageVolumeSource) ProtoMessage() {} + +func (x *SimpleClusterStorageVolumeSource) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SimpleClusterStorageVolumeSource.ProtoReflect.Descriptor instead. +func (*SimpleClusterStorageVolumeSource) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{14} +} + +type HostMountVolumeSource struct { + state protoimpl.MessageState `protogen:"open.v1"` + HostPath string `protobuf:"bytes,1,opt,name=host_path,json=hostPath,proto3" json:"host_path,omitempty"` // Absolute path on host + EnsureType HostPathType `protobuf:"varint,2,opt,name=ensure_type,json=ensureType,proto3,enum=v1alpha1.HostPathType" json:"ensure_type,omitempty"` // Optional: Type to ensure/check + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HostMountVolumeSource) Reset() { + *x = HostMountVolumeSource{} + mi := &file_kat_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HostMountVolumeSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostMountVolumeSource) ProtoMessage() {} + +func (x *HostMountVolumeSource) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HostMountVolumeSource.ProtoReflect.Descriptor instead. +func (*HostMountVolumeSource) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{15} +} + +func (x *HostMountVolumeSource) GetHostPath() string { + if x != nil { + return x.HostPath + } + return "" +} + +func (x *HostMountVolumeSource) GetEnsureType() HostPathType { + if x != nil { + return x.EnsureType + } + return HostPathType_HOST_PATH_TYPE_UNSPECIFIED +} + +type Volume struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Name referenced by volumeMounts + // Types that are valid to be assigned to VolumeSource: + // + // *Volume_SimpleClusterStorage + // *Volume_HostMount + VolumeSource isVolume_VolumeSource `protobuf_oneof:"volume_source"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Volume) Reset() { + *x = Volume{} + mi := &file_kat_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Volume) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Volume) ProtoMessage() {} + +func (x *Volume) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Volume.ProtoReflect.Descriptor instead. +func (*Volume) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{16} +} + +func (x *Volume) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Volume) GetVolumeSource() isVolume_VolumeSource { + if x != nil { + return x.VolumeSource + } + return nil +} + +func (x *Volume) GetSimpleClusterStorage() *SimpleClusterStorageVolumeSource { + if x != nil { + if x, ok := x.VolumeSource.(*Volume_SimpleClusterStorage); ok { + return x.SimpleClusterStorage + } + } + return nil +} + +func (x *Volume) GetHostMount() *HostMountVolumeSource { + if x != nil { + if x, ok := x.VolumeSource.(*Volume_HostMount); ok { + return x.HostMount + } + } + return nil +} + +type isVolume_VolumeSource interface { + isVolume_VolumeSource() +} + +type Volume_SimpleClusterStorage struct { + SimpleClusterStorage *SimpleClusterStorageVolumeSource `protobuf:"bytes,2,opt,name=simple_cluster_storage,json=simpleClusterStorage,proto3,oneof"` +} + +type Volume_HostMount struct { + HostMount *HostMountVolumeSource `protobuf:"bytes,3,opt,name=host_mount,json=hostMount,proto3,oneof"` +} + +func (*Volume_SimpleClusterStorage) isVolume_VolumeSource() {} + +func (*Volume_HostMount) isVolume_VolumeSource() {} + +type WorkloadSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Type WorkloadType `protobuf:"varint,1,opt,name=type,proto3,enum=v1alpha1.WorkloadType" json:"type,omitempty"` + Source *WorkloadSource `protobuf:"bytes,2,opt,name=source,proto3" json:"source,omitempty"` + Replicas int32 `protobuf:"varint,3,opt,name=replicas,proto3" json:"replicas,omitempty"` // Required for SERVICE + UpdateStrategy *UpdateStrategy `protobuf:"bytes,4,opt,name=update_strategy,json=updateStrategy,proto3" json:"update_strategy,omitempty"` + RestartPolicy *RestartPolicy `protobuf:"bytes,5,opt,name=restart_policy,json=restartPolicy,proto3" json:"restart_policy,omitempty"` + NodeSelector map[string]string `protobuf:"bytes,6,rep,name=node_selector,json=nodeSelector,proto3" json:"node_selector,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Tolerations []*Toleration `protobuf:"bytes,7,rep,name=tolerations,proto3" json:"tolerations,omitempty"` + Container *Container `protobuf:"bytes,8,opt,name=container,proto3" json:"container,omitempty"` + Volumes []*Volume `protobuf:"bytes,9,rep,name=volumes,proto3" json:"volumes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkloadSpec) Reset() { + *x = WorkloadSpec{} + mi := &file_kat_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkloadSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadSpec) ProtoMessage() {} + +func (x *WorkloadSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadSpec.ProtoReflect.Descriptor instead. +func (*WorkloadSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{17} +} + +func (x *WorkloadSpec) GetType() WorkloadType { + if x != nil { + return x.Type + } + return WorkloadType_WORKLOAD_TYPE_UNSPECIFIED +} + +func (x *WorkloadSpec) GetSource() *WorkloadSource { + if x != nil { + return x.Source + } + return nil +} + +func (x *WorkloadSpec) GetReplicas() int32 { + if x != nil { + return x.Replicas + } + return 0 +} + +func (x *WorkloadSpec) GetUpdateStrategy() *UpdateStrategy { + if x != nil { + return x.UpdateStrategy + } + return nil +} + +func (x *WorkloadSpec) GetRestartPolicy() *RestartPolicy { + if x != nil { + return x.RestartPolicy + } + return nil +} + +func (x *WorkloadSpec) GetNodeSelector() map[string]string { + if x != nil { + return x.NodeSelector + } + return nil +} + +func (x *WorkloadSpec) GetTolerations() []*Toleration { + if x != nil { + return x.Tolerations + } + return nil +} + +func (x *WorkloadSpec) GetContainer() *Container { + if x != nil { + return x.Container + } + return nil +} + +func (x *WorkloadSpec) GetVolumes() []*Volume { + if x != nil { + return x.Volumes + } + return nil +} + +type WorkloadStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkloadStatus) Reset() { + *x = WorkloadStatus{} + mi := &file_kat_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkloadStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkloadStatus) ProtoMessage() {} + +func (x *WorkloadStatus) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkloadStatus.ProtoReflect.Descriptor instead. +func (*WorkloadStatus) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{18} +} + +type Workload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metadata *ObjectMeta `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + Spec *WorkloadSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` + Status *WorkloadStatus `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Workload) Reset() { + *x = Workload{} + mi := &file_kat_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Workload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Workload) ProtoMessage() {} + +func (x *Workload) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Workload.ProtoReflect.Descriptor instead. +func (*Workload) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{19} +} + +func (x *Workload) GetMetadata() *ObjectMeta { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *Workload) GetSpec() *WorkloadSpec { + if x != nil { + return x.Spec + } + return nil +} + +func (x *Workload) GetStatus() *WorkloadStatus { + if x != nil { + return x.Status + } + return nil +} + +// VirtualLoadBalancer (RFC 3.3) +type PortSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // Optional: e.g., "web", "grpc" + ContainerPort int32 `protobuf:"varint,2,opt,name=container_port,json=containerPort,proto3" json:"container_port,omitempty"` // Port app listens on in container + Protocol string `protobuf:"bytes,3,opt,name=protocol,proto3" json:"protocol,omitempty"` // Optional: TCP | UDP. Default TCP. + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PortSpec) Reset() { + *x = PortSpec{} + mi := &file_kat_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PortSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PortSpec) ProtoMessage() {} + +func (x *PortSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PortSpec.ProtoReflect.Descriptor instead. +func (*PortSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{20} +} + +func (x *PortSpec) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *PortSpec) GetContainerPort() int32 { + if x != nil { + return x.ContainerPort + } + return 0 +} + +func (x *PortSpec) GetProtocol() string { + if x != nil { + return x.Protocol + } + return "" +} + +type ExecHealthCheck struct { + state protoimpl.MessageState `protogen:"open.v1"` + Command []string `protobuf:"bytes,1,rep,name=command,proto3" json:"command,omitempty"` // Exit 0 = healthy + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExecHealthCheck) Reset() { + *x = ExecHealthCheck{} + mi := &file_kat_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExecHealthCheck) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecHealthCheck) ProtoMessage() {} + +func (x *ExecHealthCheck) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecHealthCheck.ProtoReflect.Descriptor instead. +func (*ExecHealthCheck) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{21} +} + +func (x *ExecHealthCheck) GetCommand() []string { + if x != nil { + return x.Command + } + return nil +} + +type HealthCheck struct { + state protoimpl.MessageState `protogen:"open.v1"` + Exec *ExecHealthCheck `protobuf:"bytes,1,opt,name=exec,proto3" json:"exec,omitempty"` + InitialDelaySeconds int32 `protobuf:"varint,2,opt,name=initial_delay_seconds,json=initialDelaySeconds,proto3" json:"initial_delay_seconds,omitempty"` + PeriodSeconds int32 `protobuf:"varint,3,opt,name=period_seconds,json=periodSeconds,proto3" json:"period_seconds,omitempty"` + TimeoutSeconds int32 `protobuf:"varint,4,opt,name=timeout_seconds,json=timeoutSeconds,proto3" json:"timeout_seconds,omitempty"` + SuccessThreshold int32 `protobuf:"varint,5,opt,name=success_threshold,json=successThreshold,proto3" json:"success_threshold,omitempty"` + FailureThreshold int32 `protobuf:"varint,6,opt,name=failure_threshold,json=failureThreshold,proto3" json:"failure_threshold,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HealthCheck) Reset() { + *x = HealthCheck{} + mi := &file_kat_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HealthCheck) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HealthCheck) ProtoMessage() {} + +func (x *HealthCheck) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HealthCheck.ProtoReflect.Descriptor instead. +func (*HealthCheck) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{22} +} + +func (x *HealthCheck) GetExec() *ExecHealthCheck { + if x != nil { + return x.Exec + } + return nil +} + +func (x *HealthCheck) GetInitialDelaySeconds() int32 { + if x != nil { + return x.InitialDelaySeconds + } + return 0 +} + +func (x *HealthCheck) GetPeriodSeconds() int32 { + if x != nil { + return x.PeriodSeconds + } + return 0 +} + +func (x *HealthCheck) GetTimeoutSeconds() int32 { + if x != nil { + return x.TimeoutSeconds + } + return 0 +} + +func (x *HealthCheck) GetSuccessThreshold() int32 { + if x != nil { + return x.SuccessThreshold + } + return 0 +} + +func (x *HealthCheck) GetFailureThreshold() int32 { + if x != nil { + return x.FailureThreshold + } + return 0 +} + +type IngressRule struct { + state protoimpl.MessageState `protogen:"open.v1"` + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + ServicePortName string `protobuf:"bytes,3,opt,name=service_port_name,json=servicePortName,proto3" json:"service_port_name,omitempty"` // Name of port from PortSpec + ServicePort int32 `protobuf:"varint,4,opt,name=service_port,json=servicePort,proto3" json:"service_port,omitempty"` // Port number from PortSpec (overrides name) + Tls bool `protobuf:"varint,5,opt,name=tls,proto3" json:"tls,omitempty"` // Signal for ACME + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *IngressRule) Reset() { + *x = IngressRule{} + mi := &file_kat_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *IngressRule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IngressRule) ProtoMessage() {} + +func (x *IngressRule) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IngressRule.ProtoReflect.Descriptor instead. +func (*IngressRule) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{23} +} + +func (x *IngressRule) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (x *IngressRule) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *IngressRule) GetServicePortName() string { + if x != nil { + return x.ServicePortName + } + return "" +} + +func (x *IngressRule) GetServicePort() int32 { + if x != nil { + return x.ServicePort + } + return 0 +} + +func (x *IngressRule) GetTls() bool { + if x != nil { + return x.Tls + } + return false +} + +type VirtualLoadBalancerSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Ports []*PortSpec `protobuf:"bytes,1,rep,name=ports,proto3" json:"ports,omitempty"` + HealthCheck *HealthCheck `protobuf:"bytes,2,opt,name=health_check,json=healthCheck,proto3" json:"health_check,omitempty"` + Ingress []*IngressRule `protobuf:"bytes,3,rep,name=ingress,proto3" json:"ingress,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VirtualLoadBalancerSpec) Reset() { + *x = VirtualLoadBalancerSpec{} + mi := &file_kat_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VirtualLoadBalancerSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VirtualLoadBalancerSpec) ProtoMessage() {} + +func (x *VirtualLoadBalancerSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VirtualLoadBalancerSpec.ProtoReflect.Descriptor instead. +func (*VirtualLoadBalancerSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{24} +} + +func (x *VirtualLoadBalancerSpec) GetPorts() []*PortSpec { + if x != nil { + return x.Ports + } + return nil +} + +func (x *VirtualLoadBalancerSpec) GetHealthCheck() *HealthCheck { + if x != nil { + return x.HealthCheck + } + return nil +} + +func (x *VirtualLoadBalancerSpec) GetIngress() []*IngressRule { + if x != nil { + return x.Ingress + } + return nil +} + +type VirtualLoadBalancer struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metadata *ObjectMeta `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` // Name likely matches Workload name + Spec *VirtualLoadBalancerSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` // VirtualLoadBalancerStatus status = 3; // Placeholder + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VirtualLoadBalancer) Reset() { + *x = VirtualLoadBalancer{} + mi := &file_kat_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VirtualLoadBalancer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VirtualLoadBalancer) ProtoMessage() {} + +func (x *VirtualLoadBalancer) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VirtualLoadBalancer.ProtoReflect.Descriptor instead. +func (*VirtualLoadBalancer) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{25} +} + +func (x *VirtualLoadBalancer) GetMetadata() *ObjectMeta { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *VirtualLoadBalancer) GetSpec() *VirtualLoadBalancerSpec { + if x != nil { + return x.Spec + } + return nil +} + +// JobDefinition (RFC 3.4) +type JobDefinitionSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Schedule string `protobuf:"bytes,1,opt,name=schedule,proto3" json:"schedule,omitempty"` // Optional: Cron schedule + Completions int32 `protobuf:"varint,2,opt,name=completions,proto3" json:"completions,omitempty"` // Optional: Default 1 + Parallelism int32 `protobuf:"varint,3,opt,name=parallelism,proto3" json:"parallelism,omitempty"` // Optional: Default 1 + ActiveDeadlineSeconds int32 `protobuf:"varint,4,opt,name=active_deadline_seconds,json=activeDeadlineSeconds,proto3" json:"active_deadline_seconds,omitempty"` // Optional + BackoffLimit int32 `protobuf:"varint,5,opt,name=backoff_limit,json=backoffLimit,proto3" json:"backoff_limit,omitempty"` // Optional: Default 3 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JobDefinitionSpec) Reset() { + *x = JobDefinitionSpec{} + mi := &file_kat_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JobDefinitionSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JobDefinitionSpec) ProtoMessage() {} + +func (x *JobDefinitionSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[26] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JobDefinitionSpec.ProtoReflect.Descriptor instead. +func (*JobDefinitionSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{26} +} + +func (x *JobDefinitionSpec) GetSchedule() string { + if x != nil { + return x.Schedule + } + return "" +} + +func (x *JobDefinitionSpec) GetCompletions() int32 { + if x != nil { + return x.Completions + } + return 0 +} + +func (x *JobDefinitionSpec) GetParallelism() int32 { + if x != nil { + return x.Parallelism + } + return 0 +} + +func (x *JobDefinitionSpec) GetActiveDeadlineSeconds() int32 { + if x != nil { + return x.ActiveDeadlineSeconds + } + return 0 +} + +func (x *JobDefinitionSpec) GetBackoffLimit() int32 { + if x != nil { + return x.BackoffLimit + } + return 0 +} + +type JobDefinition struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metadata *ObjectMeta `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` // Name likely matches Workload name + Spec *JobDefinitionSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` // JobDefinitionStatus status = 3; // Placeholder + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JobDefinition) Reset() { + *x = JobDefinition{} + mi := &file_kat_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JobDefinition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JobDefinition) ProtoMessage() {} + +func (x *JobDefinition) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JobDefinition.ProtoReflect.Descriptor instead. +func (*JobDefinition) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{27} +} + +func (x *JobDefinition) GetMetadata() *ObjectMeta { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *JobDefinition) GetSpec() *JobDefinitionSpec { + if x != nil { + return x.Spec + } + return nil +} + +// BuildDefinition (RFC 3.5) +type BuildCache struct { + state protoimpl.MessageState `protogen:"open.v1"` + RegistryPath string `protobuf:"bytes,1,opt,name=registry_path,json=registryPath,proto3" json:"registry_path,omitempty"` // e.g., "myreg.com/cache/myapp" + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BuildCache) Reset() { + *x = BuildCache{} + mi := &file_kat_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BuildCache) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BuildCache) ProtoMessage() {} + +func (x *BuildCache) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BuildCache.ProtoReflect.Descriptor instead. +func (*BuildCache) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{28} +} + +func (x *BuildCache) GetRegistryPath() string { + if x != nil { + return x.RegistryPath + } + return "" +} + +type BuildDefinitionSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + BuildContext string `protobuf:"bytes,1,opt,name=build_context,json=buildContext,proto3" json:"build_context,omitempty"` // Optional: Path relative to repo root. Defaults to "." + DockerfilePath string `protobuf:"bytes,2,opt,name=dockerfile_path,json=dockerfilePath,proto3" json:"dockerfile_path,omitempty"` // Optional: Path relative to buildContext. Defaults to "./Dockerfile" + BuildArgs map[string]string `protobuf:"bytes,3,rep,name=build_args,json=buildArgs,proto3" json:"build_args,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Optional + TargetStage string `protobuf:"bytes,4,opt,name=target_stage,json=targetStage,proto3" json:"target_stage,omitempty"` // Optional + Platform string `protobuf:"bytes,5,opt,name=platform,proto3" json:"platform,omitempty"` // Optional: e.g., "linux/arm64" + Cache *BuildCache `protobuf:"bytes,6,opt,name=cache,proto3" json:"cache,omitempty"` // Optional + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BuildDefinitionSpec) Reset() { + *x = BuildDefinitionSpec{} + mi := &file_kat_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BuildDefinitionSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BuildDefinitionSpec) ProtoMessage() {} + +func (x *BuildDefinitionSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[29] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BuildDefinitionSpec.ProtoReflect.Descriptor instead. +func (*BuildDefinitionSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{29} +} + +func (x *BuildDefinitionSpec) GetBuildContext() string { + if x != nil { + return x.BuildContext + } + return "" +} + +func (x *BuildDefinitionSpec) GetDockerfilePath() string { + if x != nil { + return x.DockerfilePath + } + return "" +} + +func (x *BuildDefinitionSpec) GetBuildArgs() map[string]string { + if x != nil { + return x.BuildArgs + } + return nil +} + +func (x *BuildDefinitionSpec) GetTargetStage() string { + if x != nil { + return x.TargetStage + } + return "" +} + +func (x *BuildDefinitionSpec) GetPlatform() string { + if x != nil { + return x.Platform + } + return "" +} + +func (x *BuildDefinitionSpec) GetCache() *BuildCache { + if x != nil { + return x.Cache + } + return nil +} + +type BuildDefinition struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metadata *ObjectMeta `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` // Name likely matches Workload name + Spec *BuildDefinitionSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` // BuildDefinitionStatus status = 3; // Placeholder + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BuildDefinition) Reset() { + *x = BuildDefinition{} + mi := &file_kat_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BuildDefinition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BuildDefinition) ProtoMessage() {} + +func (x *BuildDefinition) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[30] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BuildDefinition.ProtoReflect.Descriptor instead. +func (*BuildDefinition) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{30} +} + +func (x *BuildDefinition) GetMetadata() *ObjectMeta { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *BuildDefinition) GetSpec() *BuildDefinitionSpec { + if x != nil { + return x.Spec + } + return nil +} + +// Namespace (RFC 3.7) +type NamespaceSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NamespaceSpec) Reset() { + *x = NamespaceSpec{} + mi := &file_kat_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NamespaceSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NamespaceSpec) ProtoMessage() {} + +func (x *NamespaceSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[31] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NamespaceSpec.ProtoReflect.Descriptor instead. +func (*NamespaceSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{31} +} + +type NamespaceStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NamespaceStatus) Reset() { + *x = NamespaceStatus{} + mi := &file_kat_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NamespaceStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NamespaceStatus) ProtoMessage() {} + +func (x *NamespaceStatus) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NamespaceStatus.ProtoReflect.Descriptor instead. +func (*NamespaceStatus) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{32} +} + +type Namespace struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metadata *ObjectMeta `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + Spec *NamespaceSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` + Status *NamespaceStatus `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Namespace) Reset() { + *x = Namespace{} + mi := &file_kat_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Namespace) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Namespace) ProtoMessage() {} + +func (x *Namespace) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[33] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Namespace.ProtoReflect.Descriptor instead. +func (*Namespace) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{33} +} + +func (x *Namespace) GetMetadata() *ObjectMeta { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *Namespace) GetSpec() *NamespaceSpec { + if x != nil { + return x.Spec + } + return nil +} + +func (x *Namespace) GetStatus() *NamespaceStatus { + if x != nil { + return x.Status + } + return nil +} + +// Node (Internal Representation - RFC 3.8) +type NodeResources struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cpu string `protobuf:"bytes,1,opt,name=cpu,proto3" json:"cpu,omitempty"` // e.g., "2000m" + Memory string `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` // e.g., "4096Mi" + CustomResources map[string]string `protobuf:"bytes,3,rep,name=custom_resources,json=customResources,proto3" json:"custom_resources,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // e.g., for GPUs "nvidia.com/gpu: 2" + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NodeResources) Reset() { + *x = NodeResources{} + mi := &file_kat_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NodeResources) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeResources) ProtoMessage() {} + +func (x *NodeResources) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[34] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeResources.ProtoReflect.Descriptor instead. +func (*NodeResources) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{34} +} + +func (x *NodeResources) GetCpu() string { + if x != nil { + return x.Cpu + } + return "" +} + +func (x *NodeResources) GetMemory() string { + if x != nil { + return x.Memory + } + return "" +} + +func (x *NodeResources) GetCustomResources() map[string]string { + if x != nil { + return x.CustomResources + } + return nil +} + +type NodeStatusDetails struct { + state protoimpl.MessageState `protogen:"open.v1"` + Capacity *NodeResources `protobuf:"bytes,1,opt,name=capacity,proto3" json:"capacity,omitempty"` + Allocatable *NodeResources `protobuf:"bytes,2,opt,name=allocatable,proto3" json:"allocatable,omitempty"` + // repeated WorkloadInstanceStatus workload_instances = 3; // Define later + // OverlayNetworkStatus overlay_network = 4; // Define later + Condition string `protobuf:"bytes,5,opt,name=condition,proto3" json:"condition,omitempty"` // e.g., "Ready", "NotReady", "Draining" + LastHeartbeatTime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=last_heartbeat_time,json=lastHeartbeatTime,proto3" json:"last_heartbeat_time,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NodeStatusDetails) Reset() { + *x = NodeStatusDetails{} + mi := &file_kat_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NodeStatusDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeStatusDetails) ProtoMessage() {} + +func (x *NodeStatusDetails) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[35] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeStatusDetails.ProtoReflect.Descriptor instead. +func (*NodeStatusDetails) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{35} +} + +func (x *NodeStatusDetails) GetCapacity() *NodeResources { + if x != nil { + return x.Capacity + } + return nil +} + +func (x *NodeStatusDetails) GetAllocatable() *NodeResources { + if x != nil { + return x.Allocatable + } + return nil +} + +func (x *NodeStatusDetails) GetCondition() string { + if x != nil { + return x.Condition + } + return "" +} + +func (x *NodeStatusDetails) GetLastHeartbeatTime() *timestamppb.Timestamp { + if x != nil { + return x.LastHeartbeatTime + } + return nil +} + +type Taint struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Effect Taint_Effect `protobuf:"varint,3,opt,name=effect,proto3,enum=v1alpha1.Taint_Effect" json:"effect,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Taint) Reset() { + *x = Taint{} + mi := &file_kat_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Taint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Taint) ProtoMessage() {} + +func (x *Taint) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[36] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Taint.ProtoReflect.Descriptor instead. +func (*Taint) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{36} +} + +func (x *Taint) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Taint) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *Taint) GetEffect() Taint_Effect { + if x != nil { + return x.Effect + } + return Taint_EFFECT_UNSPECIFIED +} + +type NodeSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Taints []*Taint `protobuf:"bytes,1,rep,name=taints,proto3" json:"taints,omitempty"` + OverlaySubnet string `protobuf:"bytes,2,opt,name=overlay_subnet,json=overlaySubnet,proto3" json:"overlay_subnet,omitempty"` // Assigned by leader + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NodeSpec) Reset() { + *x = NodeSpec{} + mi := &file_kat_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NodeSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeSpec) ProtoMessage() {} + +func (x *NodeSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[37] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeSpec.ProtoReflect.Descriptor instead. +func (*NodeSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{37} +} + +func (x *NodeSpec) GetTaints() []*Taint { + if x != nil { + return x.Taints + } + return nil +} + +func (x *NodeSpec) GetOverlaySubnet() string { + if x != nil { + return x.OverlaySubnet + } + return "" +} + +type Node struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metadata *ObjectMeta `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` // Name is the unique node name/ID + Spec *NodeSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` + Status *NodeStatusDetails `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Node) Reset() { + *x = Node{} + mi := &file_kat_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Node) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Node) ProtoMessage() {} + +func (x *Node) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[38] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Node.ProtoReflect.Descriptor instead. +func (*Node) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{38} +} + +func (x *Node) GetMetadata() *ObjectMeta { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *Node) GetSpec() *NodeSpec { + if x != nil { + return x.Spec + } + return nil +} + +func (x *Node) GetStatus() *NodeStatusDetails { + if x != nil { + return x.Status + } + return nil +} + +// ClusterConfiguration (RFC 3.9) +type ClusterConfigurationSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + ClusterCidr string `protobuf:"bytes,1,opt,name=cluster_cidr,json=clusterCidr,proto3" json:"cluster_cidr,omitempty"` + ServiceCidr string `protobuf:"bytes,2,opt,name=service_cidr,json=serviceCidr,proto3" json:"service_cidr,omitempty"` + NodeSubnetBits int32 `protobuf:"varint,3,opt,name=node_subnet_bits,json=nodeSubnetBits,proto3" json:"node_subnet_bits,omitempty"` + ClusterDomain string `protobuf:"bytes,4,opt,name=cluster_domain,json=clusterDomain,proto3" json:"cluster_domain,omitempty"` + AgentPort int32 `protobuf:"varint,5,opt,name=agent_port,json=agentPort,proto3" json:"agent_port,omitempty"` + ApiPort int32 `protobuf:"varint,6,opt,name=api_port,json=apiPort,proto3" json:"api_port,omitempty"` + EtcdPeerPort int32 `protobuf:"varint,7,opt,name=etcd_peer_port,json=etcdPeerPort,proto3" json:"etcd_peer_port,omitempty"` + EtcdClientPort int32 `protobuf:"varint,8,opt,name=etcd_client_port,json=etcdClientPort,proto3" json:"etcd_client_port,omitempty"` + VolumeBasePath string `protobuf:"bytes,9,opt,name=volume_base_path,json=volumeBasePath,proto3" json:"volume_base_path,omitempty"` + BackupPath string `protobuf:"bytes,10,opt,name=backup_path,json=backupPath,proto3" json:"backup_path,omitempty"` + BackupIntervalMinutes int32 `protobuf:"varint,11,opt,name=backup_interval_minutes,json=backupIntervalMinutes,proto3" json:"backup_interval_minutes,omitempty"` + AgentTickSeconds int32 `protobuf:"varint,12,opt,name=agent_tick_seconds,json=agentTickSeconds,proto3" json:"agent_tick_seconds,omitempty"` + NodeLossTimeoutSeconds int32 `protobuf:"varint,13,opt,name=node_loss_timeout_seconds,json=nodeLossTimeoutSeconds,proto3" json:"node_loss_timeout_seconds,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClusterConfigurationSpec) Reset() { + *x = ClusterConfigurationSpec{} + mi := &file_kat_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClusterConfigurationSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterConfigurationSpec) ProtoMessage() {} + +func (x *ClusterConfigurationSpec) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[39] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterConfigurationSpec.ProtoReflect.Descriptor instead. +func (*ClusterConfigurationSpec) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{39} +} + +func (x *ClusterConfigurationSpec) GetClusterCidr() string { + if x != nil { + return x.ClusterCidr + } + return "" +} + +func (x *ClusterConfigurationSpec) GetServiceCidr() string { + if x != nil { + return x.ServiceCidr + } + return "" +} + +func (x *ClusterConfigurationSpec) GetNodeSubnetBits() int32 { + if x != nil { + return x.NodeSubnetBits + } + return 0 +} + +func (x *ClusterConfigurationSpec) GetClusterDomain() string { + if x != nil { + return x.ClusterDomain + } + return "" +} + +func (x *ClusterConfigurationSpec) GetAgentPort() int32 { + if x != nil { + return x.AgentPort + } + return 0 +} + +func (x *ClusterConfigurationSpec) GetApiPort() int32 { + if x != nil { + return x.ApiPort + } + return 0 +} + +func (x *ClusterConfigurationSpec) GetEtcdPeerPort() int32 { + if x != nil { + return x.EtcdPeerPort + } + return 0 +} + +func (x *ClusterConfigurationSpec) GetEtcdClientPort() int32 { + if x != nil { + return x.EtcdClientPort + } + return 0 +} + +func (x *ClusterConfigurationSpec) GetVolumeBasePath() string { + if x != nil { + return x.VolumeBasePath + } + return "" +} + +func (x *ClusterConfigurationSpec) GetBackupPath() string { + if x != nil { + return x.BackupPath + } + return "" +} + +func (x *ClusterConfigurationSpec) GetBackupIntervalMinutes() int32 { + if x != nil { + return x.BackupIntervalMinutes + } + return 0 +} + +func (x *ClusterConfigurationSpec) GetAgentTickSeconds() int32 { + if x != nil { + return x.AgentTickSeconds + } + return 0 +} + +func (x *ClusterConfigurationSpec) GetNodeLossTimeoutSeconds() int32 { + if x != nil { + return x.NodeLossTimeoutSeconds + } + return 0 +} + +type ClusterConfiguration struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metadata *ObjectMeta `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` // e.g., name of the cluster + Spec *ClusterConfigurationSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` // ClusterConfigurationStatus status = 3; // Placeholder + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClusterConfiguration) Reset() { + *x = ClusterConfiguration{} + mi := &file_kat_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClusterConfiguration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterConfiguration) ProtoMessage() {} + +func (x *ClusterConfiguration) ProtoReflect() protoreflect.Message { + mi := &file_kat_proto_msgTypes[40] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterConfiguration.ProtoReflect.Descriptor instead. +func (*ClusterConfiguration) Descriptor() ([]byte, []int) { + return file_kat_proto_rawDescGZIP(), []int{40} +} + +func (x *ClusterConfiguration) GetMetadata() *ObjectMeta { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *ClusterConfiguration) GetSpec() *ClusterConfigurationSpec { + if x != nil { + return x.Spec + } + return nil +} + +var File_kat_proto protoreflect.FileDescriptor + +const file_kat_proto_rawDesc = "" + + "\n" + + "\tkat.proto\x12\bv1alpha1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xe4\x03\n" + + "\n" + + "ObjectMeta\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1c\n" + + "\tnamespace\x18\x02 \x01(\tR\tnamespace\x12\x10\n" + + "\x03uid\x18\x03 \x01(\tR\x03uid\x12\x1e\n" + + "\n" + + "generation\x18\x04 \x01(\x03R\n" + + "generation\x12)\n" + + "\x10resource_version\x18\x05 \x01(\tR\x0fresourceVersion\x12I\n" + + "\x12creation_timestamp\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\x11creationTimestamp\x128\n" + + "\x06labels\x18\a \x03(\v2 .v1alpha1.ObjectMeta.LabelsEntryR\x06labels\x12G\n" + + "\vannotations\x18\b \x03(\v2%.v1alpha1.ObjectMeta.AnnotationsEntryR\vannotations\x1a9\n" + + "\vLabelsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1a>\n" + + "\x10AnnotationsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"m\n" + + "\tGitSource\x12\x1e\n" + + "\n" + + "repository\x18\x01 \x01(\tR\n" + + "repository\x12\x16\n" + + "\x06branch\x18\x02 \x01(\tR\x06branch\x12\x10\n" + + "\x03tag\x18\x03 \x01(\tR\x03tag\x12\x16\n" + + "\x06commit\x18\x04 \x01(\tR\x06commit\"\x81\x01\n" + + "\x0eWorkloadSource\x12\x16\n" + + "\x05image\x18\x01 \x01(\tH\x00R\x05image\x12'\n" + + "\x03git\x18\x02 \x01(\v2\x13.v1alpha1.GitSourceH\x00R\x03git\x12\x1f\n" + + "\vcache_image\x18\x03 \x01(\tR\n" + + "cacheImageB\r\n" + + "\vsource_type\"4\n" + + "\x15RollingUpdateStrategy\x12\x1b\n" + + "\tmax_surge\x18\x01 \x01(\tR\bmaxSurge\"}\n" + + "\x0eUpdateStrategy\x120\n" + + "\x04type\x18\x01 \x01(\x0e2\x1c.v1alpha1.UpdateStrategyTypeR\x04type\x129\n" + + "\arolling\x18\x02 \x01(\v2\x1f.v1alpha1.RollingUpdateStrategyR\arolling\"\x91\x01\n" + + "\rRestartPolicy\x128\n" + + "\tcondition\x18\x01 \x01(\x0e2\x1a.v1alpha1.RestartConditionR\tcondition\x12!\n" + + "\fmax_restarts\x18\x02 \x01(\x05R\vmaxRestarts\x12#\n" + + "\rreset_seconds\x18\x03 \x01(\x05R\fresetSeconds\"\xac\x02\n" + + "\n" + + "Toleration\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x129\n" + + "\boperator\x18\x02 \x01(\x0e2\x1d.v1alpha1.Toleration.OperatorR\boperator\x12\x14\n" + + "\x05value\x18\x03 \x01(\tR\x05value\x123\n" + + "\x06effect\x18\x04 \x01(\x0e2\x1b.v1alpha1.Toleration.EffectR\x06effect\";\n" + + "\bOperator\x12\x18\n" + + "\x14OPERATOR_UNSPECIFIED\x10\x00\x12\n" + + "\n" + + "\x06EXISTS\x10\x01\x12\t\n" + + "\x05EQUAL\x10\x02\"I\n" + + "\x06Effect\x12\x16\n" + + "\x12EFFECT_UNSPECIFIED\x10\x00\x12\x0f\n" + + "\vNO_SCHEDULE\x10\x01\x12\x16\n" + + "\x12PREFER_NO_SCHEDULE\x10\x02\"2\n" + + "\x06EnvVar\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value\"x\n" + + "\vVolumeMount\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x1d\n" + + "\n" + + "mount_path\x18\x02 \x01(\tR\tmountPath\x12\x19\n" + + "\bsub_path\x18\x03 \x01(\tR\asubPath\x12\x1b\n" + + "\tread_only\x18\x04 \x01(\bR\breadOnly\"<\n" + + "\x10ResourceRequests\x12\x10\n" + + "\x03cpu\x18\x01 \x01(\tR\x03cpu\x12\x16\n" + + "\x06memory\x18\x02 \x01(\tR\x06memory\":\n" + + "\x0eResourceLimits\x12\x10\n" + + "\x03cpu\x18\x01 \x01(\tR\x03cpu\x12\x16\n" + + "\x06memory\x18\x02 \x01(\tR\x06memory\"V\n" + + "\aGPUSpec\x12+\n" + + "\x06driver\x18\x01 \x01(\x0e2\x13.v1alpha1.GPUDriverR\x06driver\x12\x1e\n" + + "\vmin_vram_mb\x18\x02 \x01(\x05R\tminVramMb\"\xa3\x01\n" + + "\x12ContainerResources\x126\n" + + "\brequests\x18\x01 \x01(\v2\x1a.v1alpha1.ResourceRequestsR\brequests\x120\n" + + "\x06limits\x18\x02 \x01(\v2\x18.v1alpha1.ResourceLimitsR\x06limits\x12#\n" + + "\x03gpu\x18\x03 \x01(\v2\x11.v1alpha1.GPUSpecR\x03gpu\"\xe9\x01\n" + + "\tContainer\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" + + "\acommand\x18\x02 \x03(\tR\acommand\x12\x12\n" + + "\x04args\x18\x03 \x03(\tR\x04args\x12\"\n" + + "\x03env\x18\x04 \x03(\v2\x10.v1alpha1.EnvVarR\x03env\x12:\n" + + "\rvolume_mounts\x18\x05 \x03(\v2\x15.v1alpha1.VolumeMountR\fvolumeMounts\x12:\n" + + "\tresources\x18\x06 \x01(\v2\x1c.v1alpha1.ContainerResourcesR\tresources\"\"\n" + + " SimpleClusterStorageVolumeSource\"m\n" + + "\x15HostMountVolumeSource\x12\x1b\n" + + "\thost_path\x18\x01 \x01(\tR\bhostPath\x127\n" + + "\vensure_type\x18\x02 \x01(\x0e2\x16.v1alpha1.HostPathTypeR\n" + + "ensureType\"\xd3\x01\n" + + "\x06Volume\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12b\n" + + "\x16simple_cluster_storage\x18\x02 \x01(\v2*.v1alpha1.SimpleClusterStorageVolumeSourceH\x00R\x14simpleClusterStorage\x12@\n" + + "\n" + + "host_mount\x18\x03 \x01(\v2\x1f.v1alpha1.HostMountVolumeSourceH\x00R\thostMountB\x0f\n" + + "\rvolume_source\"\xb2\x04\n" + + "\fWorkloadSpec\x12*\n" + + "\x04type\x18\x01 \x01(\x0e2\x16.v1alpha1.WorkloadTypeR\x04type\x120\n" + + "\x06source\x18\x02 \x01(\v2\x18.v1alpha1.WorkloadSourceR\x06source\x12\x1a\n" + + "\breplicas\x18\x03 \x01(\x05R\breplicas\x12A\n" + + "\x0fupdate_strategy\x18\x04 \x01(\v2\x18.v1alpha1.UpdateStrategyR\x0eupdateStrategy\x12>\n" + + "\x0erestart_policy\x18\x05 \x01(\v2\x17.v1alpha1.RestartPolicyR\rrestartPolicy\x12M\n" + + "\rnode_selector\x18\x06 \x03(\v2(.v1alpha1.WorkloadSpec.NodeSelectorEntryR\fnodeSelector\x126\n" + + "\vtolerations\x18\a \x03(\v2\x14.v1alpha1.TolerationR\vtolerations\x121\n" + + "\tcontainer\x18\b \x01(\v2\x13.v1alpha1.ContainerR\tcontainer\x12*\n" + + "\avolumes\x18\t \x03(\v2\x10.v1alpha1.VolumeR\avolumes\x1a?\n" + + "\x11NodeSelectorEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\x10\n" + + "\x0eWorkloadStatus\"\x9a\x01\n" + + "\bWorkload\x120\n" + + "\bmetadata\x18\x01 \x01(\v2\x14.v1alpha1.ObjectMetaR\bmetadata\x12*\n" + + "\x04spec\x18\x02 \x01(\v2\x16.v1alpha1.WorkloadSpecR\x04spec\x120\n" + + "\x06status\x18\x03 \x01(\v2\x18.v1alpha1.WorkloadStatusR\x06status\"a\n" + + "\bPortSpec\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12%\n" + + "\x0econtainer_port\x18\x02 \x01(\x05R\rcontainerPort\x12\x1a\n" + + "\bprotocol\x18\x03 \x01(\tR\bprotocol\"+\n" + + "\x0fExecHealthCheck\x12\x18\n" + + "\acommand\x18\x01 \x03(\tR\acommand\"\x9a\x02\n" + + "\vHealthCheck\x12-\n" + + "\x04exec\x18\x01 \x01(\v2\x19.v1alpha1.ExecHealthCheckR\x04exec\x122\n" + + "\x15initial_delay_seconds\x18\x02 \x01(\x05R\x13initialDelaySeconds\x12%\n" + + "\x0eperiod_seconds\x18\x03 \x01(\x05R\rperiodSeconds\x12'\n" + + "\x0ftimeout_seconds\x18\x04 \x01(\x05R\x0etimeoutSeconds\x12+\n" + + "\x11success_threshold\x18\x05 \x01(\x05R\x10successThreshold\x12+\n" + + "\x11failure_threshold\x18\x06 \x01(\x05R\x10failureThreshold\"\x96\x01\n" + + "\vIngressRule\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\x12\x12\n" + + "\x04path\x18\x02 \x01(\tR\x04path\x12*\n" + + "\x11service_port_name\x18\x03 \x01(\tR\x0fservicePortName\x12!\n" + + "\fservice_port\x18\x04 \x01(\x05R\vservicePort\x12\x10\n" + + "\x03tls\x18\x05 \x01(\bR\x03tls\"\xae\x01\n" + + "\x17VirtualLoadBalancerSpec\x12(\n" + + "\x05ports\x18\x01 \x03(\v2\x12.v1alpha1.PortSpecR\x05ports\x128\n" + + "\fhealth_check\x18\x02 \x01(\v2\x15.v1alpha1.HealthCheckR\vhealthCheck\x12/\n" + + "\aingress\x18\x03 \x03(\v2\x15.v1alpha1.IngressRuleR\aingress\"~\n" + + "\x13VirtualLoadBalancer\x120\n" + + "\bmetadata\x18\x01 \x01(\v2\x14.v1alpha1.ObjectMetaR\bmetadata\x125\n" + + "\x04spec\x18\x02 \x01(\v2!.v1alpha1.VirtualLoadBalancerSpecR\x04spec\"\xd0\x01\n" + + "\x11JobDefinitionSpec\x12\x1a\n" + + "\bschedule\x18\x01 \x01(\tR\bschedule\x12 \n" + + "\vcompletions\x18\x02 \x01(\x05R\vcompletions\x12 \n" + + "\vparallelism\x18\x03 \x01(\x05R\vparallelism\x126\n" + + "\x17active_deadline_seconds\x18\x04 \x01(\x05R\x15activeDeadlineSeconds\x12#\n" + + "\rbackoff_limit\x18\x05 \x01(\x05R\fbackoffLimit\"r\n" + + "\rJobDefinition\x120\n" + + "\bmetadata\x18\x01 \x01(\v2\x14.v1alpha1.ObjectMetaR\bmetadata\x12/\n" + + "\x04spec\x18\x02 \x01(\v2\x1b.v1alpha1.JobDefinitionSpecR\x04spec\"1\n" + + "\n" + + "BuildCache\x12#\n" + + "\rregistry_path\x18\x01 \x01(\tR\fregistryPath\"\xd9\x02\n" + + "\x13BuildDefinitionSpec\x12#\n" + + "\rbuild_context\x18\x01 \x01(\tR\fbuildContext\x12'\n" + + "\x0fdockerfile_path\x18\x02 \x01(\tR\x0edockerfilePath\x12K\n" + + "\n" + + "build_args\x18\x03 \x03(\v2,.v1alpha1.BuildDefinitionSpec.BuildArgsEntryR\tbuildArgs\x12!\n" + + "\ftarget_stage\x18\x04 \x01(\tR\vtargetStage\x12\x1a\n" + + "\bplatform\x18\x05 \x01(\tR\bplatform\x12*\n" + + "\x05cache\x18\x06 \x01(\v2\x14.v1alpha1.BuildCacheR\x05cache\x1a<\n" + + "\x0eBuildArgsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"v\n" + + "\x0fBuildDefinition\x120\n" + + "\bmetadata\x18\x01 \x01(\v2\x14.v1alpha1.ObjectMetaR\bmetadata\x121\n" + + "\x04spec\x18\x02 \x01(\v2\x1d.v1alpha1.BuildDefinitionSpecR\x04spec\"\x0f\n" + + "\rNamespaceSpec\"\x11\n" + + "\x0fNamespaceStatus\"\x9d\x01\n" + + "\tNamespace\x120\n" + + "\bmetadata\x18\x01 \x01(\v2\x14.v1alpha1.ObjectMetaR\bmetadata\x12+\n" + + "\x04spec\x18\x02 \x01(\v2\x17.v1alpha1.NamespaceSpecR\x04spec\x121\n" + + "\x06status\x18\x03 \x01(\v2\x19.v1alpha1.NamespaceStatusR\x06status\"\xd6\x01\n" + + "\rNodeResources\x12\x10\n" + + "\x03cpu\x18\x01 \x01(\tR\x03cpu\x12\x16\n" + + "\x06memory\x18\x02 \x01(\tR\x06memory\x12W\n" + + "\x10custom_resources\x18\x03 \x03(\v2,.v1alpha1.NodeResources.CustomResourcesEntryR\x0fcustomResources\x1aB\n" + + "\x14CustomResourcesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xed\x01\n" + + "\x11NodeStatusDetails\x123\n" + + "\bcapacity\x18\x01 \x01(\v2\x17.v1alpha1.NodeResourcesR\bcapacity\x129\n" + + "\vallocatable\x18\x02 \x01(\v2\x17.v1alpha1.NodeResourcesR\vallocatable\x12\x1c\n" + + "\tcondition\x18\x05 \x01(\tR\tcondition\x12J\n" + + "\x13last_heartbeat_time\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\x11lastHeartbeatTime\"\xaa\x01\n" + + "\x05Taint\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value\x12.\n" + + "\x06effect\x18\x03 \x01(\x0e2\x16.v1alpha1.Taint.EffectR\x06effect\"I\n" + + "\x06Effect\x12\x16\n" + + "\x12EFFECT_UNSPECIFIED\x10\x00\x12\x0f\n" + + "\vNO_SCHEDULE\x10\x01\x12\x16\n" + + "\x12PREFER_NO_SCHEDULE\x10\x02\"Z\n" + + "\bNodeSpec\x12'\n" + + "\x06taints\x18\x01 \x03(\v2\x0f.v1alpha1.TaintR\x06taints\x12%\n" + + "\x0eoverlay_subnet\x18\x02 \x01(\tR\roverlaySubnet\"\x95\x01\n" + + "\x04Node\x120\n" + + "\bmetadata\x18\x01 \x01(\v2\x14.v1alpha1.ObjectMetaR\bmetadata\x12&\n" + + "\x04spec\x18\x02 \x01(\v2\x12.v1alpha1.NodeSpecR\x04spec\x123\n" + + "\x06status\x18\x03 \x01(\v2\x1b.v1alpha1.NodeStatusDetailsR\x06status\"\xa7\x04\n" + + "\x18ClusterConfigurationSpec\x12!\n" + + "\fcluster_cidr\x18\x01 \x01(\tR\vclusterCidr\x12!\n" + + "\fservice_cidr\x18\x02 \x01(\tR\vserviceCidr\x12(\n" + + "\x10node_subnet_bits\x18\x03 \x01(\x05R\x0enodeSubnetBits\x12%\n" + + "\x0ecluster_domain\x18\x04 \x01(\tR\rclusterDomain\x12\x1d\n" + + "\n" + + "agent_port\x18\x05 \x01(\x05R\tagentPort\x12\x19\n" + + "\bapi_port\x18\x06 \x01(\x05R\aapiPort\x12$\n" + + "\x0eetcd_peer_port\x18\a \x01(\x05R\fetcdPeerPort\x12(\n" + + "\x10etcd_client_port\x18\b \x01(\x05R\x0eetcdClientPort\x12(\n" + + "\x10volume_base_path\x18\t \x01(\tR\x0evolumeBasePath\x12\x1f\n" + + "\vbackup_path\x18\n" + + " \x01(\tR\n" + + "backupPath\x126\n" + + "\x17backup_interval_minutes\x18\v \x01(\x05R\x15backupIntervalMinutes\x12,\n" + + "\x12agent_tick_seconds\x18\f \x01(\x05R\x10agentTickSeconds\x129\n" + + "\x19node_loss_timeout_seconds\x18\r \x01(\x05R\x16nodeLossTimeoutSeconds\"\x80\x01\n" + + "\x14ClusterConfiguration\x120\n" + + "\bmetadata\x18\x01 \x01(\v2\x14.v1alpha1.ObjectMetaR\bmetadata\x126\n" + + "\x04spec\x18\x02 \x01(\v2\".v1alpha1.ClusterConfigurationSpecR\x04spec*W\n" + + "\fWorkloadType\x12\x1d\n" + + "\x19WORKLOAD_TYPE_UNSPECIFIED\x10\x00\x12\v\n" + + "\aSERVICE\x10\x01\x12\a\n" + + "\x03JOB\x10\x02\x12\x12\n" + + "\x0eDAEMON_SERVICE\x10\x03*Y\n" + + "\x12UpdateStrategyType\x12$\n" + + " UPDATE_STRATEGY_TYPE_UNSPECIFIED\x10\x00\x12\v\n" + + "\aROLLING\x10\x01\x12\x10\n" + + "\fSIMULTANEOUS\x10\x02*[\n" + + "\x10RestartCondition\x12!\n" + + "\x1dRESTART_CONDITION_UNSPECIFIED\x10\x00\x12\t\n" + + "\x05NEVER\x10\x01\x12\r\n" + + "\tMAX_COUNT\x10\x02\x12\n" + + "\n" + + "\x06ALWAYS\x10\x03*E\n" + + "\tGPUDriver\x12\x1a\n" + + "\x16GPU_DRIVER_UNSPECIFIED\x10\x00\x12\a\n" + + "\x03ANY\x10\x01\x12\n" + + "\n" + + "\x06NVIDIA\x10\x02\x12\a\n" + + "\x03AMD\x10\x03*\x80\x01\n" + + "\fHostPathType\x12\x1e\n" + + "\x1aHOST_PATH_TYPE_UNSPECIFIED\x10\x00\x12\x17\n" + + "\x13DIRECTORY_OR_CREATE\x10\x01\x12\r\n" + + "\tDIRECTORY\x10\x02\x12\x12\n" + + "\x0eFILE_OR_CREATE\x10\x03\x12\b\n" + + "\x04FILE\x10\x04\x12\n" + + "\n" + + "\x06SOCKET\x10\x05B\x17Z\x15git.dws.rip/dubey/katb\x06proto3" + +var ( + file_kat_proto_rawDescOnce sync.Once + file_kat_proto_rawDescData []byte +) + +func file_kat_proto_rawDescGZIP() []byte { + file_kat_proto_rawDescOnce.Do(func() { + file_kat_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_kat_proto_rawDesc), len(file_kat_proto_rawDesc))) + }) + return file_kat_proto_rawDescData +} + +var file_kat_proto_enumTypes = make([]protoimpl.EnumInfo, 8) +var file_kat_proto_msgTypes = make([]protoimpl.MessageInfo, 46) +var file_kat_proto_goTypes = []any{ + (WorkloadType)(0), // 0: v1alpha1.WorkloadType + (UpdateStrategyType)(0), // 1: v1alpha1.UpdateStrategyType + (RestartCondition)(0), // 2: v1alpha1.RestartCondition + (GPUDriver)(0), // 3: v1alpha1.GPUDriver + (HostPathType)(0), // 4: v1alpha1.HostPathType + (Toleration_Operator)(0), // 5: v1alpha1.Toleration.Operator + (Toleration_Effect)(0), // 6: v1alpha1.Toleration.Effect + (Taint_Effect)(0), // 7: v1alpha1.Taint.Effect + (*ObjectMeta)(nil), // 8: v1alpha1.ObjectMeta + (*GitSource)(nil), // 9: v1alpha1.GitSource + (*WorkloadSource)(nil), // 10: v1alpha1.WorkloadSource + (*RollingUpdateStrategy)(nil), // 11: v1alpha1.RollingUpdateStrategy + (*UpdateStrategy)(nil), // 12: v1alpha1.UpdateStrategy + (*RestartPolicy)(nil), // 13: v1alpha1.RestartPolicy + (*Toleration)(nil), // 14: v1alpha1.Toleration + (*EnvVar)(nil), // 15: v1alpha1.EnvVar + (*VolumeMount)(nil), // 16: v1alpha1.VolumeMount + (*ResourceRequests)(nil), // 17: v1alpha1.ResourceRequests + (*ResourceLimits)(nil), // 18: v1alpha1.ResourceLimits + (*GPUSpec)(nil), // 19: v1alpha1.GPUSpec + (*ContainerResources)(nil), // 20: v1alpha1.ContainerResources + (*Container)(nil), // 21: v1alpha1.Container + (*SimpleClusterStorageVolumeSource)(nil), // 22: v1alpha1.SimpleClusterStorageVolumeSource + (*HostMountVolumeSource)(nil), // 23: v1alpha1.HostMountVolumeSource + (*Volume)(nil), // 24: v1alpha1.Volume + (*WorkloadSpec)(nil), // 25: v1alpha1.WorkloadSpec + (*WorkloadStatus)(nil), // 26: v1alpha1.WorkloadStatus + (*Workload)(nil), // 27: v1alpha1.Workload + (*PortSpec)(nil), // 28: v1alpha1.PortSpec + (*ExecHealthCheck)(nil), // 29: v1alpha1.ExecHealthCheck + (*HealthCheck)(nil), // 30: v1alpha1.HealthCheck + (*IngressRule)(nil), // 31: v1alpha1.IngressRule + (*VirtualLoadBalancerSpec)(nil), // 32: v1alpha1.VirtualLoadBalancerSpec + (*VirtualLoadBalancer)(nil), // 33: v1alpha1.VirtualLoadBalancer + (*JobDefinitionSpec)(nil), // 34: v1alpha1.JobDefinitionSpec + (*JobDefinition)(nil), // 35: v1alpha1.JobDefinition + (*BuildCache)(nil), // 36: v1alpha1.BuildCache + (*BuildDefinitionSpec)(nil), // 37: v1alpha1.BuildDefinitionSpec + (*BuildDefinition)(nil), // 38: v1alpha1.BuildDefinition + (*NamespaceSpec)(nil), // 39: v1alpha1.NamespaceSpec + (*NamespaceStatus)(nil), // 40: v1alpha1.NamespaceStatus + (*Namespace)(nil), // 41: v1alpha1.Namespace + (*NodeResources)(nil), // 42: v1alpha1.NodeResources + (*NodeStatusDetails)(nil), // 43: v1alpha1.NodeStatusDetails + (*Taint)(nil), // 44: v1alpha1.Taint + (*NodeSpec)(nil), // 45: v1alpha1.NodeSpec + (*Node)(nil), // 46: v1alpha1.Node + (*ClusterConfigurationSpec)(nil), // 47: v1alpha1.ClusterConfigurationSpec + (*ClusterConfiguration)(nil), // 48: v1alpha1.ClusterConfiguration + nil, // 49: v1alpha1.ObjectMeta.LabelsEntry + nil, // 50: v1alpha1.ObjectMeta.AnnotationsEntry + nil, // 51: v1alpha1.WorkloadSpec.NodeSelectorEntry + nil, // 52: v1alpha1.BuildDefinitionSpec.BuildArgsEntry + nil, // 53: v1alpha1.NodeResources.CustomResourcesEntry + (*timestamppb.Timestamp)(nil), // 54: google.protobuf.Timestamp +} +var file_kat_proto_depIdxs = []int32{ + 54, // 0: v1alpha1.ObjectMeta.creation_timestamp:type_name -> google.protobuf.Timestamp + 49, // 1: v1alpha1.ObjectMeta.labels:type_name -> v1alpha1.ObjectMeta.LabelsEntry + 50, // 2: v1alpha1.ObjectMeta.annotations:type_name -> v1alpha1.ObjectMeta.AnnotationsEntry + 9, // 3: v1alpha1.WorkloadSource.git:type_name -> v1alpha1.GitSource + 1, // 4: v1alpha1.UpdateStrategy.type:type_name -> v1alpha1.UpdateStrategyType + 11, // 5: v1alpha1.UpdateStrategy.rolling:type_name -> v1alpha1.RollingUpdateStrategy + 2, // 6: v1alpha1.RestartPolicy.condition:type_name -> v1alpha1.RestartCondition + 5, // 7: v1alpha1.Toleration.operator:type_name -> v1alpha1.Toleration.Operator + 6, // 8: v1alpha1.Toleration.effect:type_name -> v1alpha1.Toleration.Effect + 3, // 9: v1alpha1.GPUSpec.driver:type_name -> v1alpha1.GPUDriver + 17, // 10: v1alpha1.ContainerResources.requests:type_name -> v1alpha1.ResourceRequests + 18, // 11: v1alpha1.ContainerResources.limits:type_name -> v1alpha1.ResourceLimits + 19, // 12: v1alpha1.ContainerResources.gpu:type_name -> v1alpha1.GPUSpec + 15, // 13: v1alpha1.Container.env:type_name -> v1alpha1.EnvVar + 16, // 14: v1alpha1.Container.volume_mounts:type_name -> v1alpha1.VolumeMount + 20, // 15: v1alpha1.Container.resources:type_name -> v1alpha1.ContainerResources + 4, // 16: v1alpha1.HostMountVolumeSource.ensure_type:type_name -> v1alpha1.HostPathType + 22, // 17: v1alpha1.Volume.simple_cluster_storage:type_name -> v1alpha1.SimpleClusterStorageVolumeSource + 23, // 18: v1alpha1.Volume.host_mount:type_name -> v1alpha1.HostMountVolumeSource + 0, // 19: v1alpha1.WorkloadSpec.type:type_name -> v1alpha1.WorkloadType + 10, // 20: v1alpha1.WorkloadSpec.source:type_name -> v1alpha1.WorkloadSource + 12, // 21: v1alpha1.WorkloadSpec.update_strategy:type_name -> v1alpha1.UpdateStrategy + 13, // 22: v1alpha1.WorkloadSpec.restart_policy:type_name -> v1alpha1.RestartPolicy + 51, // 23: v1alpha1.WorkloadSpec.node_selector:type_name -> v1alpha1.WorkloadSpec.NodeSelectorEntry + 14, // 24: v1alpha1.WorkloadSpec.tolerations:type_name -> v1alpha1.Toleration + 21, // 25: v1alpha1.WorkloadSpec.container:type_name -> v1alpha1.Container + 24, // 26: v1alpha1.WorkloadSpec.volumes:type_name -> v1alpha1.Volume + 8, // 27: v1alpha1.Workload.metadata:type_name -> v1alpha1.ObjectMeta + 25, // 28: v1alpha1.Workload.spec:type_name -> v1alpha1.WorkloadSpec + 26, // 29: v1alpha1.Workload.status:type_name -> v1alpha1.WorkloadStatus + 29, // 30: v1alpha1.HealthCheck.exec:type_name -> v1alpha1.ExecHealthCheck + 28, // 31: v1alpha1.VirtualLoadBalancerSpec.ports:type_name -> v1alpha1.PortSpec + 30, // 32: v1alpha1.VirtualLoadBalancerSpec.health_check:type_name -> v1alpha1.HealthCheck + 31, // 33: v1alpha1.VirtualLoadBalancerSpec.ingress:type_name -> v1alpha1.IngressRule + 8, // 34: v1alpha1.VirtualLoadBalancer.metadata:type_name -> v1alpha1.ObjectMeta + 32, // 35: v1alpha1.VirtualLoadBalancer.spec:type_name -> v1alpha1.VirtualLoadBalancerSpec + 8, // 36: v1alpha1.JobDefinition.metadata:type_name -> v1alpha1.ObjectMeta + 34, // 37: v1alpha1.JobDefinition.spec:type_name -> v1alpha1.JobDefinitionSpec + 52, // 38: v1alpha1.BuildDefinitionSpec.build_args:type_name -> v1alpha1.BuildDefinitionSpec.BuildArgsEntry + 36, // 39: v1alpha1.BuildDefinitionSpec.cache:type_name -> v1alpha1.BuildCache + 8, // 40: v1alpha1.BuildDefinition.metadata:type_name -> v1alpha1.ObjectMeta + 37, // 41: v1alpha1.BuildDefinition.spec:type_name -> v1alpha1.BuildDefinitionSpec + 8, // 42: v1alpha1.Namespace.metadata:type_name -> v1alpha1.ObjectMeta + 39, // 43: v1alpha1.Namespace.spec:type_name -> v1alpha1.NamespaceSpec + 40, // 44: v1alpha1.Namespace.status:type_name -> v1alpha1.NamespaceStatus + 53, // 45: v1alpha1.NodeResources.custom_resources:type_name -> v1alpha1.NodeResources.CustomResourcesEntry + 42, // 46: v1alpha1.NodeStatusDetails.capacity:type_name -> v1alpha1.NodeResources + 42, // 47: v1alpha1.NodeStatusDetails.allocatable:type_name -> v1alpha1.NodeResources + 54, // 48: v1alpha1.NodeStatusDetails.last_heartbeat_time:type_name -> google.protobuf.Timestamp + 7, // 49: v1alpha1.Taint.effect:type_name -> v1alpha1.Taint.Effect + 44, // 50: v1alpha1.NodeSpec.taints:type_name -> v1alpha1.Taint + 8, // 51: v1alpha1.Node.metadata:type_name -> v1alpha1.ObjectMeta + 45, // 52: v1alpha1.Node.spec:type_name -> v1alpha1.NodeSpec + 43, // 53: v1alpha1.Node.status:type_name -> v1alpha1.NodeStatusDetails + 8, // 54: v1alpha1.ClusterConfiguration.metadata:type_name -> v1alpha1.ObjectMeta + 47, // 55: v1alpha1.ClusterConfiguration.spec:type_name -> v1alpha1.ClusterConfigurationSpec + 56, // [56:56] is the sub-list for method output_type + 56, // [56:56] is the sub-list for method input_type + 56, // [56:56] is the sub-list for extension type_name + 56, // [56:56] is the sub-list for extension extendee + 0, // [0:56] is the sub-list for field type_name +} + +func init() { file_kat_proto_init() } +func file_kat_proto_init() { + if File_kat_proto != nil { + return + } + file_kat_proto_msgTypes[2].OneofWrappers = []any{ + (*WorkloadSource_Image)(nil), + (*WorkloadSource_Git)(nil), + } + file_kat_proto_msgTypes[16].OneofWrappers = []any{ + (*Volume_SimpleClusterStorage)(nil), + (*Volume_HostMount)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_kat_proto_rawDesc), len(file_kat_proto_rawDesc)), + NumEnums: 8, + NumMessages: 46, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_kat_proto_goTypes, + DependencyIndexes: file_kat_proto_depIdxs, + EnumInfos: file_kat_proto_enumTypes, + MessageInfos: file_kat_proto_msgTypes, + }.Build() + File_kat_proto = out.File + file_kat_proto_goTypes = nil + file_kat_proto_depIdxs = nil +} diff --git a/api/v1alpha1/kat.proto b/api/v1alpha1/kat.proto new file mode 100644 index 0000000..695885d --- /dev/null +++ b/api/v1alpha1/kat.proto @@ -0,0 +1,345 @@ +// File: api/v1alpha1/kat.proto +syntax = "proto3"; + +package v1alpha1; + +option go_package = "git.dws.rip/dubey/kat"; // Adjust to your actual go module path + +import "google/protobuf/timestamp.proto"; + +// Common Metadata (RFC 3.2, Phase 0 Docs) +message ObjectMeta { + string name = 1; + string namespace = 2; + string uid = 3; + int64 generation = 4; + string resource_version = 5; // e.g., etcd ModRevision + google.protobuf.Timestamp creation_timestamp = 6; + map labels = 7; + map annotations = 8; +} + +// Workload (RFC 3.2) +enum WorkloadType { + WORKLOAD_TYPE_UNSPECIFIED = 0; + SERVICE = 1; + JOB = 2; + DAEMON_SERVICE = 3; +} + +message GitSource { + string repository = 1; + string branch = 2; + string tag = 3; + string commit = 4; +} + +message WorkloadSource { + oneof source_type { + string image = 1; // Direct image reference + GitSource git = 2; // Build from Git + } + string cache_image = 3; // Optional: Registry path for build cache layers (used with git source) +} + +enum UpdateStrategyType { + UPDATE_STRATEGY_TYPE_UNSPECIFIED = 0; + ROLLING = 1; + SIMULTANEOUS = 2; +} + +message RollingUpdateStrategy { + string max_surge = 1; // Can be int or percentage string e.g., "1" or "10%" +} + +message UpdateStrategy { + UpdateStrategyType type = 1; + RollingUpdateStrategy rolling = 2; // Relevant if type is ROLLING +} + +enum RestartCondition { + RESTART_CONDITION_UNSPECIFIED = 0; + NEVER = 1; + MAX_COUNT = 2; + ALWAYS = 3; +} + +message RestartPolicy { + RestartCondition condition = 1; + int32 max_restarts = 2; // Used if condition=MAX_COUNT + int32 reset_seconds = 3; // Used if condition=MAX_COUNT +} + +message Toleration { + string key = 1; + enum Operator { + OPERATOR_UNSPECIFIED = 0; + EXISTS = 1; + EQUAL = 2; + } + Operator operator = 2; + string value = 3; // Needed if operator=EQUAL + enum Effect { + EFFECT_UNSPECIFIED = 0; + NO_SCHEDULE = 1; + PREFER_NO_SCHEDULE = 2; + // NO_EXECUTE (not in RFC v1 scope for tolerations, but common) + } + Effect effect = 4; +} + +message EnvVar { + string name = 1; + string value = 2; +} + +message VolumeMount { + string name = 1; // Volume name from spec.volumes + string mount_path = 2; // Path inside container + string sub_path = 3; // Optional: Mount sub-directory + bool read_only = 4; // Optional: Default false +} + +message ResourceRequests { + string cpu = 1; // e.g., "100m" + string memory = 2; // e.g., "64Mi" +} + +message ResourceLimits { + string cpu = 1; // e.g., "1" + string memory = 2; // e.g., "256Mi" +} + +enum GPUDriver { + GPU_DRIVER_UNSPECIFIED = 0; + ANY = 1; + NVIDIA = 2; + AMD = 3; +} + +message GPUSpec { + GPUDriver driver = 1; + int32 min_vram_mb = 2; // Minimum GPU memory required +} + +message ContainerResources { + ResourceRequests requests = 1; + ResourceLimits limits = 2; + GPUSpec gpu = 3; +} + +message Container { + string name = 1; // Optional: Informational name + repeated string command = 2; + repeated string args = 3; + repeated EnvVar env = 4; + repeated VolumeMount volume_mounts = 5; + ContainerResources resources = 6; +} + +message SimpleClusterStorageVolumeSource { + // Empty, implies agent creates dir under volumeBasePath +} + +enum HostPathType { + HOST_PATH_TYPE_UNSPECIFIED = 0; // No check, mount whatever is there or fail + DIRECTORY_OR_CREATE = 1; + DIRECTORY = 2; + FILE_OR_CREATE = 3; + FILE = 4; + SOCKET = 5; +} + +message HostMountVolumeSource { + string host_path = 1; // Absolute path on host + HostPathType ensure_type = 2; // Optional: Type to ensure/check +} + +message Volume { + string name = 1; // Name referenced by volumeMounts + oneof volume_source { + SimpleClusterStorageVolumeSource simple_cluster_storage = 2; + HostMountVolumeSource host_mount = 3; + } +} + +message WorkloadSpec { + WorkloadType type = 1; + WorkloadSource source = 2; + int32 replicas = 3; // Required for SERVICE + UpdateStrategy update_strategy = 4; + RestartPolicy restart_policy = 5; + map node_selector = 6; + repeated Toleration tolerations = 7; + Container container = 8; + repeated Volume volumes = 9; +} + +message WorkloadStatus { + // Placeholder for Phase 0. Will be expanded later. + // Example fields: + // int32 observed_generation = 1; + // int32 ready_replicas = 2; + // string condition = 3; // e.g., "Available", "Progressing", "Failed" +} + +message Workload { + ObjectMeta metadata = 1; + WorkloadSpec spec = 2; + WorkloadStatus status = 3; +} + +// VirtualLoadBalancer (RFC 3.3) +message PortSpec { + string name = 1; // Optional: e.g., "web", "grpc" + int32 container_port = 2; // Port app listens on in container + string protocol = 3; // Optional: TCP | UDP. Default TCP. +} + +message ExecHealthCheck { + repeated string command = 1; // Exit 0 = healthy +} + +message HealthCheck { + ExecHealthCheck exec = 1; + int32 initial_delay_seconds = 2; + int32 period_seconds = 3; + int32 timeout_seconds = 4; + int32 success_threshold = 5; + int32 failure_threshold = 6; +} + +message IngressRule { + string host = 1; + string path = 2; + string service_port_name = 3; // Name of port from PortSpec + int32 service_port = 4; // Port number from PortSpec (overrides name) + bool tls = 5; // Signal for ACME +} + +message VirtualLoadBalancerSpec { + repeated PortSpec ports = 1; + HealthCheck health_check = 2; + repeated IngressRule ingress = 3; +} + +message VirtualLoadBalancer { + ObjectMeta metadata = 1; // Name likely matches Workload name + VirtualLoadBalancerSpec spec = 2; + // VirtualLoadBalancerStatus status = 3; // Placeholder +} + +// JobDefinition (RFC 3.4) +message JobDefinitionSpec { + string schedule = 1; // Optional: Cron schedule + int32 completions = 2; // Optional: Default 1 + int32 parallelism = 3; // Optional: Default 1 + int32 active_deadline_seconds = 4; // Optional + int32 backoff_limit = 5; // Optional: Default 3 +} + +message JobDefinition { + ObjectMeta metadata = 1; // Name likely matches Workload name + JobDefinitionSpec spec = 2; + // JobDefinitionStatus status = 3; // Placeholder +} + +// BuildDefinition (RFC 3.5) +message BuildCache { + string registry_path = 1; // e.g., "myreg.com/cache/myapp" +} + +message BuildDefinitionSpec { + string build_context = 1; // Optional: Path relative to repo root. Defaults to "." + string dockerfile_path = 2; // Optional: Path relative to buildContext. Defaults to "./Dockerfile" + map build_args = 3; // Optional + string target_stage = 4; // Optional + string platform = 5; // Optional: e.g., "linux/arm64" + BuildCache cache = 6; // Optional +} + +message BuildDefinition { + ObjectMeta metadata = 1; // Name likely matches Workload name + BuildDefinitionSpec spec = 2; + // BuildDefinitionStatus status = 3; // Placeholder +} + +// Namespace (RFC 3.7) +message NamespaceSpec { + // Potentially finalizers or other future spec fields +} + +message NamespaceStatus { + // string phase = 1; // e.g., "Active", "Terminating" +} + +message Namespace { + ObjectMeta metadata = 1; + NamespaceSpec spec = 2; + NamespaceStatus status = 3; +} + +// Node (Internal Representation - RFC 3.8) +message NodeResources { + string cpu = 1; // e.g., "2000m" + string memory = 2; // e.g., "4096Mi" + map custom_resources = 3; // e.g., for GPUs "nvidia.com/gpu: 2" +} + +message NodeStatusDetails { + NodeResources capacity = 1; + NodeResources allocatable = 2; + // repeated WorkloadInstanceStatus workload_instances = 3; // Define later + // OverlayNetworkStatus overlay_network = 4; // Define later + string condition = 5; // e.g., "Ready", "NotReady", "Draining" + google.protobuf.Timestamp last_heartbeat_time = 6; +} + +message Taint { // From RFC 1.5, used in NodeSpec + string key = 1; + string value = 2; + enum Effect { + EFFECT_UNSPECIFIED = 0; + NO_SCHEDULE = 1; + PREFER_NO_SCHEDULE = 2; + // NO_EXECUTE (not in RFC v1 scope for taints, but common) + } + Effect effect = 3; +} + +message NodeSpec { + repeated Taint taints = 1; + string overlay_subnet = 2; // Assigned by leader + // string provider_id = 3; // Cloud provider specific ID + // map labels = 4; // Node labels, distinct from metadata.labels + // map annotations = 5; // Node annotations +} + +message Node { + ObjectMeta metadata = 1; // Name is the unique node name/ID + NodeSpec spec = 2; + NodeStatusDetails status = 3; +} + +// ClusterConfiguration (RFC 3.9) +message ClusterConfigurationSpec { + string cluster_cidr = 1; + string service_cidr = 2; + int32 node_subnet_bits = 3; + string cluster_domain = 4; + int32 agent_port = 5; + int32 api_port = 6; + int32 etcd_peer_port = 7; + int32 etcd_client_port = 8; + string volume_base_path = 9; + string backup_path = 10; + int32 backup_interval_minutes = 11; + int32 agent_tick_seconds = 12; + int32 node_loss_timeout_seconds = 13; +} + +message ClusterConfiguration { + ObjectMeta metadata = 1; // e.g., name of the cluster + ClusterConfigurationSpec spec = 2; + // ClusterConfigurationStatus status = 3; // Placeholder +} \ No newline at end of file diff --git a/examples/cluster.kat b/examples/cluster.kat new file mode 100644 index 0000000..bab91e9 --- /dev/null +++ b/examples/cluster.kat @@ -0,0 +1,18 @@ +apiVersion: kat.dws.rip/v1alpha1 +kind: ClusterConfiguration +metadata: + name: my-kat-cluster +spec: + clusterCIDR: "10.100.0.0/16" + serviceCIDR: "10.200.0.0/16" + nodeSubnetBits: 7 # Results in /23 node subnets (e.g., 10.100.0.0/23, 10.100.2.0/23) + clusterDomain: "kat.example.local" # Overriding default + apiPort: 9115 + agentPort: 9116 + etcdPeerPort: 2380 + etcdClientPort: 2379 + volumeBasePath: "/opt/kat/volumes" # Overriding default + backupPath: "/opt/kat/backups" # Overriding default + backupIntervalMinutes: 60 + agentTickSeconds: 10 + nodeLossTimeoutSeconds: 45 \ No newline at end of file diff --git a/examples/simple-service/virtualLoadBalancer.kat b/examples/simple-service/virtualLoadBalancer.kat new file mode 100644 index 0000000..bb4afc3 --- /dev/null +++ b/examples/simple-service/virtualLoadBalancer.kat @@ -0,0 +1,15 @@ +apiVersion: kat.dws.rip/v1alpha1 +kind: VirtualLoadBalancer +metadata: + name: my-simple-nginx # Should match workload name + namespace: default +spec: + ports: + - name: http + containerPort: 80 + protocol: TCP + healthCheck: + exec: + command: ["curl", "-f", "http://localhost/"] # Nginx doesn't have curl by default, this is illustrative + initialDelaySeconds: 5 + periodSeconds: 10 \ No newline at end of file diff --git a/examples/simple-service/workload.kat b/examples/simple-service/workload.kat new file mode 100644 index 0000000..452ec71 --- /dev/null +++ b/examples/simple-service/workload.kat @@ -0,0 +1,21 @@ +apiVersion: kat.dws.rip/v1alpha1 +kind: Workload +metadata: + name: my-simple-nginx + namespace: default +spec: + type: SERVICE + source: + image: "nginx:latest" + replicas: 2 + restartPolicy: + condition: ALWAYS + container: + name: nginx-container + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "100m" + memory: "128Mi" \ No newline at end of file diff --git a/go.mod b/go.mod index 9cd178a..5c2c365 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,10 @@ module git.dws.rip/dubey/kat -go 1.21 +go 1.22 + +toolchain go1.24.2 require ( - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..c0acecb --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/config/parse.go b/internal/config/parse.go new file mode 100644 index 0000000..b4bbff3 --- /dev/null +++ b/internal/config/parse.go @@ -0,0 +1,323 @@ +// File: internal/config/parse.go +package config + +import ( + "fmt" + "io/ioutil" + "net" + "os" + + pb "git.dws.rip/dubey/kat/api/v1alpha1" // Adjust to your actual go module path + "gopkg.in/yaml.v3" // Add to go.mod: go get gopkg.in/yaml.v3 +) + +var _ = yaml.Unmarshal // Used for Quadlet parsing + +// ParseClusterConfiguration reads, unmarshals, and validates a cluster.kat file. +func ParseClusterConfiguration(filePath string) (*pb.ClusterConfiguration, error) { + if _, err := os.Stat(filePath); os.IsNotExist(err) { + return nil, fmt.Errorf("cluster configuration file not found: %s", filePath) + } + + yamlFile, err := ioutil.ReadFile(filePath) + if err != nil { + return nil, fmt.Errorf("failed to read cluster configuration file %s: %w", filePath, err) + } + + var config pb.ClusterConfiguration + // We expect the YAML to have top-level keys like 'apiVersion', 'kind', 'metadata', 'spec' + // but our proto is just the ClusterConfiguration message. + // So, we'll unmarshal into a temporary map to extract the 'spec' and 'metadata'. + var rawConfigMap map[string]interface{} + if err = yaml.Unmarshal(yamlFile, &rawConfigMap); err != nil { + return nil, fmt.Errorf("failed to unmarshal YAML from %s: %w", filePath, err) + } + + // Quick check for kind + kind, ok := rawConfigMap["kind"].(string) + if !ok || kind != "ClusterConfiguration" { + return nil, fmt.Errorf("invalid kind in %s: expected ClusterConfiguration, got %v", filePath, rawConfigMap["kind"]) + } + + metadataMap, ok := rawConfigMap["metadata"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("metadata section not found or invalid in %s", filePath) + } + metadataBytes, err := yaml.Marshal(metadataMap) + if err != nil { + return nil, fmt.Errorf("failed to re-marshal metadata: %w", err) + } + if err = yaml.Unmarshal(metadataBytes, &config.Metadata); err != nil { + return nil, fmt.Errorf("failed to unmarshal metadata into proto: %w", err) + } + + specMap, ok := rawConfigMap["spec"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("spec section not found or invalid in %s", filePath) + } + specBytes, err := yaml.Marshal(specMap) + if err != nil { + return nil, fmt.Errorf("failed to re-marshal spec: %w", err) + } + if err = yaml.Unmarshal(specBytes, &config.Spec); err != nil { + return nil, fmt.Errorf("failed to unmarshal spec into proto: %w", err) + } + + SetClusterConfigDefaults(&config) + + if err := ValidateClusterConfiguration(&config); err != nil { + return nil, fmt.Errorf("invalid cluster configuration in %s: %w", filePath, err) + } + + return &config, nil +} + +// SetClusterConfigDefaults applies default values to the ClusterConfiguration spec. +func SetClusterConfigDefaults(config *pb.ClusterConfiguration) { + if config.Spec == nil { + config.Spec = &pb.ClusterConfigurationSpec{} + } + s := config.Spec + + if s.ClusterDomain == "" { + s.ClusterDomain = DefaultClusterDomain + } + if s.AgentPort == 0 { + s.AgentPort = DefaultAgentPort + } + if s.ApiPort == 0 { + s.ApiPort = DefaultApiPort + } + if s.EtcdPeerPort == 0 { + s.EtcdPeerPort = DefaultEtcdPeerPort + } + if s.EtcdClientPort == 0 { + s.EtcdClientPort = DefaultEtcdClientPort + } + if s.VolumeBasePath == "" { + s.VolumeBasePath = DefaultVolumeBasePath + } + if s.BackupPath == "" { + s.BackupPath = DefaultBackupPath + } + if s.BackupIntervalMinutes == 0 { + s.BackupIntervalMinutes = DefaultBackupIntervalMins + } + if s.AgentTickSeconds == 0 { + s.AgentTickSeconds = DefaultAgentTickSeconds + } + if s.NodeLossTimeoutSeconds == 0 { + s.NodeLossTimeoutSeconds = DefaultNodeLossTimeoutSec + if s.AgentTickSeconds > 0 { // If agent tick is set, derive from it + s.NodeLossTimeoutSeconds = s.AgentTickSeconds * 4 // Example: 4 ticks + } + } + if s.NodeSubnetBits == 0 { + s.NodeSubnetBits = DefaultNodeSubnetBits + } +} + +// ValidateClusterConfiguration performs basic validation on the ClusterConfiguration. +func ValidateClusterConfiguration(config *pb.ClusterConfiguration) error { + if config.Metadata == nil || config.Metadata.Name == "" { + return fmt.Errorf("metadata.name is required") + } + if config.Spec == nil { + return fmt.Errorf("spec is required") + } + + s := config.Spec + if s.ClusterCidr == "" { + return fmt.Errorf("spec.clusterCIDR is required") + } + if _, _, err := net.ParseCIDR(s.ClusterCidr); err != nil { + return fmt.Errorf("invalid spec.clusterCIDR %s: %w", s.ClusterCidr, err) + } + + if s.ServiceCidr == "" { + return fmt.Errorf("spec.serviceCIDR is required") + } + if _, _, err := net.ParseCIDR(s.ServiceCidr); err != nil { + return fmt.Errorf("invalid spec.serviceCIDR %s: %w", s.ServiceCidr, err) + } + + // Validate ports + ports := []struct { + name string + port int32 + }{ + {"agentPort", s.AgentPort}, {"apiPort", s.ApiPort}, + {"etcdPeerPort", s.EtcdPeerPort}, {"etcdClientPort", s.EtcdClientPort}, + } + for _, p := range ports { + if p.port <= 0 || p.port > 65535 { + return fmt.Errorf("invalid port for %s: %d. Must be between 1 and 65535", p.name, p.port) + } + } + // Check for port conflicts among configured ports + portSet := make(map[int32]string) + for _, p := range ports { + if existing, found := portSet[p.port]; found { + return fmt.Errorf("port conflict: %s (%d) and %s (%d) use the same port", p.name, p.port, existing, p.port) + } + portSet[p.port] = p.name + } + + if s.NodeSubnetBits <= 0 || s.NodeSubnetBits >= 32 { + return fmt.Errorf("invalid spec.nodeSubnetBits: %d. Must be > 0 and < 32", s.NodeSubnetBits) + } + // Validate nodeSubnetBits against clusterCIDR prefix length + _, clusterNet, _ := net.ParseCIDR(s.ClusterCidr) + clusterPrefixLen, _ := clusterNet.Mask.Size() + if int(s.NodeSubnetBits) <= clusterPrefixLen { + // This logic might be too simple. NodeSubnetBits is the number of *additional* bits for the subnet *within* the cluster prefix. + // So, the resulting node subnet prefix length would be clusterPrefixLen + s.NodeSubnetBits. + // This must be less than 32 (or 31 for usable IPs). + // The RFC states: "Default 7 (yielding /23 subnets if clusterCIDR=/16)" + // So if clusterCIDR is /16, node subnet is / (16+7) = /23. This is valid. + // A node subnet prefix length must be > clusterPrefixLen and < 32. + if (clusterPrefixLen + int(s.NodeSubnetBits)) >= 32 { + return fmt.Errorf("spec.nodeSubnetBits (%d) combined with clusterCIDR prefix (%d) results in an invalid subnet size (>= /32)", s.NodeSubnetBits, clusterPrefixLen) + } + } else { + // This case seems unlikely if nodeSubnetBits is the number of bits for the node part. + // Let's assume nodeSubnetBits is the number of bits *after* the cluster prefix that define the node subnet. + // e.g. cluster 10.0.0.0/8, nodeSubnetBits=8 -> node subnets are /16. + } + + if s.BackupIntervalMinutes < 0 { // 0 could mean disabled, but RFC implies positive + return fmt.Errorf("spec.backupIntervalMinutes must be non-negative") + } + if s.AgentTickSeconds <= 0 { + return fmt.Errorf("spec.agentTickSeconds must be positive") + } + if s.NodeLossTimeoutSeconds <= 0 { + return fmt.Errorf("spec.nodeLossTimeoutSeconds must be positive") + } + if s.NodeLossTimeoutSeconds < s.AgentTickSeconds { + return fmt.Errorf("spec.nodeLossTimeoutSeconds must be greater than or equal to spec.agentTickSeconds") + } + + // volumeBasePath and backupPath should be absolute paths, but validation can be tricky + // For now, just check if they are non-empty if specified, defaults handle empty. + // A more robust check would be filepath.IsAbs() + + return nil +} + +// ParsedQuadletFiles holds the structured data from a Quadlet directory. +type ParsedQuadletFiles struct { + Workload *pb.Workload + VirtualLoadBalancer *pb.VirtualLoadBalancer + JobDefinition *pb.JobDefinition + BuildDefinition *pb.BuildDefinition + // Namespace is typically a cluster-level resource, not part of a workload quadlet bundle. + // If it were, it would be: Namespace *pb.Namespace + + // Store raw file contents for potential future use (e.g. annotations, original source) + RawFiles map[string][]byte +} + +// ParseQuadletFile unmarshals a single Quadlet file content based on its kind. +// It returns the specific protobuf message. +func ParseQuadletFile(fileName string, content []byte) (interface{}, error) { + var base struct { + ApiVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + } + if err := yaml.Unmarshal(content, &base); err != nil { + return nil, fmt.Errorf("failed to unmarshal base YAML from %s to determine kind: %w", fileName, err) + } + + // TODO: Check apiVersion, e.g., base.ApiVersion == "kat.dws.rip/v1alpha1" + + var resource interface{} + var err error + + switch base.Kind { + case "Workload": + var wl pb.Workload + // Similar to ClusterConfiguration, need to unmarshal metadata and spec separately + // from a temporary map if the proto doesn't match the full YAML structure directly. + // For simplicity in Phase 0, assuming direct unmarshal works if YAML matches proto structure. + // If YAML has apiVersion/kind/metadata/spec at top level, then: + var raw map[string]interface{} + if err = yaml.Unmarshal(content, &raw); err == nil { + if meta, ok := raw["metadata"]; ok { + metaBytes, _ := yaml.Marshal(meta) + yaml.Unmarshal(metaBytes, &wl.Metadata) + } + if spec, ok := raw["spec"]; ok { + specBytes, _ := yaml.Marshal(spec) + yaml.Unmarshal(specBytes, &wl.Spec) + } + } + resource = &wl + case "VirtualLoadBalancer": + var vlb pb.VirtualLoadBalancer + var raw map[string]interface{} + if err = yaml.Unmarshal(content, &raw); err == nil { + if meta, ok := raw["metadata"]; ok { + metaBytes, _ := yaml.Marshal(meta) + yaml.Unmarshal(metaBytes, &vlb.Metadata) + } + if spec, ok := raw["spec"]; ok { + specBytes, _ := yaml.Marshal(spec) + yaml.Unmarshal(specBytes, &vlb.Spec) + } + } + resource = &vlb + // Add cases for JobDefinition, BuildDefinition as they are defined + case "JobDefinition": + var jd pb.JobDefinition + // ... unmarshal logic ... + resource = &jd + case "BuildDefinition": + var bd pb.BuildDefinition + // ... unmarshal logic ... + resource = &bd + default: + return nil, fmt.Errorf("unknown Kind '%s' in file %s", base.Kind, fileName) + } + + if err != nil { + return nil, fmt.Errorf("failed to unmarshal YAML for Kind '%s' from %s: %w", base.Kind, fileName, err) + } + // TODO: Add basic validation for each parsed type (e.g., required fields like metadata.name) + return resource, nil +} + +// ParseQuadletDirectory processes a map of file contents (from UntarQuadlets). +func ParseQuadletDirectory(files map[string][]byte) (*ParsedQuadletFiles, error) { + parsed := &ParsedQuadletFiles{RawFiles: files} + + for fileName, content := range files { + obj, err := ParseQuadletFile(fileName, content) + if err != nil { + return nil, fmt.Errorf("error parsing quadlet file %s: %w", fileName, err) + } + switch v := obj.(type) { + case *pb.Workload: + if parsed.Workload != nil { + return nil, fmt.Errorf("multiple Workload definitions found") + } + parsed.Workload = v + case *pb.VirtualLoadBalancer: + if parsed.VirtualLoadBalancer != nil { + return nil, fmt.Errorf("multiple VirtualLoadBalancer definitions found") + } + parsed.VirtualLoadBalancer = v + // Add cases for JobDefinition, BuildDefinition + } + } + + // TODO: Perform cross-Quadlet file validation (e.g., workload.kat must exist) + if parsed.Workload == nil { + return nil, fmt.Errorf("required Workload definition (workload.kat) not found in Quadlet bundle") + } + if parsed.Workload.Metadata == nil || parsed.Workload.Metadata.Name == "" { + return nil, fmt.Errorf("workload.kat must have metadata.name defined") + } + + return parsed, nil +} diff --git a/internal/config/parse_test.go b/internal/config/parse_test.go index a061a7c..bf133fd 100644 --- a/internal/config/parse_test.go +++ b/internal/config/parse_test.go @@ -1,19 +1,16 @@ package config import ( - "io/ioutil" "os" - "path/filepath" "strings" "testing" - "git.dws.rip/dubey/kat/api/v1alpha1" - "google.golang.org/protobuf/types/known/timestamppb" + pb "git.dws.rip/dubey/kat/api/v1alpha1" ) func createTestClusterKatFile(t *testing.T, content string) string { t.Helper() - tmpFile, err := ioutil.TempFile(t.TempDir(), "cluster.*.kat") + tmpFile, err := os.CreateTemp(t.TempDir(), "cluster.*.kat") if err != nil { t.Fatalf("Failed to create temp file: %v", err) } @@ -144,8 +141,8 @@ spec: } func TestSetClusterConfigDefaults(t *testing.T) { - config := &v1alpha1.ClusterConfiguration{ - Spec: &v1alpha1.ClusterConfigurationSpec{}, + config := &pb.ClusterConfiguration{ + Spec: &pb.ClusterConfigurationSpec{}, } SetClusterConfigDefaults(config) @@ -184,8 +181,8 @@ func TestSetClusterConfigDefaults(t *testing.T) { } // Test NodeLossTimeoutSeconds derivation - configWithTick := &v1alpha1.ClusterConfiguration{ - Spec: &v1alpha1.ClusterConfigurationSpec{AgentTickSeconds: 10}, + configWithTick := &pb.ClusterConfiguration{ + Spec: &pb.ClusterConfigurationSpec{AgentTickSeconds: 10}, } SetClusterConfigDefaults(configWithTick) if configWithTick.Spec.NodeLossTimeoutSeconds != 40 { // 10 * 4 @@ -194,48 +191,53 @@ func TestSetClusterConfigDefaults(t *testing.T) { } func TestValidateClusterConfiguration_InvalidValues(t *testing.T) { - baseValidSpec := func() *v1alpha1.ClusterConfigurationSpec { - return &v1alpha1.ClusterConfigurationSpec{ - ClusterCidr: "10.0.0.0/16", - ServiceCidr: "10.1.0.0/16", - NodeSubnetBits: 8, - ClusterDomain: "test.local", - AgentPort: 10250, - ApiPort: 10251, - EtcdPeerPort: 2380, - EtcdClientPort: 2379, - VolumeBasePath: "/var/lib/kat/volumes", - BackupPath: "/var/lib/kat/backups", - BackupIntervalMinutes: 30, - AgentTickSeconds: 15, - NodeLossTimeoutSeconds:60, + baseValidSpec := func() *pb.ClusterConfigurationSpec { + return &pb.ClusterConfigurationSpec{ + ClusterCidr: "10.0.0.0/16", + ServiceCidr: "10.1.0.0/16", + NodeSubnetBits: 8, + ClusterDomain: "test.local", + AgentPort: 10250, + ApiPort: 10251, + EtcdPeerPort: 2380, + EtcdClientPort: 2379, + VolumeBasePath: "/var/lib/kat/volumes", + BackupPath: "/var/lib/kat/backups", + BackupIntervalMinutes: 30, + AgentTickSeconds: 15, + NodeLossTimeoutSeconds: 60, } } - baseValidMetadata := func() *v1alpha1.ObjectMeta { - return &v1alpha1.ObjectMeta{Name: "test"} + baseValidMetadata := func() *pb.ObjectMeta { + return &pb.ObjectMeta{Name: "test"} } tests := []struct { name string - mutator func(cfg *v1alpha1.ClusterConfiguration) + mutator func(cfg *pb.ClusterConfiguration) wantErr string }{ - {"invalid clusterCIDR", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.ClusterCidr = "invalid" }, "invalid spec.clusterCIDR"}, - {"invalid serviceCIDR", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.ServiceCidr = "invalid" }, "invalid spec.serviceCIDR"}, - {"invalid agentPort low", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.AgentPort = 0 }, "invalid port for agentPort"}, - {"invalid agentPort high", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.AgentPort = 70000 }, "invalid port for agentPort"}, - {"port conflict", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.ApiPort = cfg.Spec.AgentPort }, "port conflict"}, - {"invalid nodeSubnetBits low", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.NodeSubnetBits = 0 }, "invalid spec.nodeSubnetBits"}, - {"invalid nodeSubnetBits high", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.NodeSubnetBits = 32 }, "invalid spec.nodeSubnetBits"}, - {"invalid nodeSubnetBits vs clusterCIDR", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.ClusterCidr = "10.0.0.0/28"; cfg.Spec.NodeSubnetBits = 8 }, "results in an invalid subnet size"}, - {"invalid agentTickSeconds", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.AgentTickSeconds = 0 }, "agentTickSeconds must be positive"}, - {"invalid nodeLossTimeoutSeconds", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.NodeLossTimeoutSeconds = 0 }, "nodeLossTimeoutSeconds must be positive"}, - {"nodeLoss < agentTick", func(cfg *v1alpha1.ClusterConfiguration) { cfg.Spec.NodeLossTimeoutSeconds = cfg.Spec.AgentTickSeconds - 1 }, "nodeLossTimeoutSeconds must be greater"}, + {"invalid clusterCIDR", func(cfg *pb.ClusterConfiguration) { cfg.Spec.ClusterCidr = "invalid" }, "invalid spec.clusterCIDR"}, + {"invalid serviceCIDR", func(cfg *pb.ClusterConfiguration) { cfg.Spec.ServiceCidr = "invalid" }, "invalid spec.serviceCIDR"}, + {"invalid agentPort low", func(cfg *pb.ClusterConfiguration) { cfg.Spec.AgentPort = 0 }, "invalid port for agentPort"}, + {"invalid agentPort high", func(cfg *pb.ClusterConfiguration) { cfg.Spec.AgentPort = 70000 }, "invalid port for agentPort"}, + {"port conflict", func(cfg *pb.ClusterConfiguration) { cfg.Spec.ApiPort = cfg.Spec.AgentPort }, "port conflict"}, + {"invalid nodeSubnetBits low", func(cfg *pb.ClusterConfiguration) { cfg.Spec.NodeSubnetBits = 0 }, "invalid spec.nodeSubnetBits"}, + {"invalid nodeSubnetBits high", func(cfg *pb.ClusterConfiguration) { cfg.Spec.NodeSubnetBits = 32 }, "invalid spec.nodeSubnetBits"}, + {"invalid nodeSubnetBits vs clusterCIDR", func(cfg *pb.ClusterConfiguration) { + cfg.Spec.ClusterCidr = "10.0.0.0/28" + cfg.Spec.NodeSubnetBits = 8 + }, "results in an invalid subnet size"}, + {"invalid agentTickSeconds", func(cfg *pb.ClusterConfiguration) { cfg.Spec.AgentTickSeconds = 0 }, "agentTickSeconds must be positive"}, + {"invalid nodeLossTimeoutSeconds", func(cfg *pb.ClusterConfiguration) { cfg.Spec.NodeLossTimeoutSeconds = 0 }, "nodeLossTimeoutSeconds must be positive"}, + {"nodeLoss < agentTick", func(cfg *pb.ClusterConfiguration) { + cfg.Spec.NodeLossTimeoutSeconds = cfg.Spec.AgentTickSeconds - 1 + }, "nodeLossTimeoutSeconds must be greater"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - config := &v1alpha1.ClusterConfiguration{Metadata: baseValidMetadata(), Spec: baseValidSpec()} + config := &pb.ClusterConfiguration{Metadata: baseValidMetadata(), Spec: baseValidSpec()} tt.mutator(config) err := ValidateClusterConfiguration(config) if err == nil { diff --git a/internal/config/types.go b/internal/config/types.go new file mode 100644 index 0000000..d49c9c7 --- /dev/null +++ b/internal/config/types.go @@ -0,0 +1,23 @@ +// File: internal/config/types.go +package config + +// For Phase 0, we will primarily use the generated protobuf types +// (e.g., *v1alpha1.ClusterConfiguration) directly. +// This file can hold auxiliary types or constants related to config parsing if needed later. + +const ( + DefaultClusterDomain = "kat.cluster.local" + DefaultAgentPort = 9116 + DefaultApiPort = 9115 + DefaultEtcdPeerPort = 2380 + DefaultEtcdClientPort = 2379 + DefaultVolumeBasePath = "/var/lib/kat/volumes" + DefaultBackupPath = "/var/lib/kat/backups" + DefaultBackupIntervalMins = 30 + DefaultAgentTickSeconds = 15 + DefaultNodeLossTimeoutSec = 60 // DefaultNodeLossTimeoutSeconds = DefaultAgentTickSeconds * 4 (example logic) + DefaultNodeSubnetBits = 7 // yields /23 from /16, or /31 from /24 etc. (5 bits for /29, 7 for /25) + // RFC says 7 for /23 from /16. This means 2^(32-16-7) = 2^9 = 512 IPs per node subnet. + // If nodeSubnetBits means bits for the node portion *within* the host part of clusterCIDR: + // e.g. /16 -> 16 host bits. If nodeSubnetBits = 7, then node subnet is / (16+7) = /23. +) \ No newline at end of file diff --git a/internal/utils/tar.go b/internal/utils/tar.go new file mode 100644 index 0000000..fd69cff --- /dev/null +++ b/internal/utils/tar.go @@ -0,0 +1,87 @@ +package utils + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "path/filepath" + "strings" +) + +const maxQuadletFileSize = 1 * 1024 * 1024 // 1MB limit per file in tarball +const maxTotalQuadletSize = 5 * 1024 * 1024 // 5MB limit for total uncompressed size +const maxQuadletFiles = 20 // Max number of files in a quadlet bundle + +// UntarQuadlets unpacks a tar.gz stream in memory and returns a map of fileName -> fileContent. +// It performs basic validation on file names and sizes. +func UntarQuadlets(reader io.Reader) (map[string][]byte, error) { + gzr, err := gzip.NewReader(reader) + if err != nil { + return nil, fmt.Errorf("failed to create gzip reader: %w", err) + } + defer gzr.Close() + + tr := tar.NewReader(gzr) + files := make(map[string][]byte) + var totalSize int64 + fileCount := 0 + + for { + header, err := tr.Next() + if err == io.EOF { + break // End of archive + } + if err != nil { + return nil, fmt.Errorf("failed to read tar header: %w", err) + } + + // Basic security checks + if strings.Contains(header.Name, "..") { + return nil, fmt.Errorf("invalid file path in tar: %s (contains '..')", header.Name) + } + // Ensure files are *.kat and are not in subdirectories within the tarball + // The Quadlet concept implies a flat directory of *.kat files. + if filepath.Dir(header.Name) != "." && filepath.Dir(header.Name) != "" { + return nil, fmt.Errorf("invalid file path in tar: %s (subdirectories are not allowed for Quadlet files)", header.Name) + } + if !strings.HasSuffix(strings.ToLower(header.Name), ".kat") { + return nil, fmt.Errorf("invalid file type in tar: %s (only .kat files are allowed)", header.Name) + } + + switch header.Typeflag { + case tar.TypeReg: // Regular file + fileCount++ + if fileCount > maxQuadletFiles { + return nil, fmt.Errorf("too many files in quadlet bundle; limit %d", maxQuadletFiles) + } + + if header.Size > maxQuadletFileSize { + return nil, fmt.Errorf("file %s in tar is too large: %d bytes (max %d)", header.Name, header.Size, maxQuadletFileSize) + } + totalSize += header.Size + if totalSize > maxTotalQuadletSize { + return nil, fmt.Errorf("total size of files in tar is too large (max %d MB)", maxTotalQuadletSize/(1024*1024)) + } + + content, err := io.ReadAll(tr) + if err != nil { + return nil, fmt.Errorf("failed to read file content for %s from tar: %w", header.Name, err) + } + if int64(len(content)) != header.Size { + return nil, fmt.Errorf("file %s in tar has inconsistent size: header %d, read %d", header.Name, header.Size, len(content)) + } + files[header.Name] = content + case tar.TypeDir: // Directory + // Directories are ignored; we expect a flat structure of .kat files. + continue + default: + // Symlinks, char devices, etc. are not allowed. + return nil, fmt.Errorf("unsupported file type in tar for %s: typeflag %c", header.Name, header.Typeflag) + } + } + if len(files) == 0 { + return nil, fmt.Errorf("no .kat files found in the provided archive") + } + return files, nil +} diff --git a/internal/utils/tar_test.go b/internal/utils/tar_test.go index b8cea2f..c83563f 100644 --- a/internal/utils/tar_test.go +++ b/internal/utils/tar_test.go @@ -5,7 +5,6 @@ import ( "bytes" "compress/gzip" "io" - "os" "path/filepath" "strings" "testing" @@ -132,7 +131,7 @@ func TestUntarQuadlets_FileTooLarge(t *testing.T) { func TestUntarQuadlets_TotalSizeTooLarge(t *testing.T) { numFiles := (maxTotalQuadletSize / maxQuadletFileSize) + 2 fileSize := maxQuadletFileSize / 2 - + inputFiles := make(map[string]string) content := strings.Repeat("a", int(fileSize)) for i := 0; i < int(numFiles); i++ { @@ -150,18 +149,18 @@ func TestUntarQuadlets_TotalSizeTooLarge(t *testing.T) { } func TestUntarQuadlets_TooManyFiles(t *testing.T) { - inputFiles := make(map[string]string) - for i := 0; i <= maxQuadletFiles; i++ { - inputFiles[filepath.Join(".", "file"+string(rune(i+'a'))+".kat")] = "content" - } - reader := createTestTarGz(t, inputFiles, nil) - _, err := UntarQuadlets(reader) - if err == nil { - t.Fatal("UntarQuadlets() with too many files did not return an error") - } - if !strings.Contains(err.Error(), "too many files in quadlet bundle") { - t.Errorf("Expected 'too many files' error, got: %v", err) - } + inputFiles := make(map[string]string) + for i := 0; i <= maxQuadletFiles; i++ { + inputFiles[filepath.Join(".", "file"+string(rune(i+'a'))+".kat")] = "content" + } + reader := createTestTarGz(t, inputFiles, nil) + _, err := UntarQuadlets(reader) + if err == nil { + t.Fatal("UntarQuadlets() with too many files did not return an error") + } + if !strings.Contains(err.Error(), "too many files in quadlet bundle") { + t.Errorf("Expected 'too many files' error, got: %v", err) + } } func TestUntarQuadlets_UnsupportedFileType(t *testing.T) { diff --git a/scripts/gen-proto.sh b/scripts/gen-proto.sh new file mode 100755 index 0000000..51e6ccc --- /dev/null +++ b/scripts/gen-proto.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# File: scripts/gen-proto.sh +set -xe + +# Find protoc-gen-go +PROTOC_GEN_GO_PATH="" +if command -v protoc-gen-go &> /dev/null; then + PROTOC_GEN_GO_PATH=$(command -v protoc-gen-go) +elif [ -f "$(go env GOBIN)/protoc-gen-go" ]; then + PROTOC_GEN_GO_PATH="$(go env GOBIN)/protoc-gen-go" +elif [ -f "$(go env GOPATH)/bin/protoc-gen-go" ]; then + PROTOC_GEN_GO_PATH="$(go env GOPATH)/bin/protoc-gen-go" +else + echo "protoc-gen-go not found. Please run:" + echo "go install google.golang.org/protobuf/cmd/protoc-gen-go" + echo "And ensure GOBIN or GOPATH/bin is in your PATH." + exit 1 +fi + +# Project root assumed to be parent of 'scripts' directory +PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" +API_DIR="${PROJECT_ROOT}/api/v1alpha1" +# Output generated code directly into the api/v1alpha1 directory, alongside kat.proto +# This is a common pattern and simplifies imports. +# The go_package option in kat.proto already points here. +OUT_DIR="${API_DIR}" + +# Ensure output directory exists (it should, it's the same as API_DIR) +mkdir -p "$OUT_DIR" + +echo "Generating Go code from Protobuf definitions..." +protoc --proto_path="${API_DIR}" \ + --plugin="protoc-gen-go=${PROTOC_GEN_GO_PATH}" \ + --go_out="${OUT_DIR}" --go_opt=paths=source_relative \ + "${API_DIR}/kat.proto" + +echo "Protobuf Go code generated in ${OUT_DIR}" + +# Optional: Generate gRPC stubs if/when you add services +# PROTOC_GEN_GO_GRPC_PATH="" # Similar logic to find protoc-gen-go-grpc +# go install google.golang.org/grpc/cmd/protoc-gen-go-grpc +# protoc --proto_path="${API_DIR}" \ +# --plugin="protoc-gen-go=${PROTOC_GEN_GO_PATH}" \ +# --plugin="protoc-gen-go-grpc=${PROTOC_GEN_GO_GRPC_PATH}" \ +# --go_out="${OUT_DIR}" --go_opt=paths=source_relative \ +# --go-grpc_out="${OUT_DIR}" --go-grpc_opt=paths=source_relative \ +# "${API_DIR}/kat.proto" \ No newline at end of file