diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index a4607e42..0cf65e41 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -24,6 +24,8 @@ bases: # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. # - ../prometheus +- ../scaler + patchesStrategicMerge: # Protect the /metrics endpoint by putting it behind auth. # If you want your controller-manager to expose the /metrics diff --git a/config/scaler/kustomization.yaml b/config/scaler/kustomization.yaml new file mode 100644 index 00000000..b2d57759 --- /dev/null +++ b/config/scaler/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - service.yaml diff --git a/config/scaler/service.yaml b/config/scaler/service.yaml new file mode 100644 index 00000000..fc7602d5 --- /dev/null +++ b/config/scaler/service.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: external-scaler + namespace: kruise-game-system +spec: + ports: + - port: 6000 + targetPort: 6000 + selector: + control-plane: controller-manager \ No newline at end of file diff --git a/docs/en/user_manuals/autoscale.md b/docs/en/user_manuals/autoscale.md new file mode 100644 index 00000000..7e969a10 --- /dev/null +++ b/docs/en/user_manuals/autoscale.md @@ -0,0 +1,99 @@ +## Feature overview + +Compared to stateless service types, game servers have higher requirements for automatic scaling, especially in terms of scaling down. + +The differences between game servers become more and more obvious over time, and the precision requirements for scaling down are extremely high. Coarse-grained scaling mechanisms can easily cause negative effects such as player disconnections, resulting in huge losses for the business. + +The horizontal scaling mechanism in native Kubernetes is shown in the following figure: + +![autoscaling-k8s-en.png](../../images/autoscaling-k8s-en.png) + +In the game scenario, its main problems are: + +- At the pod level, it is unable to perceive the game server game status and therefore cannot set deletion priority based on game status. +- At the workload level, it cannot select scaling-down objects based on game status. +- At the autoscaler level, it cannot accurately calculate the appropriate number of replicas based on the game server game status. + +In this way, the automatic scaling mechanism based on native Kubernetes will cause two major problems in the game scenario: + +- The number of scaling down is not accurate. It is easy to delete too many or too few game servers. +- The scaling-down object is not accurate. It is easy to delete game servers with high game load levels. + + +The automatic scaling mechanism of OKG is shown in the following figure: + +![autoscaling-okg-en.png](../../images/autoscaling-okg-en.png) + +- At the game server level, each game server can report its own status and expose whether it is in the WaitToBeDeleted state through custom service quality or external components. +- At the workload level, the GameServerSet can determine the scaling-down object based on the business status reported by the game server. As described in Game Server Horizontal Scaling, the game server in the WaitToBeDeleted state is the highest priority game server to be deleted during scaling down. +- At the autoscaler level, accurately calculate the number of game servers in the WaitToBeDeleted state, and use it as the scaling-down quantity to avoid accidental deletion. + +In this way, OKG's automatic scaler will only delete game servers in the WaitToBeDeleted state during the scaling-down window, achieving targeted and precise scaling down. + +## Usage Example + +_**Prerequisites: Install [KEDA](https://keda.sh/docs/2.10/deploy/) in the cluster.**_ + +Deploy the ScaledObject object to set the automatic scaling strategy. Refer to the [ScaledObject API](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledobject_types.go) for the specific field meanings. + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: minecraft # Fill in the name of the corresponding GameServerSet +spec: + scaleTargetRef: + name: minecraft # Fill in the name of the corresponding GameServerSet + apiVersion: game.kruise.io/v1alpha1 + kind: GameServerSet + pollingInterval: 30 + minReplicaCount: 0 + advanced: + horizontalPodAutoscalerConfig: + behavior: # Inherit from HPA behavior, refer to https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior + scaleDown: + stabilizationWindowSeconds: 45 # Set the scaling-down stabilization window time to 45 seconds + policies: + - type: Percent + value: 100 + periodSeconds: 15 + triggers: + - type: external + metricType: Value + metadata: + scalerAddress: kruise-game-external-scaler.kruise-game-system:6000 + +``` + +After deployment, change the opsState of the gs minecraft-0 to WaitToBeDeleted (see [Custom Service Quality](service_qualities.md) for automated setting of game server status). + +```bash +kubectl edit gs minecraft-0 + +... +spec: + deletionPriority: 0 + opsState: WaitToBeDeleted # Set to None initially, and change it to WaitToBeDeleted + updatePriority: 0 +... + +``` + +After the scaling-down window period, the game server minecraft-0 is automatically deleted. + +```bash +kubectl get gs +NAME STATE OPSSTATE DP UP +minecraft-0 Deleting WaitToBeDeleted 0 0 +minecraft-1 Ready None 0 0 +minecraft-2 Ready None 0 0 + +# After a while +... + +kubectl get gs +NAME STATE OPSSTATE DP UP +minecraft-1 Ready None 0 0 +minecraft-2 Ready None 0 0 + +``` \ No newline at end of file diff --git a/docs/images/autoscaling-k8s-en.png b/docs/images/autoscaling-k8s-en.png new file mode 100644 index 00000000..797d9b9f Binary files /dev/null and b/docs/images/autoscaling-k8s-en.png differ diff --git a/docs/images/autoscaling-k8s.png b/docs/images/autoscaling-k8s.png new file mode 100644 index 00000000..3b159403 Binary files /dev/null and b/docs/images/autoscaling-k8s.png differ diff --git a/docs/images/autoscaling-okg-en.png b/docs/images/autoscaling-okg-en.png new file mode 100644 index 00000000..936d389c Binary files /dev/null and b/docs/images/autoscaling-okg-en.png differ diff --git a/docs/images/autoscaling-okg.png b/docs/images/autoscaling-okg.png new file mode 100644 index 00000000..7359944a Binary files /dev/null and b/docs/images/autoscaling-okg.png differ diff --git "a/docs/\344\270\255\346\226\207/\347\224\250\346\210\267\346\211\213\345\206\214/\350\207\252\345\212\250\344\274\270\347\274\251.md" "b/docs/\344\270\255\346\226\207/\347\224\250\346\210\267\346\211\213\345\206\214/\350\207\252\345\212\250\344\274\270\347\274\251.md" new file mode 100644 index 00000000..8beef924 --- /dev/null +++ "b/docs/\344\270\255\346\226\207/\347\224\250\346\210\267\346\211\213\345\206\214/\350\207\252\345\212\250\344\274\270\347\274\251.md" @@ -0,0 +1,94 @@ +## 功能概览 + +游戏服与无状态业务类型不同,对于自动伸缩特性有着更高的要求,其要求主要体现在缩容方面。 + +由于游戏为强有状态业务,随着时间的推移,游戏服之间的差异性愈加明显,缩容的精确度要求极高,粗糙的缩容机制容易造成玩家断线等负面影响,给业务造成巨大损失。 + +原生Kubernetes中的水平伸缩机制如下图所示 + +![autoscaling-k8s.png](../../images/autoscaling-k8s.png) + +在游戏场景下,它的主要问题在于: + +- 在pod层面,无法感知游戏服业务状态,进而无法通过业务状态设置删除优先级 +- 在workload层面,无法根据业务状态选择缩容对象 +- 在autoscaler层面,无法定向感知游戏服业务状态计算合适的副本数目 + +这样一来,基于原生Kubernetes的自动伸缩机制将在游戏场景下造成两大问题: + +- 缩容数目不精确。容易删除过多或过少的游戏服。 +- 缩容对象不精确。容易删除业务负载水平高的游戏服。 + +OKG 的自动伸缩机制如下所示 + +![autoscaling-okg.png](../../images/autoscaling-okg.png) + +- 在游戏服层面,每个游戏服可以上报自身状态,通过自定义服务质量或外部组件来暴露自身是否为WaitToBeDeleted状态。 +- 在workload层面,GameServerSet可根据游戏服上报的业务状态来决定缩容的对象,如[游戏服水平伸缩](../快速开始/游戏服水平伸缩.md)中所述,WaitToBeDeleted的游戏服是删除优先级最高的游戏服,缩容时最优先删除。 +- 在autoscaler层面,精准计算WaitToBeDeleted的游戏服个数,将其作为缩容数量,不会造成误删的情况。 + +如此一来,OKG的自动伸缩器在缩容窗口期内只会删除处于WaitToBeDeleted状态的游戏服,真正做到定向缩容、精准缩容。 + +## 使用示例 + +_**前置条件:在集群中安装 [KEDA](https://keda.sh/docs/2.10/deploy/)**_ + +部署ScaledObject对象来设置自动伸缩策略,具体字段含义可参考 [ScaledObject API](https://github.com/kedacore/keda/blob/main/apis/keda/v1alpha1/scaledobject_types.go) + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: minecraft #填写对应GameServerSet的名称 +spec: + scaleTargetRef: + name: minecraft #填写对应GameServerSet的名称 + apiVersion: game.kruise.io/v1alpha1 + kind: GameServerSet + pollingInterval: 30 + minReplicaCount: 0 + advanced: + horizontalPodAutoscalerConfig: + behavior: #继承HPA策略,可参考文档 https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior + scaleDown: + stabilizationWindowSeconds: 45 #设置缩容稳定窗口时间为45秒 + policies: + - type: Percent + value: 100 + periodSeconds: 15 + triggers: + - type: external + metricType: Value + metadata: + scalerAddress: kruise-game-external-scaler.kruise-game-system:6000 +``` + +部署完成后,更改gs minecraft-0 的 opsState 为 WaitToBeDeleted(可参考[自定义服务质量](自定义服务质量.md)实现自动化设置游戏服状态) + +```bash +kubectl edit gs minecraft-0 + +... +spec: + deletionPriority: 0 + opsState: WaitToBeDeleted #初始为None, 将其改为WaitToBeDeleted + updatePriority: 0 +... +``` + +经过缩容窗口期后,游戏服minecraft-0自动被删除 +```bash +kubectl get gs +NAME STATE OPSSTATE DP UP +minecraft-0 Deleting WaitToBeDeleted 0 0 +minecraft-1 Ready None 0 0 +minecraft-2 Ready None 0 0 + +# After a while +... + +kubectl get gs +NAME STATE OPSSTATE DP UP +minecraft-1 Ready None 0 0 +minecraft-2 Ready None 0 0 +``` \ No newline at end of file diff --git a/go.mod b/go.mod index ab020a7d..10a3e4bb 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,8 @@ require ( github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.18.1 github.com/openkruise/kruise-api v1.3.0 + google.golang.org/grpc v1.40.0 + google.golang.org/protobuf v1.27.1 k8s.io/api v0.24.0 k8s.io/apimachinery v0.24.0 k8s.io/client-go v0.24.0 @@ -75,7 +77,7 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.27.1 // indirect + google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index cb89074f..01490df3 100644 --- a/go.sum +++ b/go.sum @@ -865,6 +865,7 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 h1:Et6SkiuvnBn+SgrSYXs/BrUpGB4mbdwt4R3vaPIlicA= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -887,6 +888,7 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/main.go b/main.go index cc90921a..3b7f1aec 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,10 @@ import ( "github.com/openkruise/kruise-game/cloudprovider" cpmanager "github.com/openkruise/kruise-game/cloudprovider/manager" controller "github.com/openkruise/kruise-game/pkg/controllers" + "github.com/openkruise/kruise-game/pkg/externalscaler" "github.com/openkruise/kruise-game/pkg/webhook" + "google.golang.org/grpc" + "net" "os" "time" @@ -66,6 +69,7 @@ func main() { var probeAddr string var namespace string var syncPeriodStr string + var scaleServerAddr string flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8082", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, @@ -74,6 +78,7 @@ func main() { flag.StringVar(&namespace, "namespace", "", "Namespace if specified restricts the manager's cache to watch objects in the desired namespace. Defaults to all namespaces.") flag.StringVar(&syncPeriodStr, "sync-period", "", "Determines the minimum frequency at which watched resources are reconciled.") + flag.StringVar(&scaleServerAddr, "scale-server-bind-address", ":6000", "The address the scale server endpoint binds to.") // Add cloud provider flags cloudprovider.InitCloudProviderFlags() @@ -164,6 +169,17 @@ func main() { } }() + externalScaler := externalscaler.NewExternalScaler(mgr.GetClient()) + go func() { + grpcServer := grpc.NewServer() + lis, _ := net.Listen("tcp", scaleServerAddr) + externalscaler.RegisterExternalScalerServer(grpcServer, externalScaler) + if err := grpcServer.Serve(lis); err != nil { + setupLog.Error(err, "unable to setup ExternalScalerServer") + os.Exit(1) + } + }() + setupLog.Info("starting kruise-game-manager") if err := mgr.Start(signal); err != nil { diff --git a/pkg/externalscaler/externalscaler.go b/pkg/externalscaler/externalscaler.go new file mode 100644 index 00000000..e904cac1 --- /dev/null +++ b/pkg/externalscaler/externalscaler.go @@ -0,0 +1,75 @@ +package externalscaler + +import ( + "context" + "fmt" + gamekruiseiov1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type ExternalScaler struct { + client client.Client +} + +func (e *ExternalScaler) mustEmbedUnimplementedExternalScalerServer() { +} + +func (e *ExternalScaler) IsActive(ctx context.Context, scaledObject *ScaledObjectRef) (*IsActiveResponse, error) { + return &IsActiveResponse{ + Result: true, + }, nil +} + +func (e *ExternalScaler) StreamIsActive(scaledObject *ScaledObjectRef, epsServer ExternalScaler_StreamIsActiveServer) error { + return nil +} + +func (e *ExternalScaler) GetMetricSpec(ctx context.Context, scaledObjectRef *ScaledObjectRef) (*GetMetricSpecResponse, error) { + name := scaledObjectRef.GetName() + ns := scaledObjectRef.GetNamespace() + gss := &gamekruiseiov1alpha1.GameServerSet{} + err := e.client.Get(ctx, types.NamespacedName{Namespace: ns, Name: name}, gss) + if err != nil { + klog.Error(err) + return nil, err + } + desireReplicas := gss.Spec.Replicas + klog.Infof("GameServerSet %s/%s TargetSize is %d", ns, name, *desireReplicas) + return &GetMetricSpecResponse{ + MetricSpecs: []*MetricSpec{{ + MetricName: "gssReplicas", + TargetSize: int64(*desireReplicas), + }}, + }, nil +} + +func (e *ExternalScaler) GetMetrics(ctx context.Context, metricRequest *GetMetricsRequest) (*GetMetricsResponse, error) { + name := metricRequest.ScaledObjectRef.GetName() + ns := metricRequest.ScaledObjectRef.GetNamespace() + gss := &gamekruiseiov1alpha1.GameServerSet{} + err := e.client.Get(ctx, types.NamespacedName{Namespace: ns, Name: name}, gss) + if err != nil { + klog.Error(err) + return nil, err + } + currentReplicas := gss.Status.CurrentReplicas + numWaitToBeDeleted := gss.Status.WaitToBeDeletedReplicas + if numWaitToBeDeleted == nil || currentReplicas == 0 { + return nil, fmt.Errorf("GameServerSet %s/%s has not inited", ns, name) + } + klog.Infof("GameServerSet %s/%s desire replicas is %d", ns, name, currentReplicas-*numWaitToBeDeleted) + return &GetMetricsResponse{ + MetricValues: []*MetricValue{{ + MetricName: "gssReplicas", + MetricValue: int64(currentReplicas - *numWaitToBeDeleted), + }}, + }, nil +} + +func NewExternalScaler(client client.Client) *ExternalScaler { + return &ExternalScaler{ + client: client, + } +} diff --git a/pkg/externalscaler/externalscaler.pb.go b/pkg/externalscaler/externalscaler.pb.go new file mode 100644 index 00000000..a955cc4e --- /dev/null +++ b/pkg/externalscaler/externalscaler.pb.go @@ -0,0 +1,622 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v4.22.0--rc2 +// source: externalscaler.proto + +package externalscaler + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ScaledObjectRef struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + ScalerMetadata map[string]string `protobuf:"bytes,3,rep,name=scalerMetadata,proto3" json:"scalerMetadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ScaledObjectRef) Reset() { + *x = ScaledObjectRef{} + if protoimpl.UnsafeEnabled { + mi := &file_externalscaler_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ScaledObjectRef) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScaledObjectRef) ProtoMessage() {} + +func (x *ScaledObjectRef) ProtoReflect() protoreflect.Message { + mi := &file_externalscaler_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ScaledObjectRef.ProtoReflect.Descriptor instead. +func (*ScaledObjectRef) Descriptor() ([]byte, []int) { + return file_externalscaler_proto_rawDescGZIP(), []int{0} +} + +func (x *ScaledObjectRef) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ScaledObjectRef) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *ScaledObjectRef) GetScalerMetadata() map[string]string { + if x != nil { + return x.ScalerMetadata + } + return nil +} + +type IsActiveResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result bool `protobuf:"varint,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (x *IsActiveResponse) Reset() { + *x = IsActiveResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_externalscaler_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IsActiveResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IsActiveResponse) ProtoMessage() {} + +func (x *IsActiveResponse) ProtoReflect() protoreflect.Message { + mi := &file_externalscaler_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IsActiveResponse.ProtoReflect.Descriptor instead. +func (*IsActiveResponse) Descriptor() ([]byte, []int) { + return file_externalscaler_proto_rawDescGZIP(), []int{1} +} + +func (x *IsActiveResponse) GetResult() bool { + if x != nil { + return x.Result + } + return false +} + +type GetMetricSpecResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MetricSpecs []*MetricSpec `protobuf:"bytes,1,rep,name=metricSpecs,proto3" json:"metricSpecs,omitempty"` +} + +func (x *GetMetricSpecResponse) Reset() { + *x = GetMetricSpecResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_externalscaler_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetMetricSpecResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMetricSpecResponse) ProtoMessage() {} + +func (x *GetMetricSpecResponse) ProtoReflect() protoreflect.Message { + mi := &file_externalscaler_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMetricSpecResponse.ProtoReflect.Descriptor instead. +func (*GetMetricSpecResponse) Descriptor() ([]byte, []int) { + return file_externalscaler_proto_rawDescGZIP(), []int{2} +} + +func (x *GetMetricSpecResponse) GetMetricSpecs() []*MetricSpec { + if x != nil { + return x.MetricSpecs + } + return nil +} + +type MetricSpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MetricName string `protobuf:"bytes,1,opt,name=metricName,proto3" json:"metricName,omitempty"` + TargetSize int64 `protobuf:"varint,2,opt,name=targetSize,proto3" json:"targetSize,omitempty"` +} + +func (x *MetricSpec) Reset() { + *x = MetricSpec{} + if protoimpl.UnsafeEnabled { + mi := &file_externalscaler_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricSpec) ProtoMessage() {} + +func (x *MetricSpec) ProtoReflect() protoreflect.Message { + mi := &file_externalscaler_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricSpec.ProtoReflect.Descriptor instead. +func (*MetricSpec) Descriptor() ([]byte, []int) { + return file_externalscaler_proto_rawDescGZIP(), []int{3} +} + +func (x *MetricSpec) GetMetricName() string { + if x != nil { + return x.MetricName + } + return "" +} + +func (x *MetricSpec) GetTargetSize() int64 { + if x != nil { + return x.TargetSize + } + return 0 +} + +type GetMetricsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ScaledObjectRef *ScaledObjectRef `protobuf:"bytes,1,opt,name=scaledObjectRef,proto3" json:"scaledObjectRef,omitempty"` + MetricName string `protobuf:"bytes,2,opt,name=metricName,proto3" json:"metricName,omitempty"` +} + +func (x *GetMetricsRequest) Reset() { + *x = GetMetricsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_externalscaler_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetMetricsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMetricsRequest) ProtoMessage() {} + +func (x *GetMetricsRequest) ProtoReflect() protoreflect.Message { + mi := &file_externalscaler_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMetricsRequest.ProtoReflect.Descriptor instead. +func (*GetMetricsRequest) Descriptor() ([]byte, []int) { + return file_externalscaler_proto_rawDescGZIP(), []int{4} +} + +func (x *GetMetricsRequest) GetScaledObjectRef() *ScaledObjectRef { + if x != nil { + return x.ScaledObjectRef + } + return nil +} + +func (x *GetMetricsRequest) GetMetricName() string { + if x != nil { + return x.MetricName + } + return "" +} + +type GetMetricsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MetricValues []*MetricValue `protobuf:"bytes,1,rep,name=metricValues,proto3" json:"metricValues,omitempty"` +} + +func (x *GetMetricsResponse) Reset() { + *x = GetMetricsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_externalscaler_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetMetricsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMetricsResponse) ProtoMessage() {} + +func (x *GetMetricsResponse) ProtoReflect() protoreflect.Message { + mi := &file_externalscaler_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMetricsResponse.ProtoReflect.Descriptor instead. +func (*GetMetricsResponse) Descriptor() ([]byte, []int) { + return file_externalscaler_proto_rawDescGZIP(), []int{5} +} + +func (x *GetMetricsResponse) GetMetricValues() []*MetricValue { + if x != nil { + return x.MetricValues + } + return nil +} + +type MetricValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MetricName string `protobuf:"bytes,1,opt,name=metricName,proto3" json:"metricName,omitempty"` + MetricValue int64 `protobuf:"varint,2,opt,name=metricValue,proto3" json:"metricValue,omitempty"` +} + +func (x *MetricValue) Reset() { + *x = MetricValue{} + if protoimpl.UnsafeEnabled { + mi := &file_externalscaler_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetricValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetricValue) ProtoMessage() {} + +func (x *MetricValue) ProtoReflect() protoreflect.Message { + mi := &file_externalscaler_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetricValue.ProtoReflect.Descriptor instead. +func (*MetricValue) Descriptor() ([]byte, []int) { + return file_externalscaler_proto_rawDescGZIP(), []int{6} +} + +func (x *MetricValue) GetMetricName() string { + if x != nil { + return x.MetricName + } + return "" +} + +func (x *MetricValue) GetMetricValue() int64 { + if x != nil { + return x.MetricValue + } + return 0 +} + +var File_externalscaler_proto protoreflect.FileDescriptor + +var file_externalscaler_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x22, 0xe3, 0x01, 0x0a, 0x0f, 0x53, 0x63, 0x61, 0x6c, 0x65, + 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0e, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x66, 0x2e, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x41, 0x0a, 0x13, 0x53, 0x63, 0x61, + 0x6c, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x2a, 0x0a, 0x10, + 0x49, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x55, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x70, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3c, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x70, 0x65, 0x63, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x70, + 0x65, 0x63, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x70, 0x65, 0x63, 0x73, 0x22, + 0x4c, 0x0a, 0x0a, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1e, 0x0a, + 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, + 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x7e, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x49, 0x0a, 0x0f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x61, + 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x52, 0x0f, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x12, 0x1e, 0x0a, + 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x55, 0x0a, + 0x12, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x22, 0x4f, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x32, 0xec, 0x02, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x08, 0x49, 0x73, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x12, 0x1f, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x66, 0x1a, 0x20, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x49, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0e, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x49, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x1f, 0x2e, 0x65, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x61, + 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x1a, 0x20, 0x2e, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x49, 0x73, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x59, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, + 0x70, 0x65, 0x63, 0x12, 0x1f, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x66, 0x1a, 0x25, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x53, + 0x70, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, + 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21, 0x2e, 0x65, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x2e, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x2e, + 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x42, 0x12, 0x5a, 0x10, 0x2e, 0x3b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_externalscaler_proto_rawDescOnce sync.Once + file_externalscaler_proto_rawDescData = file_externalscaler_proto_rawDesc +) + +func file_externalscaler_proto_rawDescGZIP() []byte { + file_externalscaler_proto_rawDescOnce.Do(func() { + file_externalscaler_proto_rawDescData = protoimpl.X.CompressGZIP(file_externalscaler_proto_rawDescData) + }) + return file_externalscaler_proto_rawDescData +} + +var file_externalscaler_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_externalscaler_proto_goTypes = []interface{}{ + (*ScaledObjectRef)(nil), // 0: externalscaler.ScaledObjectRef + (*IsActiveResponse)(nil), // 1: externalscaler.IsActiveResponse + (*GetMetricSpecResponse)(nil), // 2: externalscaler.GetMetricSpecResponse + (*MetricSpec)(nil), // 3: externalscaler.MetricSpec + (*GetMetricsRequest)(nil), // 4: externalscaler.GetMetricsRequest + (*GetMetricsResponse)(nil), // 5: externalscaler.GetMetricsResponse + (*MetricValue)(nil), // 6: externalscaler.MetricValue + nil, // 7: externalscaler.ScaledObjectRef.ScalerMetadataEntry +} +var file_externalscaler_proto_depIdxs = []int32{ + 7, // 0: externalscaler.ScaledObjectRef.scalerMetadata:type_name -> externalscaler.ScaledObjectRef.ScalerMetadataEntry + 3, // 1: externalscaler.GetMetricSpecResponse.metricSpecs:type_name -> externalscaler.MetricSpec + 0, // 2: externalscaler.GetMetricsRequest.scaledObjectRef:type_name -> externalscaler.ScaledObjectRef + 6, // 3: externalscaler.GetMetricsResponse.metricValues:type_name -> externalscaler.MetricValue + 0, // 4: externalscaler.ExternalScaler.IsActive:input_type -> externalscaler.ScaledObjectRef + 0, // 5: externalscaler.ExternalScaler.StreamIsActive:input_type -> externalscaler.ScaledObjectRef + 0, // 6: externalscaler.ExternalScaler.GetMetricSpec:input_type -> externalscaler.ScaledObjectRef + 4, // 7: externalscaler.ExternalScaler.GetMetrics:input_type -> externalscaler.GetMetricsRequest + 1, // 8: externalscaler.ExternalScaler.IsActive:output_type -> externalscaler.IsActiveResponse + 1, // 9: externalscaler.ExternalScaler.StreamIsActive:output_type -> externalscaler.IsActiveResponse + 2, // 10: externalscaler.ExternalScaler.GetMetricSpec:output_type -> externalscaler.GetMetricSpecResponse + 5, // 11: externalscaler.ExternalScaler.GetMetrics:output_type -> externalscaler.GetMetricsResponse + 8, // [8:12] is the sub-list for method output_type + 4, // [4:8] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_externalscaler_proto_init() } +func file_externalscaler_proto_init() { + if File_externalscaler_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_externalscaler_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ScaledObjectRef); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_externalscaler_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IsActiveResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_externalscaler_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetMetricSpecResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_externalscaler_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricSpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_externalscaler_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetMetricsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_externalscaler_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetMetricsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_externalscaler_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricValue); 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_externalscaler_proto_rawDesc, + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_externalscaler_proto_goTypes, + DependencyIndexes: file_externalscaler_proto_depIdxs, + MessageInfos: file_externalscaler_proto_msgTypes, + }.Build() + File_externalscaler_proto = out.File + file_externalscaler_proto_rawDesc = nil + file_externalscaler_proto_goTypes = nil + file_externalscaler_proto_depIdxs = nil +} diff --git a/pkg/externalscaler/externalscaler_grpc.pb.go b/pkg/externalscaler/externalscaler_grpc.pb.go new file mode 100644 index 00000000..b753ac26 --- /dev/null +++ b/pkg/externalscaler/externalscaler_grpc.pb.go @@ -0,0 +1,241 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.22.0--rc2 +// source: externalscaler.proto + +package externalscaler + +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.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// ExternalScalerClient is the client API for ExternalScaler 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. +type ExternalScalerClient interface { + IsActive(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*IsActiveResponse, error) + StreamIsActive(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (ExternalScaler_StreamIsActiveClient, error) + GetMetricSpec(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*GetMetricSpecResponse, error) + GetMetrics(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*GetMetricsResponse, error) +} + +type externalScalerClient struct { + cc grpc.ClientConnInterface +} + +func NewExternalScalerClient(cc grpc.ClientConnInterface) ExternalScalerClient { + return &externalScalerClient{cc} +} + +func (c *externalScalerClient) IsActive(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*IsActiveResponse, error) { + out := new(IsActiveResponse) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/IsActive", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *externalScalerClient) StreamIsActive(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (ExternalScaler_StreamIsActiveClient, error) { + stream, err := c.cc.NewStream(ctx, &ExternalScaler_ServiceDesc.Streams[0], "/externalscaler.ExternalScaler/StreamIsActive", opts...) + if err != nil { + return nil, err + } + x := &externalScalerStreamIsActiveClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ExternalScaler_StreamIsActiveClient interface { + Recv() (*IsActiveResponse, error) + grpc.ClientStream +} + +type externalScalerStreamIsActiveClient struct { + grpc.ClientStream +} + +func (x *externalScalerStreamIsActiveClient) Recv() (*IsActiveResponse, error) { + m := new(IsActiveResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *externalScalerClient) GetMetricSpec(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*GetMetricSpecResponse, error) { + out := new(GetMetricSpecResponse) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/GetMetricSpec", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *externalScalerClient) GetMetrics(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*GetMetricsResponse, error) { + out := new(GetMetricsResponse) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/GetMetrics", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ExternalScalerServer is the server API for ExternalScaler service. +// All implementations must embed UnimplementedExternalScalerServer +// for forward compatibility +type ExternalScalerServer interface { + IsActive(context.Context, *ScaledObjectRef) (*IsActiveResponse, error) + StreamIsActive(*ScaledObjectRef, ExternalScaler_StreamIsActiveServer) error + GetMetricSpec(context.Context, *ScaledObjectRef) (*GetMetricSpecResponse, error) + GetMetrics(context.Context, *GetMetricsRequest) (*GetMetricsResponse, error) + mustEmbedUnimplementedExternalScalerServer() +} + +// UnimplementedExternalScalerServer must be embedded to have forward compatible implementations. +type UnimplementedExternalScalerServer struct { +} + +func (UnimplementedExternalScalerServer) IsActive(context.Context, *ScaledObjectRef) (*IsActiveResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method IsActive not implemented") +} +func (UnimplementedExternalScalerServer) StreamIsActive(*ScaledObjectRef, ExternalScaler_StreamIsActiveServer) error { + return status.Errorf(codes.Unimplemented, "method StreamIsActive not implemented") +} +func (UnimplementedExternalScalerServer) GetMetricSpec(context.Context, *ScaledObjectRef) (*GetMetricSpecResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMetricSpec not implemented") +} +func (UnimplementedExternalScalerServer) GetMetrics(context.Context, *GetMetricsRequest) (*GetMetricsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMetrics not implemented") +} +func (UnimplementedExternalScalerServer) mustEmbedUnimplementedExternalScalerServer() {} + +// UnsafeExternalScalerServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ExternalScalerServer will +// result in compilation errors. +type UnsafeExternalScalerServer interface { + mustEmbedUnimplementedExternalScalerServer() +} + +func RegisterExternalScalerServer(s grpc.ServiceRegistrar, srv ExternalScalerServer) { + s.RegisterService(&ExternalScaler_ServiceDesc, srv) +} + +func _ExternalScaler_IsActive_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ScaledObjectRef) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).IsActive(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/IsActive", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).IsActive(ctx, req.(*ScaledObjectRef)) + } + return interceptor(ctx, in, info, handler) +} + +func _ExternalScaler_StreamIsActive_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ScaledObjectRef) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ExternalScalerServer).StreamIsActive(m, &externalScalerStreamIsActiveServer{stream}) +} + +type ExternalScaler_StreamIsActiveServer interface { + Send(*IsActiveResponse) error + grpc.ServerStream +} + +type externalScalerStreamIsActiveServer struct { + grpc.ServerStream +} + +func (x *externalScalerStreamIsActiveServer) Send(m *IsActiveResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _ExternalScaler_GetMetricSpec_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ScaledObjectRef) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).GetMetricSpec(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/GetMetricSpec", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).GetMetricSpec(ctx, req.(*ScaledObjectRef)) + } + return interceptor(ctx, in, info, handler) +} + +func _ExternalScaler_GetMetrics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetMetricsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).GetMetrics(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/GetMetrics", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).GetMetrics(ctx, req.(*GetMetricsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ExternalScaler_ServiceDesc is the grpc.ServiceDesc for ExternalScaler service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ExternalScaler_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "externalscaler.ExternalScaler", + HandlerType: (*ExternalScalerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "IsActive", + Handler: _ExternalScaler_IsActive_Handler, + }, + { + MethodName: "GetMetricSpec", + Handler: _ExternalScaler_GetMetricSpec_Handler, + }, + { + MethodName: "GetMetrics", + Handler: _ExternalScaler_GetMetrics_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamIsActive", + Handler: _ExternalScaler_StreamIsActive_Handler, + ServerStreams: true, + }, + }, + Metadata: "externalscaler.proto", +} diff --git a/proto/externalscaler/externalscaler.proto b/proto/externalscaler/externalscaler.proto new file mode 100644 index 00000000..939f7158 --- /dev/null +++ b/proto/externalscaler/externalscaler.proto @@ -0,0 +1,44 @@ +syntax = "proto3"; + +package externalscaler; +option go_package = ".;externalscaler"; + +service ExternalScaler { + rpc IsActive(ScaledObjectRef) returns (IsActiveResponse) {} + rpc StreamIsActive(ScaledObjectRef) returns (stream IsActiveResponse) {} + rpc GetMetricSpec(ScaledObjectRef) returns (GetMetricSpecResponse) {} + rpc GetMetrics(GetMetricsRequest) returns (GetMetricsResponse) {} +} + +message ScaledObjectRef { + string name = 1; + string namespace = 2; + map scalerMetadata = 3; +} + +message IsActiveResponse { + bool result = 1; +} + +message GetMetricSpecResponse { + repeated MetricSpec metricSpecs = 1; +} + +message MetricSpec { + string metricName = 1; + int64 targetSize = 2; +} + +message GetMetricsRequest { + ScaledObjectRef scaledObjectRef = 1; + string metricName = 2; +} + +message GetMetricsResponse { + repeated MetricValue metricValues = 1; +} + +message MetricValue { + string metricName = 1; + int64 metricValue = 2; +} \ No newline at end of file