diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/README.md b/cluster-autoscaler/cloudprovider/externalgrpc/README.md index d73118fc71f0..132319b17ab3 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/README.md +++ b/cluster-autoscaler/cloudprovider/externalgrpc/README.md @@ -52,30 +52,7 @@ The `CloudProvider` interface was designed with the assumption that its implemen ### Code Generation -To regenerate the gRPC code: - -1. install `protoc` and `protoc-gen-go-grpc`: - -```bash -go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.31 -go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3 -``` - -2. import proto dependencies using go modules -```bash -go mod vendor -``` - -3. generate gRPC client and server code: - -```bash -protoc \ - -I ./cluster-autoscaler \ - -I ./cluster-autoscaler/vendor \ - --go_out=. \ - --go-grpc_out=. \ - ./cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto -``` +To regenerate the gRPC code, run the `cluster-autoscaler/hack/update-proto.sh` script ### General considerations diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go b/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go index 45bbad632c55..9f25e15478c6 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go @@ -24,6 +24,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/anypb" + apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" @@ -123,8 +124,25 @@ func (w *Wrapper) PricingNodePrice(_ context.Context, req *protos.PricingNodePri return nil, err } reqNode := req.GetNode() - reqStartTime := req.GetStartTime() - reqEndTime := req.GetEndTime() + + var reqStartTime *metav1.Time + if startTimestamp := req.GetStartTimestamp(); startTimestamp != nil { + // read standard protobuf timestamp if set + reqStartTime = &metav1.Time{Time: startTimestamp.AsTime()} + } else { + // otherwise fallback to reading metav1.Time + reqStartTime = req.GetStartTime() + } + + var reqEndTime *metav1.Time + if endTimestamp := req.GetEndTimestamp(); endTimestamp != nil { + // read standard protobuf timestamp if set + reqEndTime = &metav1.Time{Time: endTimestamp.AsTime()} + } else { + // otherwise fallback to reading metav1.Time + reqEndTime = req.GetEndTime() + } + if reqNode == nil || reqStartTime == nil || reqEndTime == nil { return nil, fmt.Errorf("request fields were nil") } @@ -148,9 +166,38 @@ func (w *Wrapper) PricingPodPrice(_ context.Context, req *protos.PricingPodPrice } return nil, err } - reqPod := req.GetPod() - reqStartTime := req.GetStartTime() - reqEndTime := req.GetEndTime() + + var reqPod *apiv1.Pod + if podBytes := req.GetPodBytes(); podBytes != nil { + // decode from opaque bytes into pod if set + pod := &apiv1.Pod{} + if err := pod.Unmarshal(podBytes); err != nil { + return nil, err + } + reqPod = pod + } else { + // otherwise fallback to reading inlined pod + reqPod = req.GetPod() + } + + var reqStartTime *metav1.Time + if startTimestamp := req.GetStartTimestamp(); startTimestamp != nil { + // read standard protobuf timestamp if set + reqStartTime = &metav1.Time{Time: startTimestamp.AsTime()} + } else { + // otherwise fallback to reading metav1.Time + reqStartTime = req.GetStartTime() + } + + var reqEndTime *metav1.Time + if endTimestamp := req.GetEndTimestamp(); endTimestamp != nil { + // read standard protobuf timestamp if set + reqEndTime = &metav1.Time{Time: endTimestamp.AsTime()} + } else { + // otherwise fallback to reading metav1.Time + reqEndTime = req.GetEndTime() + } + if reqPod == nil || reqStartTime == nil || reqEndTime == nil { return nil, fmt.Errorf("request fields were nil") } diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider.go b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider.go index 2779f229e3d3..a10934601eeb 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider.go @@ -30,6 +30,8 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" + apiv1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -162,6 +164,9 @@ func (m *pricingModel) NodePrice(node *apiv1.Node, startTime time.Time, endTime Node: externalGrpcNode(node), StartTime: &start, EndTime: &end, + + StartTimestamp: timestamppb.New(startTime), + EndTimestamp: timestamppb.New(endTime), }) if err != nil { st, ok := status.FromError(err) @@ -182,10 +187,20 @@ func (m *pricingModel) PodPrice(pod *apiv1.Pod, startTime time.Time, endTime tim klog.V(5).Infof("Performing gRPC call PricingPodPrice for pod %v", pod.Name) start := metav1.NewTime(startTime) end := metav1.NewTime(endTime) + + podBytes, err := pod.Marshal() + if err != nil { + return 0, err + } + res, err := m.client.PricingPodPrice(ctx, &protos.PricingPodPriceRequest{ Pod: pod, StartTime: &start, EndTime: &end, + + PodBytes: podBytes, + StartTimestamp: timestamppb.New(startTime), + EndTimestamp: timestamppb.New(endTime), }) if err != nil { st, ok := status.FromError(err) diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider_test.go b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider_test.go index 366b1f418357..82caca504357 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider_test.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_cloud_provider_test.go @@ -26,6 +26,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/anypb" + apiv1 "k8s.io/api/core/v1" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/externalgrpc/protos" @@ -309,7 +310,8 @@ func TestCloudProvider_Pricing(t *testing.T) { // test correct PodPrice call m.On( "PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool { - return req.Pod.Name == "pod1" + pod := &apiv1.Pod{} + return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod1" }), ).Return( &protos.PricingPodPriceResponse{Price: 100}, @@ -317,7 +319,8 @@ func TestCloudProvider_Pricing(t *testing.T) { ) m.On( "PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool { - return req.Pod.Name == "pod2" + pod := &apiv1.Pod{} + return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod2" }), ).Return( &protos.PricingPodPriceResponse{Price: 200}, @@ -341,7 +344,8 @@ func TestCloudProvider_Pricing(t *testing.T) { // test grpc error for PodPrice m.On( "PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool { - return req.Pod.Name == "pod3" + pod := &apiv1.Pod{} + return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod3" }), ).Return( &protos.PricingPodPriceResponse{}, @@ -357,7 +361,8 @@ func TestCloudProvider_Pricing(t *testing.T) { // test notImplemented for PodPrice m.On( "PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool { - return req.Pod.Name == "pod4" + pod := &apiv1.Pod{} + return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod4" }), ).Return( &protos.PricingPodPriceResponse{}, diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go index c500ba41f11f..ab69bb2ac2fb 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go @@ -16,7 +16,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.6 -// protoc v5.29.2 +// protoc v6.33.0 // source: cloudprovider/externalgrpc/protos/externalgrpc.proto package protos @@ -26,6 +26,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" anypb "google.golang.org/protobuf/types/known/anypb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" v11 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" reflect "reflect" @@ -416,9 +417,19 @@ type PricingNodePriceRequest struct { // Node for which the request is performed. Node *ExternalGrpcNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` // Start time for the request period. + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and startTimestamp. Readers should prefer startTimestamp if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. StartTime *v1.Time `protobuf:"bytes,2,opt,name=startTime,proto3" json:"startTime,omitempty"` // End time for the request period. - EndTime *v1.Time `protobuf:"bytes,3,opt,name=endTime,proto3" json:"endTime,omitempty"` + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and endTimestamp. Readers should prefer endTimestamp if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. + EndTime *v1.Time `protobuf:"bytes,3,opt,name=endTime,proto3" json:"endTime,omitempty"` + // Start time for the request period. + StartTimestamp *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=startTimestamp,proto3" json:"startTimestamp,omitempty"` + // End time for the request period. + EndTimestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=endTimestamp,proto3" json:"endTimestamp,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -460,6 +471,7 @@ func (x *PricingNodePriceRequest) GetNode() *ExternalGrpcNode { return nil } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *PricingNodePriceRequest) GetStartTime() *v1.Time { if x != nil { return x.StartTime @@ -467,6 +479,7 @@ func (x *PricingNodePriceRequest) GetStartTime() *v1.Time { return nil } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *PricingNodePriceRequest) GetEndTime() *v1.Time { if x != nil { return x.EndTime @@ -474,6 +487,20 @@ func (x *PricingNodePriceRequest) GetEndTime() *v1.Time { return nil } +func (x *PricingNodePriceRequest) GetStartTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.StartTimestamp + } + return nil +} + +func (x *PricingNodePriceRequest) GetEndTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.EndTimestamp + } + return nil +} + type PricingNodePriceResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Theoretical minimum price of running a node for a given period. @@ -522,11 +549,28 @@ func (x *PricingNodePriceResponse) GetPrice() float64 { type PricingPodPriceRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Pod for which the request is performed. + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and podBytes. Readers should prefer to podBytes if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. Pod *v11.Pod `protobuf:"bytes,1,opt,name=pod,proto3" json:"pod,omitempty"` // Start time for the request period. + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and startTimestamp. Readers should prefer startTimestamp if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. StartTime *v1.Time `protobuf:"bytes,2,opt,name=startTime,proto3" json:"startTime,omitempty"` // End time for the request period. - EndTime *v1.Time `protobuf:"bytes,3,opt,name=endTime,proto3" json:"endTime,omitempty"` + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and endTimestamp. Readers should prefer endTimestamp if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. + EndTime *v1.Time `protobuf:"bytes,3,opt,name=endTime,proto3" json:"endTime,omitempty"` + // Proto-marshaled bytes for the pod for which the request is performed. + // Generated by calling v1.Pod#Marshal(). + // Convertable to a pod by calling v1.Pod#Unmarshal(). + PodBytes []byte `protobuf:"bytes,4,opt,name=pod_bytes,json=podBytes,proto3" json:"pod_bytes,omitempty"` + // Start time for the request period. + StartTimestamp *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=startTimestamp,proto3" json:"startTimestamp,omitempty"` + // End time for the request period. + EndTimestamp *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=endTimestamp,proto3" json:"endTimestamp,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -561,6 +605,7 @@ func (*PricingPodPriceRequest) Descriptor() ([]byte, []int) { return file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDescGZIP(), []int{8} } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *PricingPodPriceRequest) GetPod() *v11.Pod { if x != nil { return x.Pod @@ -568,6 +613,7 @@ func (x *PricingPodPriceRequest) GetPod() *v11.Pod { return nil } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *PricingPodPriceRequest) GetStartTime() *v1.Time { if x != nil { return x.StartTime @@ -575,6 +621,7 @@ func (x *PricingPodPriceRequest) GetStartTime() *v1.Time { return nil } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *PricingPodPriceRequest) GetEndTime() *v1.Time { if x != nil { return x.EndTime @@ -582,6 +629,27 @@ func (x *PricingPodPriceRequest) GetEndTime() *v1.Time { return nil } +func (x *PricingPodPriceRequest) GetPodBytes() []byte { + if x != nil { + return x.PodBytes + } + return nil +} + +func (x *PricingPodPriceRequest) GetStartTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.StartTimestamp + } + return nil +} + +func (x *PricingPodPriceRequest) GetEndTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.EndTimestamp + } + return nil +} + type PricingPodPriceResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // Theoretical minimum price of running a pod for a given period. @@ -1854,7 +1922,7 @@ var File_cloudprovider_externalgrpc_protos_externalgrpc_proto protoreflect.FileD const file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDesc = "" + "\n" + - "4cloudprovider/externalgrpc/protos/externalgrpc.proto\x12/clusterautoscaler.cloudprovider.v1.externalgrpc\x1a\x19google/protobuf/any.proto\x1a google/protobuf/descriptor.proto\x1a\"k8s.io/api/core/v1/generated.proto\x1a4k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto\"e\n" + + "4cloudprovider/externalgrpc/protos/externalgrpc.proto\x12/clusterautoscaler.cloudprovider.v1.externalgrpc\x1a\x19google/protobuf/any.proto\x1a google/protobuf/descriptor.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\"k8s.io/api/core/v1/generated.proto\x1a4k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto\"e\n" + "\tNodeGroup\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x18\n" + "\aminSize\x18\x02 \x01(\x05R\aminSize\x12\x18\n" + @@ -1881,17 +1949,22 @@ const file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDesc = "" + "\x17NodeGroupForNodeRequest\x12U\n" + "\x04node\x18\x01 \x01(\v2A.clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNodeR\x04node\"t\n" + "\x18NodeGroupForNodeResponse\x12X\n" + - "\tnodeGroup\x18\x01 \x01(\v2:.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupR\tnodeGroup\"\x80\x02\n" + + "\tnodeGroup\x18\x01 \x01(\v2:.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupR\tnodeGroup\"\x8c\x03\n" + "\x17PricingNodePriceRequest\x12U\n" + - "\x04node\x18\x01 \x01(\v2A.clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNodeR\x04node\x12H\n" + - "\tstartTime\x18\x02 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeR\tstartTime\x12D\n" + - "\aendTime\x18\x03 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeR\aendTime\"0\n" + + "\x04node\x18\x01 \x01(\v2A.clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNodeR\x04node\x12L\n" + + "\tstartTime\x18\x02 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeB\x02\x18\x01R\tstartTime\x12H\n" + + "\aendTime\x18\x03 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeB\x02\x18\x01R\aendTime\x12B\n" + + "\x0estartTimestamp\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\x0estartTimestamp\x12>\n" + + "\fendTimestamp\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\fendTimestamp\"0\n" + "\x18PricingNodePriceResponse\x12\x14\n" + - "\x05price\x18\x01 \x01(\x01R\x05price\"\xd3\x01\n" + - "\x16PricingPodPriceRequest\x12)\n" + - "\x03pod\x18\x01 \x01(\v2\x17.k8s.io.api.core.v1.PodR\x03pod\x12H\n" + - "\tstartTime\x18\x02 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeR\tstartTime\x12D\n" + - "\aendTime\x18\x03 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeR\aendTime\"/\n" + + "\x05price\x18\x01 \x01(\x01R\x05price\"\x80\x03\n" + + "\x16PricingPodPriceRequest\x12-\n" + + "\x03pod\x18\x01 \x01(\v2\x17.k8s.io.api.core.v1.PodB\x02\x18\x01R\x03pod\x12L\n" + + "\tstartTime\x18\x02 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeB\x02\x18\x01R\tstartTime\x12H\n" + + "\aendTime\x18\x03 \x01(\v2*.k8s.io.apimachinery.pkg.apis.meta.v1.TimeB\x02\x18\x01R\aendTime\x12\x1b\n" + + "\tpod_bytes\x18\x04 \x01(\fR\bpodBytes\x12B\n" + + "\x0estartTimestamp\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\x0estartTimestamp\x12>\n" + + "\fendTimestamp\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\fendTimestamp\"/\n" + "\x17PricingPodPriceResponse\x12\x14\n" + "\x05price\x18\x01 \x01(\x01R\x05price\"\x11\n" + "\x0fGPULabelRequest\"(\n" + @@ -1977,7 +2050,7 @@ const file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDesc = "" + "\x1bNodeGroupDecreaseTargetSize\x12S.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeRequest\x1aT.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeResponse\"\x00\x12\xa3\x01\n" + "\x0eNodeGroupNodes\x12F.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesRequest\x1aG.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesResponse\"\x00\x12\xc4\x01\n" + "\x19NodeGroupTemplateNodeInfo\x12Q.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoRequest\x1aR.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoResponse\"\x00\x12\xc2\x01\n" + - "\x13NodeGroupGetOptions\x12S.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest\x1aT.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse\"\x00B6Z4cluster-autoscaler/cloudprovider/externalgrpc/protosb\x06proto3" + "\x13NodeGroupGetOptions\x12S.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest\x1aT.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse\"\x00B#Z!cloudprovider/externalgrpc/protosb\x06proto3" var ( file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDescOnce sync.Once @@ -2031,14 +2104,15 @@ var file_cloudprovider_externalgrpc_protos_externalgrpc_proto_goTypes = []any{ (*NodeGroupAutoscalingOptions)(nil), // 34: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions (*NodeGroupAutoscalingOptionsRequest)(nil), // 35: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest (*NodeGroupAutoscalingOptionsResponse)(nil), // 36: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse - nil, // 37: clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.LabelsEntry - nil, // 38: clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.AnnotationsEntry - nil, // 39: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry - (*v1.Time)(nil), // 40: k8s.io.apimachinery.pkg.apis.meta.v1.Time - (*v11.Pod)(nil), // 41: k8s.io.api.core.v1.Pod - (*v11.Node)(nil), // 42: k8s.io.api.core.v1.Node - (*v1.Duration)(nil), // 43: k8s.io.apimachinery.pkg.apis.meta.v1.Duration - (*anypb.Any)(nil), // 44: google.protobuf.Any + nil, // 37: clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.LabelsEntry + nil, // 38: clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.AnnotationsEntry + nil, // 39: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry + (*v1.Time)(nil), // 40: k8s.io.apimachinery.pkg.apis.meta.v1.Time + (*timestamppb.Timestamp)(nil), // 41: google.protobuf.Timestamp + (*v11.Pod)(nil), // 42: k8s.io.api.core.v1.Pod + (*v11.Node)(nil), // 43: k8s.io.api.core.v1.Node + (*v1.Duration)(nil), // 44: k8s.io.apimachinery.pkg.apis.meta.v1.Duration + (*anypb.Any)(nil), // 45: google.protobuf.Any } var file_cloudprovider_externalgrpc_protos_externalgrpc_proto_depIdxs = []int32{ 37, // 0: clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.labels:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.LabelsEntry @@ -2049,57 +2123,61 @@ var file_cloudprovider_externalgrpc_protos_externalgrpc_proto_depIdxs = []int32{ 2, // 5: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest.node:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode 40, // 6: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest.startTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Time 40, // 7: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest.endTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Time - 41, // 8: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.pod:type_name -> k8s.io.api.core.v1.Pod - 40, // 9: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.startTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Time - 40, // 10: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.endTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Time - 39, // 11: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.gpuTypes:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry - 2, // 12: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesRequest.nodes:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode - 29, // 13: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesResponse.instances:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.Instance - 30, // 14: clusterautoscaler.cloudprovider.v1.externalgrpc.Instance.status:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus - 0, // 15: clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus.instanceState:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus.InstanceState - 31, // 16: clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus.errorInfo:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceErrorInfo - 42, // 17: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoResponse.nodeInfo:type_name -> k8s.io.api.core.v1.Node - 43, // 18: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnneededTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration - 43, // 19: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnreadyTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration - 43, // 20: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.MaxNodeProvisionTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration - 34, // 21: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest.defaults:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions - 34, // 22: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse.nodeGroupAutoscalingOptions:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions - 44, // 23: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry.value:type_name -> google.protobuf.Any - 3, // 24: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsRequest - 5, // 25: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeRequest - 7, // 26: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest - 9, // 27: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest - 11, // 28: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelRequest - 13, // 29: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesRequest - 15, // 30: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupRequest - 17, // 31: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshRequest - 19, // 32: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeRequest - 21, // 33: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeRequest - 23, // 34: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesRequest - 25, // 35: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeRequest - 27, // 36: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesRequest - 32, // 37: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoRequest - 35, // 38: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest - 4, // 39: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsResponse - 6, // 40: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeResponse - 8, // 41: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceResponse - 10, // 42: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceResponse - 12, // 43: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelResponse - 14, // 44: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse - 16, // 45: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupResponse - 18, // 46: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshResponse - 20, // 47: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeResponse - 22, // 48: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeResponse - 24, // 49: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesResponse - 26, // 50: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeResponse - 28, // 51: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesResponse - 33, // 52: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoResponse - 36, // 53: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse - 39, // [39:54] is the sub-list for method output_type - 24, // [24:39] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 41, // 8: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest.startTimestamp:type_name -> google.protobuf.Timestamp + 41, // 9: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest.endTimestamp:type_name -> google.protobuf.Timestamp + 42, // 10: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.pod:type_name -> k8s.io.api.core.v1.Pod + 40, // 11: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.startTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Time + 40, // 12: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.endTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Time + 41, // 13: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.startTimestamp:type_name -> google.protobuf.Timestamp + 41, // 14: clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest.endTimestamp:type_name -> google.protobuf.Timestamp + 39, // 15: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.gpuTypes:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry + 2, // 16: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesRequest.nodes:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode + 29, // 17: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesResponse.instances:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.Instance + 30, // 18: clusterautoscaler.cloudprovider.v1.externalgrpc.Instance.status:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus + 0, // 19: clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus.instanceState:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus.InstanceState + 31, // 20: clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceStatus.errorInfo:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.InstanceErrorInfo + 43, // 21: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoResponse.nodeInfo:type_name -> k8s.io.api.core.v1.Node + 44, // 22: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnneededTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration + 44, // 23: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnreadyTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration + 44, // 24: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.MaxNodeProvisionTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration + 34, // 25: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest.defaults:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions + 34, // 26: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse.nodeGroupAutoscalingOptions:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions + 45, // 27: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry.value:type_name -> google.protobuf.Any + 3, // 28: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsRequest + 5, // 29: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeRequest + 7, // 30: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest + 9, // 31: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest + 11, // 32: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelRequest + 13, // 33: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesRequest + 15, // 34: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupRequest + 17, // 35: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshRequest + 19, // 36: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeRequest + 21, // 37: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeRequest + 23, // 38: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesRequest + 25, // 39: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeRequest + 27, // 40: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesRequest + 32, // 41: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoRequest + 35, // 42: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest + 4, // 43: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsResponse + 6, // 44: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeResponse + 8, // 45: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceResponse + 10, // 46: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceResponse + 12, // 47: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelResponse + 14, // 48: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse + 16, // 49: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupResponse + 18, // 50: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshResponse + 20, // 51: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeResponse + 22, // 52: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeResponse + 24, // 53: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesResponse + 26, // 54: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeResponse + 28, // 55: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesResponse + 33, // 56: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoResponse + 36, // 57: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse + 43, // [43:58] is the sub-list for method output_type + 28, // [28:43] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name } func init() { file_cloudprovider_externalgrpc_protos_externalgrpc_proto_init() } diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto index 0e87886666d1..b90f011d2801 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto +++ b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto @@ -20,10 +20,11 @@ package clusterautoscaler.cloudprovider.v1.externalgrpc; import "google/protobuf/any.proto"; import "google/protobuf/descriptor.proto"; +import "google/protobuf/timestamp.proto"; import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -option go_package = "cluster-autoscaler/cloudprovider/externalgrpc/protos"; +option go_package = "cloudprovider/externalgrpc/protos"; service CloudProvider { // CloudProvider specific RPC functions @@ -150,10 +151,18 @@ message PricingNodePriceRequest { ExternalGrpcNode node = 1; // Start time for the request period. - k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 2; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and startTimestamp. Readers should prefer startTimestamp if set. + k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 2 [deprecated = true]; // End time for the request period. - k8s.io.apimachinery.pkg.apis.meta.v1.Time endTime = 3; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and endTimestamp. Readers should prefer endTimestamp if set. + k8s.io.apimachinery.pkg.apis.meta.v1.Time endTime = 3 [deprecated = true]; + + // Start time for the request period. + google.protobuf.Timestamp startTimestamp = 4; + + // End time for the request period. + google.protobuf.Timestamp endTimestamp = 5; } message PricingNodePriceResponse { @@ -163,13 +172,27 @@ message PricingNodePriceResponse { message PricingPodPriceRequest { // Pod for which the request is performed. - k8s.io.api.core.v1.Pod pod = 1; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and podBytes. Readers should prefer to podBytes if set. + k8s.io.api.core.v1.Pod pod = 1 [deprecated = true]; + + // Start time for the request period. + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and startTimestamp. Readers should prefer startTimestamp if set. + k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 2 [deprecated = true]; + + // End time for the request period. + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and endTimestamp. Readers should prefer endTimestamp if set. + k8s.io.apimachinery.pkg.apis.meta.v1.Time endTime = 3 [deprecated = true]; + + // Proto-marshaled bytes for the pod for which the request is performed. + // Generated by calling v1.Pod#Marshal(). + // Convertable to a pod by calling v1.Pod#Unmarshal(). + bytes pod_bytes = 4; // Start time for the request period. - k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 2; + google.protobuf.Timestamp startTimestamp = 5; // End time for the request period. - k8s.io.apimachinery.pkg.apis.meta.v1.Time endTime = 3; + google.protobuf.Timestamp endTimestamp = 6; } message PricingPodPriceResponse { diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc_grpc.pb.go b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc_grpc.pb.go index e788f5d071e7..3c45674257e6 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc_grpc.pb.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc_grpc.pb.go @@ -16,7 +16,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.29.2 +// - protoc v6.33.0 // source: cloudprovider/externalgrpc/protos/externalgrpc.proto package protos diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc_test.go b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc_test.go new file mode 100644 index 000000000000..c4ea0aac352f --- /dev/null +++ b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc_test.go @@ -0,0 +1,122 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package protos + +import ( + "testing" + "time" + + "github.com/golang/protobuf/proto" + "github.com/google/go-cmp/cmp" + "google.golang.org/protobuf/types/known/timestamppb" + + corev1 "k8s.io/api/core/v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestRoundTripPricingPodPriceRequest(t *testing.T) { + t1 := time.Unix(1000, 100) + t1meta := metav1.NewTime(t1) + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "test"}, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "test", + Image: "test", + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + "cpu": resource.MustParse("1"), + "memory": resource.MustParse("1Gi"), + }, + }, + }}, + }, + } + podBytes, err := pod.Marshal() + if err != nil { + t.Fatal(err) + } + + r := &PricingPodPriceRequest{ + // These three fields are expected to stop being serializable in 1.35, + // and to need to be removed from the .proto file + StartTime: &t1meta, + EndTime: &t1meta, + Pod: pod, + + // These fields should remain serializable + StartTimestamp: timestamppb.New(t1), + EndTimestamp: timestamppb.New(t1), + PodBytes: podBytes, + } + data, err := proto.Marshal(r) + if err != nil { + t.Fatal(err) + } + + r2 := &PricingPodPriceRequest{} + if err := proto.Unmarshal(data, r2); err != nil { + t.Fatal(err) + } + + pod2 := &corev1.Pod{} + if err := pod2.Unmarshal(r2.PodBytes); err != nil { + t.Fatal(err) + } + if !proto.Equal(r, r2) { + t.Fatalf("message did not round-trip: %s", cmp.Diff(r, r2)) + } + // The Pod field is expected to be removed in 1.35 + if !apiequality.Semantic.DeepEqual(pod, r2.Pod) { + t.Fatalf("pod did not round-trip: %s", cmp.Diff(r, r2)) + } + // Pod bytes must remain round-trippable + if !apiequality.Semantic.DeepEqual(pod, pod2) { + t.Fatalf("pod bytes did not round-trip: %s", cmp.Diff(r, r2)) + } +} + +func TestRoundTripPricingNodePriceRequest(t *testing.T) { + t1 := time.Unix(1000, 100) + t1meta := metav1.NewTime(t1) + + r := &PricingNodePriceRequest{ + // These three fields are expected to stop being serializable in 1.35, + // and to need to be removed from the .proto file + StartTime: &t1meta, + EndTime: &t1meta, + + // These fields should remain serializable + StartTimestamp: timestamppb.New(t1), + EndTimestamp: timestamppb.New(t1), + } + data, err := proto.Marshal(r) + if err != nil { + t.Fatal(err) + } + + r2 := &PricingNodePriceRequest{} + if err := proto.Unmarshal(data, r2); err != nil { + t.Fatal(err) + } + + if !proto.Equal(r, r2) { + t.Fatalf("message did not round-trip: %s", cmp.Diff(r, r2)) + } +} diff --git a/cluster-autoscaler/expander/grpcplugin/README.md b/cluster-autoscaler/expander/grpcplugin/README.md index a27ce2358a46..c19a41217503 100644 --- a/cluster-autoscaler/expander/grpcplugin/README.md +++ b/cluster-autoscaler/expander/grpcplugin/README.md @@ -38,4 +38,6 @@ Start Cluster Autoscaler with the `--grpc-expander-url=SERVICE_NAME.NAMESPACE_NA The gRPC client currently transforms nodeInfo objects passed into the expander to v1.Node objects to save rpc call throughput. As such, the gRPC server will not have access to daemonsets and static pods running on each node. +### Code Generation +To regenerate the gRPC code, run the `cluster-autoscaler/hack/update-proto.sh` script diff --git a/cluster-autoscaler/expander/grpcplugin/example/fake_grpc_server.go b/cluster-autoscaler/expander/grpcplugin/example/fake_grpc_server.go index e4aac5fcd55e..162f8b9fc128 100644 --- a/cluster-autoscaler/expander/grpcplugin/example/fake_grpc_server.go +++ b/cluster-autoscaler/expander/grpcplugin/example/fake_grpc_server.go @@ -24,6 +24,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" + "k8s.io/autoscaler/cluster-autoscaler/expander/grpcplugin/protos" ) @@ -72,7 +73,9 @@ func getNetListener(port uint) net.Listener { } // ExpanderServerImpl is an implementation of Expander Server from proto definition -type ExpanderServerImpl struct{} +type ExpanderServerImpl struct { + protos.UnsafeExpanderServer +} // NewExpanderServerImpl is this Expander's implementation of the server func NewExpanderServerImpl() *ExpanderServerImpl { diff --git a/cluster-autoscaler/expander/grpcplugin/grpc_client.go b/cluster-autoscaler/expander/grpcplugin/grpc_client.go index ca1f2a716960..c0025859d102 100644 --- a/cluster-autoscaler/expander/grpcplugin/grpc_client.go +++ b/cluster-autoscaler/expander/grpcplugin/grpc_client.go @@ -80,13 +80,13 @@ func (g *grpcclientstrategy) BestOptions(expansionOptions []expander.Option, nod // Transform inputs to gRPC inputs grpcOptionsSlice, nodeGroupIDOptionMap := populateOptionsForGRPC(expansionOptions) - grpcNodeMap := populateNodeInfoForGRPC(nodeInfo) + grpcNodeMap, grpcNodeBytesMap := populateNodeInfoForGRPC(nodeInfo) // call gRPC server to get BestOption klog.V(2).Infof("GPRC call of best options to server with %v options", len(nodeGroupIDOptionMap)) ctx, cancel := context.WithTimeout(context.Background(), gRPCTimeout) defer cancel() - bestOptionsResponse, err := g.grpcClient.BestOptions(ctx, &protos.BestOptionsRequest{Options: grpcOptionsSlice, NodeMap: grpcNodeMap}) + bestOptionsResponse, err := g.grpcClient.BestOptions(ctx, &protos.BestOptionsRequest{Options: grpcOptionsSlice, NodeMap: grpcNodeMap, NodeBytesMap: grpcNodeBytesMap}) if err != nil { klog.V(4).Infof("GRPC call failed, no options filtered: %v", err) return expansionOptions @@ -117,12 +117,26 @@ func populateOptionsForGRPC(expansionOptions []expander.Option) ([]*protos.Optio } // populateNodeInfoForGRPC looks at the corresponding v1.Node object per NodeInfo object, and populates the grpcNodeInfoMap with these to pass over grpc -func populateNodeInfoForGRPC(nodeInfos map[string]*framework.NodeInfo) map[string]*v1.Node { +func populateNodeInfoForGRPC(nodeInfos map[string]*framework.NodeInfo) (map[string]*v1.Node, map[string][]byte) { grpcNodeInfoMap := make(map[string]*v1.Node) + grpcNodeBytesMap := make(map[string][]byte) for nodeId, nodeInfo := range nodeInfos { - grpcNodeInfoMap[nodeId] = nodeInfo.Node() + node := nodeInfo.Node() + grpcNodeInfoMap[nodeId] = node + + // if we're still accumulating node bytes + if grpcNodeBytesMap != nil { + // try to serialize to proto bytes + nodeBytes, err := node.Marshal() + if err != nil { + // unexpected proto serialization error, avoid sending nodeBytes map at all + grpcNodeBytesMap = nil + } else { + grpcNodeBytesMap[nodeId] = nodeBytes + } + } } - return grpcNodeInfoMap + return grpcNodeInfoMap, grpcNodeBytesMap } func transformAndSanitizeOptionsFromGRPC(bestOptionsResponseOptions []*protos.Option, nodeGroupIDOptionMap map[string]expander.Option) []expander.Option { @@ -143,5 +157,17 @@ func transformAndSanitizeOptionsFromGRPC(bestOptionsResponseOptions []*protos.Op } func newOptionMessage(nodeGroupId string, nodeCount int32, debug string, pods []*v1.Pod) *protos.Option { - return &protos.Option{NodeGroupId: nodeGroupId, NodeCount: nodeCount, Debug: debug, Pod: pods} + var podsBytes [][]byte + if len(pods) > 0 { + podsBytes = make([][]byte, 0, len(pods)) + for _, pod := range pods { + podBytes, err := pod.Marshal() + if err != nil { + podsBytes = nil + break + } + podsBytes = append(podsBytes, podBytes) + } + } + return &protos.Option{NodeGroupId: nodeGroupId, NodeCount: nodeCount, Debug: debug, Pod: pods, PodBytes: podsBytes} } diff --git a/cluster-autoscaler/expander/grpcplugin/grpc_client_test.go b/cluster-autoscaler/expander/grpcplugin/grpc_client_test.go index d04670bebd74..c5990184f6cf 100644 --- a/cluster-autoscaler/expander/grpcplugin/grpc_client_test.go +++ b/cluster-autoscaler/expander/grpcplugin/grpc_client_test.go @@ -22,6 +22,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" "k8s.io/autoscaler/cluster-autoscaler/expander/grpcplugin/protos" "k8s.io/autoscaler/cluster-autoscaler/expander/mocks" @@ -135,13 +136,17 @@ func makeFakeNodeInfos() map[string]*framework.NodeInfo { func TestPopulateNodeInfoForGRPC(t *testing.T) { nodeInfos := makeFakeNodeInfos() - grpcNodeInfoMap := populateNodeInfoForGRPC(nodeInfos) + grpcNodeInfoMap, grpcNodeBytesMap := populateNodeInfoForGRPC(nodeInfos) expectedGrpcNodeInfoMap := make(map[string]*v1.Node) + expectedGrpcNodeBytesMap := make(map[string][]byte) for i, opt := range options { expectedGrpcNodeInfoMap[opt.NodeGroup.Id()] = nodes[i] + expectedGrpcNodeBytesMap[opt.NodeGroup.Id()], _ = nodes[i].Marshal() } + assert.Equal(t, expectedGrpcNodeInfoMap, grpcNodeInfoMap) + assert.Equal(t, expectedGrpcNodeBytesMap, grpcNodeBytesMap) } func TestValidTransformAndSanitizeOptionsFromGRPC(t *testing.T) { @@ -179,12 +184,15 @@ func TestBestOptionsValid(t *testing.T) { nodeInfos := makeFakeNodeInfos() grpcNodeInfoMap := make(map[string]*v1.Node) + grpcNodeBytesMap := make(map[string][]byte) for i, opt := range options { grpcNodeInfoMap[opt.NodeGroup.Id()] = nodes[i] + grpcNodeBytesMap[opt.NodeGroup.Id()], _ = nodes[i].Marshal() } expectedBestOptionsReq := &protos.BestOptionsRequest{ - Options: []*protos.Option{&grpcEoT2Micro, &grpcEoT2Large, &grpcEoT3Large, &grpcEoM44XLarge}, - NodeMap: grpcNodeInfoMap, + Options: []*protos.Option{&grpcEoT2Micro, &grpcEoT2Large, &grpcEoT3Large, &grpcEoM44XLarge}, + NodeMap: grpcNodeInfoMap, + NodeBytesMap: grpcNodeBytesMap, } mockClient.EXPECT().BestOptions( @@ -220,12 +228,14 @@ func TestBestOptionsEmpty(t *testing.T) { }, } for _, tc := range testCases { - grpcNodeInfoMap := populateNodeInfoForGRPC(makeFakeNodeInfos()) + grpcNodeInfoMap, grpcNodeBytesMap := populateNodeInfoForGRPC(makeFakeNodeInfos()) + assert.NotNil(t, grpcNodeBytesMap) mockClient.EXPECT().BestOptions( gomock.Any(), gomock.Eq( &protos.BestOptionsRequest{ - Options: []*protos.Option{&grpcEoT2Micro, &grpcEoT2Large, &grpcEoT3Large, &grpcEoM44XLarge}, - NodeMap: grpcNodeInfoMap, + Options: []*protos.Option{&grpcEoT2Micro, &grpcEoT2Large, &grpcEoT3Large, &grpcEoM44XLarge}, + NodeMap: grpcNodeInfoMap, + NodeBytesMap: grpcNodeBytesMap, })).Return(&tc.mockResponse, nil) resp := g.BestOptions(options, makeFakeNodeInfos()) @@ -284,13 +294,15 @@ func TestBestOptionsErrors(t *testing.T) { }, } for _, tc := range testCases { - grpcNodeInfoMap := populateNodeInfoForGRPC(tc.nodeInfo) + grpcNodeInfoMap, grpcNodeBytesMap := populateNodeInfoForGRPC(tc.nodeInfo) + assert.NotNil(t, grpcNodeBytesMap) if tc.client.grpcClient != nil { mockClient.EXPECT().BestOptions( gomock.Any(), gomock.Eq( &protos.BestOptionsRequest{ - Options: []*protos.Option{&grpcEoT2Micro, &grpcEoT2Large, &grpcEoT3Large, &grpcEoM44XLarge}, - NodeMap: grpcNodeInfoMap, + Options: []*protos.Option{&grpcEoT2Micro, &grpcEoT2Large, &grpcEoT3Large, &grpcEoM44XLarge}, + NodeMap: grpcNodeInfoMap, + NodeBytesMap: grpcNodeBytesMap, })).Return(&tc.mockResponse, tc.errResponse) } resp := tc.client.BestOptions(options, tc.nodeInfo) diff --git a/cluster-autoscaler/expander/grpcplugin/protos/expander.pb.go b/cluster-autoscaler/expander/grpcplugin/protos/expander.pb.go index 33faac8ffeae..a4b2b8fb336a 100644 --- a/cluster-autoscaler/expander/grpcplugin/protos/expander.pb.go +++ b/cluster-autoscaler/expander/grpcplugin/protos/expander.pb.go @@ -1,32 +1,33 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +// +//Copyright 2021 The Kubernetes Authors. +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v6.33.0 +// source: expander/grpcplugin/protos/expander.proto package protos import ( - "context" - reflect "reflect" - sync "sync" - - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" v1 "k8s.io/api/core/v1" + reflect "reflect" + sync "sync" + unsafe "unsafe" ) const ( @@ -37,22 +38,25 @@ const ( ) type BestOptionsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Options []*Option `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Options []*Option `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // key is node id from options - NodeMap map[string]*v1.Node `protobuf:"bytes,2,rep,name=nodeMap,proto3" json:"nodeMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and nodeBytesMap. Readers should prefer nodeBytesMap if set. + // + // Deprecated: Marked as deprecated in expander/grpcplugin/protos/expander.proto. + NodeMap map[string]*v1.Node `protobuf:"bytes,2,rep,name=nodeMap,proto3" json:"nodeMap,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // key is node id from options. + // values are proto-serialized v1.Node objects. + NodeBytesMap map[string][]byte `protobuf:"bytes,3,rep,name=nodeBytesMap,proto3" json:"nodeBytesMap,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *BestOptionsRequest) Reset() { *x = BestOptionsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_expander_grpcplugin_protos_expander_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BestOptionsRequest) String() string { @@ -62,8 +66,8 @@ func (x *BestOptionsRequest) String() string { func (*BestOptionsRequest) ProtoMessage() {} func (x *BestOptionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_expander_grpcplugin_protos_expander_proto_msgTypes[0] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -75,7 +79,7 @@ func (x *BestOptionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BestOptionsRequest.ProtoReflect.Descriptor instead. func (*BestOptionsRequest) Descriptor() ([]byte, []int) { - return file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescGZIP(), []int{0} + return file_expander_grpcplugin_protos_expander_proto_rawDescGZIP(), []int{0} } func (x *BestOptionsRequest) GetOptions() []*Option { @@ -85,6 +89,7 @@ func (x *BestOptionsRequest) GetOptions() []*Option { return nil } +// Deprecated: Marked as deprecated in expander/grpcplugin/protos/expander.proto. func (x *BestOptionsRequest) GetNodeMap() map[string]*v1.Node { if x != nil { return x.NodeMap @@ -92,21 +97,25 @@ func (x *BestOptionsRequest) GetNodeMap() map[string]*v1.Node { return nil } +func (x *BestOptionsRequest) GetNodeBytesMap() map[string][]byte { + if x != nil { + return x.NodeBytesMap + } + return nil +} + type BestOptionsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Options []*Option `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` unknownFields protoimpl.UnknownFields - - Options []*Option `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` + sizeCache protoimpl.SizeCache } func (x *BestOptionsResponse) Reset() { *x = BestOptionsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_expander_grpcplugin_protos_expander_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BestOptionsResponse) String() string { @@ -116,8 +125,8 @@ func (x *BestOptionsResponse) String() string { func (*BestOptionsResponse) ProtoMessage() {} func (x *BestOptionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_expander_grpcplugin_protos_expander_proto_msgTypes[1] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -129,7 +138,7 @@ func (x *BestOptionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BestOptionsResponse.ProtoReflect.Descriptor instead. func (*BestOptionsResponse) Descriptor() ([]byte, []int) { - return file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescGZIP(), []int{1} + return file_expander_grpcplugin_protos_expander_proto_rawDescGZIP(), []int{1} } func (x *BestOptionsResponse) GetOptions() []*Option { @@ -140,24 +149,26 @@ func (x *BestOptionsResponse) GetOptions() []*Option { } type Option struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - + state protoimpl.MessageState `protogen:"open.v1"` // only need the ID of node to uniquely identify the nodeGroup, used in the nodeInfo map. - NodeGroupId string `protobuf:"bytes,1,opt,name=nodeGroupId,proto3" json:"nodeGroupId,omitempty"` - NodeCount int32 `protobuf:"varint,2,opt,name=nodeCount,proto3" json:"nodeCount,omitempty"` - Debug string `protobuf:"bytes,3,opt,name=debug,proto3" json:"debug,omitempty"` - Pod []*v1.Pod `protobuf:"bytes,4,rep,name=pod,proto3" json:"pod,omitempty"` + NodeGroupId string `protobuf:"bytes,1,opt,name=nodeGroupId,proto3" json:"nodeGroupId,omitempty"` + NodeCount int32 `protobuf:"varint,2,opt,name=nodeCount,proto3" json:"nodeCount,omitempty"` + Debug string `protobuf:"bytes,3,opt,name=debug,proto3" json:"debug,omitempty"` + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and podBytes. Readers should prefer podBytes if set. + // + // Deprecated: Marked as deprecated in expander/grpcplugin/protos/expander.proto. + Pod []*v1.Pod `protobuf:"bytes,4,rep,name=pod,proto3" json:"pod,omitempty"` + // proto-serialized v1.Pod object + PodBytes [][]byte `protobuf:"bytes,5,rep,name=podBytes,proto3" json:"podBytes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Option) Reset() { *x = Option{} - if protoimpl.UnsafeEnabled { - mi := &file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_expander_grpcplugin_protos_expander_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Option) String() string { @@ -167,8 +178,8 @@ func (x *Option) String() string { func (*Option) ProtoMessage() {} func (x *Option) ProtoReflect() protoreflect.Message { - mi := &file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_expander_grpcplugin_protos_expander_proto_msgTypes[2] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -180,7 +191,7 @@ func (x *Option) ProtoReflect() protoreflect.Message { // Deprecated: Use Option.ProtoReflect.Descriptor instead. func (*Option) Descriptor() ([]byte, []int) { - return file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescGZIP(), []int{2} + return file_expander_grpcplugin_protos_expander_proto_rawDescGZIP(), []int{2} } func (x *Option) GetNodeGroupId() string { @@ -204,6 +215,7 @@ func (x *Option) GetDebug() string { return "" } +// Deprecated: Marked as deprecated in expander/grpcplugin/protos/expander.proto. func (x *Option) GetPod() []*v1.Pod { if x != nil { return x.Pod @@ -211,230 +223,98 @@ func (x *Option) GetPod() []*v1.Pod { return nil } -var File_cluster_autoscaler_expander_grpcplugin_protos_expander_proto protoreflect.FileDescriptor - -var file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDesc = []byte{ - 0x0a, 0x3c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x61, 0x75, 0x74, 0x6f, 0x73, 0x63, - 0x61, 0x6c, 0x65, 0x72, 0x2f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2f, 0x67, 0x72, - 0x70, 0x63, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, - 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, - 0x67, 0x72, 0x70, 0x63, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x1a, 0x22, 0x6b, 0x38, 0x73, 0x2e, - 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdf, - 0x01, 0x0a, 0x12, 0x42, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x70, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x2e, 0x42, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x70, 0x1a, 0x54, 0x0a, 0x0c, 0x4e, 0x6f, - 0x64, 0x65, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6b, 0x38, - 0x73, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x43, 0x0a, 0x13, 0x42, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x70, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x06, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x12, 0x29, 0x0a, 0x03, 0x70, 0x6f, 0x64, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6b, 0x38, 0x73, 0x2e, 0x69, 0x6f, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x64, 0x52, 0x03, 0x70, 0x6f, - 0x64, 0x32, 0x5c, 0x0a, 0x08, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x50, 0x0a, - 0x0b, 0x42, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x42, 0x65, 0x73, 0x74, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x42, 0x65, 0x73, 0x74, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x2f, 0x5a, 0x2d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x61, 0x75, 0x74, 0x6f, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2f, 0x67, - 0x72, 0x70, 0x63, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +func (x *Option) GetPodBytes() [][]byte { + if x != nil { + return x.PodBytes + } + return nil } +var File_expander_grpcplugin_protos_expander_proto protoreflect.FileDescriptor + +const file_expander_grpcplugin_protos_expander_proto_rawDesc = "" + + "\n" + + ")expander/grpcplugin/protos/expander.proto\x12\n" + + "grpcplugin\x1a\"k8s.io/api/core/v1/generated.proto\"\xfa\x02\n" + + "\x12BestOptionsRequest\x12,\n" + + "\aoptions\x18\x01 \x03(\v2\x12.grpcplugin.OptionR\aoptions\x12I\n" + + "\anodeMap\x18\x02 \x03(\v2+.grpcplugin.BestOptionsRequest.NodeMapEntryB\x02\x18\x01R\anodeMap\x12T\n" + + "\fnodeBytesMap\x18\x03 \x03(\v20.grpcplugin.BestOptionsRequest.NodeBytesMapEntryR\fnodeBytesMap\x1aT\n" + + "\fNodeMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12.\n" + + "\x05value\x18\x02 \x01(\v2\x18.k8s.io.api.core.v1.NodeR\x05value:\x028\x01\x1a?\n" + + "\x11NodeBytesMapEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\fR\x05value:\x028\x01\"C\n" + + "\x13BestOptionsResponse\x12,\n" + + "\aoptions\x18\x01 \x03(\v2\x12.grpcplugin.OptionR\aoptions\"\xa9\x01\n" + + "\x06Option\x12 \n" + + "\vnodeGroupId\x18\x01 \x01(\tR\vnodeGroupId\x12\x1c\n" + + "\tnodeCount\x18\x02 \x01(\x05R\tnodeCount\x12\x14\n" + + "\x05debug\x18\x03 \x01(\tR\x05debug\x12-\n" + + "\x03pod\x18\x04 \x03(\v2\x17.k8s.io.api.core.v1.PodB\x02\x18\x01R\x03pod\x12\x1a\n" + + "\bpodBytes\x18\x05 \x03(\fR\bpodBytes2\\\n" + + "\bExpander\x12P\n" + + "\vBestOptions\x12\x1e.grpcplugin.BestOptionsRequest\x1a\x1f.grpcplugin.BestOptionsResponse\"\x00B\x1cZ\x1aexpander/grpcplugin/protosb\x06proto3" + var ( - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescOnce sync.Once - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescData = file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDesc + file_expander_grpcplugin_protos_expander_proto_rawDescOnce sync.Once + file_expander_grpcplugin_protos_expander_proto_rawDescData []byte ) -func file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescGZIP() []byte { - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescOnce.Do(func() { - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescData = protoimpl.X.CompressGZIP(file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescData) +func file_expander_grpcplugin_protos_expander_proto_rawDescGZIP() []byte { + file_expander_grpcplugin_protos_expander_proto_rawDescOnce.Do(func() { + file_expander_grpcplugin_protos_expander_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_expander_grpcplugin_protos_expander_proto_rawDesc), len(file_expander_grpcplugin_protos_expander_proto_rawDesc))) }) - return file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDescData + return file_expander_grpcplugin_protos_expander_proto_rawDescData } -var file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_goTypes = []interface{}{ +var file_expander_grpcplugin_protos_expander_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_expander_grpcplugin_protos_expander_proto_goTypes = []any{ (*BestOptionsRequest)(nil), // 0: grpcplugin.BestOptionsRequest (*BestOptionsResponse)(nil), // 1: grpcplugin.BestOptionsResponse (*Option)(nil), // 2: grpcplugin.Option nil, // 3: grpcplugin.BestOptionsRequest.NodeMapEntry - (*v1.Pod)(nil), // 4: k8s.io.api.core.v1.Pod - (*v1.Node)(nil), // 5: k8s.io.api.core.v1.Node + nil, // 4: grpcplugin.BestOptionsRequest.NodeBytesMapEntry + (*v1.Pod)(nil), // 5: k8s.io.api.core.v1.Pod + (*v1.Node)(nil), // 6: k8s.io.api.core.v1.Node } -var file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_depIdxs = []int32{ +var file_expander_grpcplugin_protos_expander_proto_depIdxs = []int32{ 2, // 0: grpcplugin.BestOptionsRequest.options:type_name -> grpcplugin.Option 3, // 1: grpcplugin.BestOptionsRequest.nodeMap:type_name -> grpcplugin.BestOptionsRequest.NodeMapEntry - 2, // 2: grpcplugin.BestOptionsResponse.options:type_name -> grpcplugin.Option - 4, // 3: grpcplugin.Option.pod:type_name -> k8s.io.api.core.v1.Pod - 5, // 4: grpcplugin.BestOptionsRequest.NodeMapEntry.value:type_name -> k8s.io.api.core.v1.Node - 0, // 5: grpcplugin.Expander.BestOptions:input_type -> grpcplugin.BestOptionsRequest - 1, // 6: grpcplugin.Expander.BestOptions:output_type -> grpcplugin.BestOptionsResponse - 6, // [6:7] is the sub-list for method output_type - 5, // [5:6] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_init() } -func file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_init() { - if File_cluster_autoscaler_expander_grpcplugin_protos_expander_proto != nil { + 4, // 2: grpcplugin.BestOptionsRequest.nodeBytesMap:type_name -> grpcplugin.BestOptionsRequest.NodeBytesMapEntry + 2, // 3: grpcplugin.BestOptionsResponse.options:type_name -> grpcplugin.Option + 5, // 4: grpcplugin.Option.pod:type_name -> k8s.io.api.core.v1.Pod + 6, // 5: grpcplugin.BestOptionsRequest.NodeMapEntry.value:type_name -> k8s.io.api.core.v1.Node + 0, // 6: grpcplugin.Expander.BestOptions:input_type -> grpcplugin.BestOptionsRequest + 1, // 7: grpcplugin.Expander.BestOptions:output_type -> grpcplugin.BestOptionsResponse + 7, // [7:8] is the sub-list for method output_type + 6, // [6:7] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_expander_grpcplugin_protos_expander_proto_init() } +func file_expander_grpcplugin_protos_expander_proto_init() { + if File_expander_grpcplugin_protos_expander_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BestOptionsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BestOptionsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Option); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_expander_grpcplugin_protos_expander_proto_rawDesc), len(file_expander_grpcplugin_protos_expander_proto_rawDesc)), NumEnums: 0, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_goTypes, - DependencyIndexes: file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_depIdxs, - MessageInfos: file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_msgTypes, + GoTypes: file_expander_grpcplugin_protos_expander_proto_goTypes, + DependencyIndexes: file_expander_grpcplugin_protos_expander_proto_depIdxs, + MessageInfos: file_expander_grpcplugin_protos_expander_proto_msgTypes, }.Build() - File_cluster_autoscaler_expander_grpcplugin_protos_expander_proto = out.File - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_rawDesc = nil - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_goTypes = nil - file_cluster_autoscaler_expander_grpcplugin_protos_expander_proto_depIdxs = nil -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConnInterface - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 - -// ExpanderClient is the client API for Expander service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type ExpanderClient interface { - BestOptions(ctx context.Context, in *BestOptionsRequest, opts ...grpc.CallOption) (*BestOptionsResponse, error) -} - -type expanderClient struct { - cc grpc.ClientConnInterface -} - -func NewExpanderClient(cc grpc.ClientConnInterface) ExpanderClient { - return &expanderClient{cc} -} - -func (c *expanderClient) BestOptions(ctx context.Context, in *BestOptionsRequest, opts ...grpc.CallOption) (*BestOptionsResponse, error) { - out := new(BestOptionsResponse) - err := c.cc.Invoke(ctx, "/grpcplugin.Expander/BestOptions", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ExpanderServer is the server API for Expander service. -type ExpanderServer interface { - BestOptions(context.Context, *BestOptionsRequest) (*BestOptionsResponse, error) -} - -// UnimplementedExpanderServer can be embedded to have forward compatible implementations. -type UnimplementedExpanderServer struct { -} - -func (*UnimplementedExpanderServer) BestOptions(context.Context, *BestOptionsRequest) (*BestOptionsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method BestOptions not implemented") -} - -func RegisterExpanderServer(s *grpc.Server, srv ExpanderServer) { - s.RegisterService(&_Expander_serviceDesc, srv) -} - -func _Expander_BestOptions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(BestOptionsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ExpanderServer).BestOptions(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/grpcplugin.Expander/BestOptions", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ExpanderServer).BestOptions(ctx, req.(*BestOptionsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Expander_serviceDesc = grpc.ServiceDesc{ - ServiceName: "grpcplugin.Expander", - HandlerType: (*ExpanderServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "BestOptions", - Handler: _Expander_BestOptions_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "cluster-autoscaler/expander/grpcplugin/protos/expander.proto", + File_expander_grpcplugin_protos_expander_proto = out.File + file_expander_grpcplugin_protos_expander_proto_goTypes = nil + file_expander_grpcplugin_protos_expander_proto_depIdxs = nil } diff --git a/cluster-autoscaler/expander/grpcplugin/protos/expander.proto b/cluster-autoscaler/expander/grpcplugin/protos/expander.proto index 5a08e8ff301b..eae0ac1a908f 100644 --- a/cluster-autoscaler/expander/grpcplugin/protos/expander.proto +++ b/cluster-autoscaler/expander/grpcplugin/protos/expander.proto @@ -1,8 +1,24 @@ +/* + Copyright 2021 The Kubernetes Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + syntax = "proto3"; package grpcplugin; import "k8s.io/api/core/v1/generated.proto"; -option go_package = "cluster-autoscaler/expander/grpcplugin/protos"; +option go_package = "expander/grpcplugin/protos"; @@ -16,7 +32,12 @@ service Expander { message BestOptionsRequest { repeated Option options = 1; // key is node id from options - map nodeMap = 2; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and nodeBytesMap. Readers should prefer nodeBytesMap if set. + map nodeMap = 2 [deprecated = true]; + + // key is node id from options. + // values are proto-serialized v1.Node objects. + map nodeBytesMap = 3; } message BestOptionsResponse { repeated Option options = 1; @@ -26,5 +47,10 @@ message Option { string nodeGroupId = 1; int32 nodeCount = 2; string debug = 3; - repeated k8s.io.api.core.v1.Pod pod = 4; + + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and podBytes. Readers should prefer podBytes if set. + repeated k8s.io.api.core.v1.Pod pod = 4 [deprecated = true]; + + // proto-serialized v1.Pod object + repeated bytes podBytes = 5; } diff --git a/cluster-autoscaler/expander/grpcplugin/protos/expander_grpc.pb.go b/cluster-autoscaler/expander/grpcplugin/protos/expander_grpc.pb.go new file mode 100644 index 000000000000..7bfaff4721a6 --- /dev/null +++ b/cluster-autoscaler/expander/grpcplugin/protos/expander_grpc.pb.go @@ -0,0 +1,140 @@ +// +//Copyright 2021 The Kubernetes Authors. +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v6.33.0 +// source: expander/grpcplugin/protos/expander.proto + +package protos + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Expander_BestOptions_FullMethodName = "/grpcplugin.Expander/BestOptions" +) + +// ExpanderClient is the client API for Expander service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// Interface for Expander +type ExpanderClient interface { + BestOptions(ctx context.Context, in *BestOptionsRequest, opts ...grpc.CallOption) (*BestOptionsResponse, error) +} + +type expanderClient struct { + cc grpc.ClientConnInterface +} + +func NewExpanderClient(cc grpc.ClientConnInterface) ExpanderClient { + return &expanderClient{cc} +} + +func (c *expanderClient) BestOptions(ctx context.Context, in *BestOptionsRequest, opts ...grpc.CallOption) (*BestOptionsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BestOptionsResponse) + err := c.cc.Invoke(ctx, Expander_BestOptions_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ExpanderServer is the server API for Expander service. +// All implementations must embed UnimplementedExpanderServer +// for forward compatibility. +// +// Interface for Expander +type ExpanderServer interface { + BestOptions(context.Context, *BestOptionsRequest) (*BestOptionsResponse, error) + mustEmbedUnimplementedExpanderServer() +} + +// UnimplementedExpanderServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedExpanderServer struct{} + +func (UnimplementedExpanderServer) BestOptions(context.Context, *BestOptionsRequest) (*BestOptionsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BestOptions not implemented") +} +func (UnimplementedExpanderServer) mustEmbedUnimplementedExpanderServer() {} +func (UnimplementedExpanderServer) testEmbeddedByValue() {} + +// UnsafeExpanderServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ExpanderServer will +// result in compilation errors. +type UnsafeExpanderServer interface { + mustEmbedUnimplementedExpanderServer() +} + +func RegisterExpanderServer(s grpc.ServiceRegistrar, srv ExpanderServer) { + // If the following call pancis, it indicates UnimplementedExpanderServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Expander_ServiceDesc, srv) +} + +func _Expander_BestOptions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BestOptionsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExpanderServer).BestOptions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Expander_BestOptions_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExpanderServer).BestOptions(ctx, req.(*BestOptionsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Expander_ServiceDesc is the grpc.ServiceDesc for Expander service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Expander_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "grpcplugin.Expander", + HandlerType: (*ExpanderServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "BestOptions", + Handler: _Expander_BestOptions_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "expander/grpcplugin/protos/expander.proto", +} diff --git a/cluster-autoscaler/expander/grpcplugin/protos/round_trip_test.go b/cluster-autoscaler/expander/grpcplugin/protos/round_trip_test.go new file mode 100644 index 000000000000..810c5f13fca7 --- /dev/null +++ b/cluster-autoscaler/expander/grpcplugin/protos/round_trip_test.go @@ -0,0 +1,164 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package protos + +import ( + "testing" + + "github.com/golang/protobuf/proto" + "github.com/google/go-cmp/cmp" + + corev1 "k8s.io/api/core/v1" + apiequality "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestRoundTripBestOptionsRequest(t *testing.T) { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "test"}, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "test", + Image: "test", + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + "cpu": resource.MustParse("1"), + "memory": resource.MustParse("1Gi"), + }, + }, + }}, + }, + } + podBytes, err := pod.Marshal() + if err != nil { + t.Fatal(err) + } + + node := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "test"}, + Spec: corev1.NodeSpec{}, + Status: corev1.NodeStatus{ + Capacity: corev1.ResourceList{ + "cpu": resource.MustParse("1"), + "memory": resource.MustParse("1Gi"), + }, + }, + } + nodeBytes, err := node.Marshal() + if err != nil { + t.Fatal(err) + } + + r := &BestOptionsRequest{ + Options: []*Option{{ + // This field is expected to stop being serializable in 1.35, and to need to be removed from the .proto file + Pod: []*corev1.Pod{pod}, + // This field should remain serializable + PodBytes: [][]byte{podBytes}, + }}, + // This field is expected to stop being serializable in 1.35, and to need to be removed from the .proto file + NodeMap: map[string]*corev1.Node{"node": node}, + // This field should remain serializable + NodeBytesMap: map[string][]byte{"node": nodeBytes}, + } + data, err := proto.Marshal(r) + if err != nil { + t.Fatal(err) + } + + r2 := &BestOptionsRequest{} + if err := proto.Unmarshal(data, r2); err != nil { + t.Fatal(err) + } + + pod2 := &corev1.Pod{} + if err := pod2.Unmarshal(r2.Options[0].PodBytes[0]); err != nil { + t.Fatal(err) + } + if !proto.Equal(r, r2) { + t.Fatalf("message did not round-trip: %s", cmp.Diff(r, r2)) + } + // The Pod field is expected to be removed in 1.35 + if !apiequality.Semantic.DeepEqual(pod, r2.Options[0].Pod[0]) { + t.Fatalf("pod did not round-trip: %s", cmp.Diff(r, r2)) + } + // Pod bytes must remain round-trippable + if !apiequality.Semantic.DeepEqual(pod, pod2) { + t.Fatalf("pod bytes did not round-trip: %s", cmp.Diff(r, r2)) + } + + node2 := &corev1.Node{} + if err := node2.Unmarshal(r2.NodeBytesMap["node"]); err != nil { + t.Fatal(err) + } + if !proto.Equal(r, r2) { + t.Fatalf("message did not round-trip: %s", cmp.Diff(r, r2)) + } + // The NodeMap field is expected to be removed in 1.35 + if !apiequality.Semantic.DeepEqual(node, r2.NodeMap["node"]) { + t.Fatalf("pod did not round-trip: %s", cmp.Diff(r, r2)) + } + // Node bytes must remain round-trippable + if !apiequality.Semantic.DeepEqual(node, node2) { + t.Fatalf("pod bytes did not round-trip: %s", cmp.Diff(r, r2)) + } +} + +func TestRoundTripBestOptionsResponse(t *testing.T) { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "test"}, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "test", + Image: "test", + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + "cpu": resource.MustParse("1"), + "memory": resource.MustParse("1Gi"), + }, + }, + }}, + }, + } + podBytes, err := pod.Marshal() + if err != nil { + t.Fatal(err) + } + + r := &BestOptionsResponse{ + Options: []*Option{{ + // This field is expected to stop being serializable in 1.35, and to need to be removed from the .proto file + Pod: []*corev1.Pod{pod}, + // This field should remain serializable + PodBytes: [][]byte{podBytes}, + }}, + } + data, err := proto.Marshal(r) + if err != nil { + t.Fatal(err) + } + + r2 := &BestOptionsResponse{} + if err := proto.Unmarshal(data, r2); err != nil { + t.Fatal(err) + } + + if !proto.Equal(r, r2) { + t.Fatalf("message did not round-trip: %s", cmp.Diff(r, r2)) + } +} diff --git a/cluster-autoscaler/go.mod b/cluster-autoscaler/go.mod index 5a58f093c4a4..c10c6434de8b 100644 --- a/cluster-autoscaler/go.mod +++ b/cluster-autoscaler/go.mod @@ -20,6 +20,7 @@ require ( github.com/digitalocean/godo v1.27.0 github.com/gofrs/uuid v4.4.0+incompatible github.com/golang/mock v1.6.0 + github.com/golang/protobuf v1.5.4 github.com/google/go-cmp v0.7.0 github.com/google/go-querystring v1.0.0 github.com/google/uuid v1.6.0 @@ -126,7 +127,6 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/cadvisor v0.52.1 // indirect github.com/google/cel-go v0.26.0 // indirect diff --git a/cluster-autoscaler/hack/genproto/.gitignore b/cluster-autoscaler/hack/genproto/.gitignore new file mode 100644 index 000000000000..d3763f636391 --- /dev/null +++ b/cluster-autoscaler/hack/genproto/.gitignore @@ -0,0 +1,2 @@ +vendor +protobuf diff --git a/cluster-autoscaler/hack/genproto/go.mod b/cluster-autoscaler/hack/genproto/go.mod new file mode 100644 index 000000000000..ce71a2e7fce7 --- /dev/null +++ b/cluster-autoscaler/hack/genproto/go.mod @@ -0,0 +1,34 @@ +module k8s.io/autoscaler/cluster-autoscaler/genproto + +go 1.25.3 + +tool ( + google.golang.org/grpc/cmd/protoc-gen-go-grpc + google.golang.org/protobuf/cmd/protoc-gen-go + k8s.io/api/core/v1 + k8s.io/apimachinery/pkg/apis/meta/v1 +) + +require ( + github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/x448/float16 v0.8.4 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/text v0.23.0 // indirect + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect + google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + k8s.io/api v0.34.1 // indirect + k8s.io/apimachinery v0.34.1 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect +) diff --git a/cluster-autoscaler/hack/genproto/go.sum b/cluster-autoscaler/hack/genproto/go.sum new file mode 100644 index 000000000000..9499a122f6fc --- /dev/null +++ b/cluster-autoscaler/hack/genproto/go.sum @@ -0,0 +1,105 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= +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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= +k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= +k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= +k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/cluster-autoscaler/hack/update-proto.sh b/cluster-autoscaler/hack/update-proto.sh new file mode 100755 index 000000000000..c6c0094a87c7 --- /dev/null +++ b/cluster-autoscaler/hack/update-proto.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash + +# Copyright 2025 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# canonicalize the path +CLUSTER_AUTOSCALER_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P) + +# directory where protoc releases are unpacked +protoc_dir="${CLUSTER_AUTOSCALER_ROOT}/hack/genproto/protobuf" +# ensure this directory contains bin/protoc and include/... +protoc_bin_dir="${protoc_dir}/bin" +protoc_include_dir="${protoc_dir}/include" +if [[ ! -f "${protoc_bin_dir}/protoc" || ! -d "${protoc_include_dir}" ]]; then + protoc_version="33.0" + case "$(uname -om)" in + x86_64*Linux) + protoc_url="https://github.com/protocolbuffers/protobuf/releases/download/v${protoc_version}/protoc-${protoc_version}-linux-x86_64.zip" + ;; + i?86_64*Linux) + protoc_url="https://github.com/protocolbuffers/protobuf/releases/download/v${protoc_version}/protoc-${protoc_version}-linux-x86_64.zip" + ;; + amd64*Linux) + protoc_url="https://github.com/protocolbuffers/protobuf/releases/download/v${protoc_version}/protoc-${protoc_version}-linux-x86_64.zip" + ;; + aarch64*Linux) + protoc_url="https://github.com/protocolbuffers/protobuf/releases/download/v${protoc_version}/protoc-${protoc_version}-linux-aarch_64.zip" + ;; + arm64*Linux) + protoc_url="https://github.com/protocolbuffers/protobuf/releases/download/v${protoc_version}/protoc-${protoc_version}-linux-aarch_64.zip" + ;; + *Darwin) + protoc_url="https://github.com/protocolbuffers/protobuf/releases/download/v${protoc_version}/protoc-${protoc_version}-osx-universal_binary.zip" + ;; + *) + echo "Unsupported host os/arch. Must be Darwin, or x86_64/arm64 Linux." >&2 + exit 1 + ;; + esac + echo "Downloading ${protoc_url} to ${protoc_dir}" + mkdir -p "${protoc_dir}" + curl -s -L "${protoc_url}" -o "${protoc_dir}/protoc.zip" + unzip -q "${protoc_dir}/protoc.zip" -d "${protoc_dir}" +fi + +# Build protoc-gen-go and protoc-gen-go-grpc into bin directory +pushd "${CLUSTER_AUTOSCALER_ROOT}/hack/genproto" >/dev/null + go mod tidy + go mod vendor + GOBIN="${protoc_bin_dir}" go install google.golang.org/protobuf/cmd/protoc-gen-go + GOBIN="${protoc_bin_dir}" go install google.golang.org/grpc/cmd/protoc-gen-go-grpc +popd >/dev/null + +pushd "${CLUSTER_AUTOSCALER_ROOT}" >/dev/null + +PATH="${protoc_bin_dir}" "${protoc_bin_dir}/protoc" \ + -I . \ + -I ./hack/genproto/vendor \ + -I "${protoc_include_dir}" \ + --go_out=. \ + --go-grpc_out=. \ + ./cloudprovider/externalgrpc/protos/externalgrpc.proto + +PATH="${protoc_bin_dir}" "${protoc_bin_dir}/protoc" \ + -I . \ + -I ./hack/genproto/vendor \ + -I "${protoc_include_dir}" \ + --go_out=. \ + --go-grpc_out=. \ + ./expander/grpcplugin/protos/expander.proto + +popd >/dev/null + +rm -fr "${CLUSTER_AUTOSCALER_ROOT}/hack/genproto/vendor" diff --git a/hack/boilerplate/boilerplate.py b/hack/boilerplate/boilerplate.py index 3736a8328b64..d948338eb05c 100755 --- a/hack/boilerplate/boilerplate.py +++ b/hack/boilerplate/boilerplate.py @@ -148,6 +148,7 @@ def file_extension(filename): skipped_dirs = ['Godeps', 'third_party', '_gopath', '_output', '.git', 'cluster/env.sh', "vendor", "test/e2e/generated/bindata.go", "hack/boilerplate/test", "pkg/generated/bindata.go", + "cluster-autoscaler/expander/grpcplugin/protos", "cluster-autoscaler/cloudprovider/aws/aws-sdk-go", "cluster-autoscaler/cloudprovider/huaweicloud/huaweicloud-sdk-go-v3", "cluster-autoscaler/cloudprovider/bizflycloud/gobizfly",