This is an automated email from the ASF dual-hosted git repository.

sunnianjun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shardingsphere-on-cloud.git


The following commit(s) were added to refs/heads/main by this push:
     new fdb8283  feta(operator,hpa): add support for Custom Metric for HPA. 
(#112)
fdb8283 is described below

commit fdb8283a7a1df37600724f39f03faeadd414b604
Author: pierce <[email protected]>
AuthorDate: Thu Nov 24 17:54:00 2022 +0800

    feta(operator,hpa): add support for Custom Metric for HPA. (#112)
    
    * feta(operator,hpa): add support for Custom Metric for HPA.
    
    Signed-off-by: xuanyuan300 <[email protected]>
    
    * chore(license): add license to crd yaml
    
    Signed-off-by: xuanyuan300 <[email protected]>
    
    Signed-off-by: xuanyuan300 <[email protected]>
---
 ...ingsphere.apache.org_shardingsphereproxies.yaml | 490 ++++++++++++++++++++-
 ...pache.org_shardingsphereproxyserverconfigs.yaml |   8 +-
 .../api/v1alpha1/proxy_types.go                    |   7 +-
 .../api/v1alpha1/zz_generated.deepcopy.go          |  10 +-
 .../pkg/reconcile/reconcile_test.go                | 148 +++++++
 shardingsphere-operator/pkg/reconcile/resource.go  |  41 +-
 6 files changed, 674 insertions(+), 30 deletions(-)

diff --git 
a/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxies.yaml
 
b/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxies.yaml
index 0592270..01a235e 100644
--- 
a/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxies.yaml
+++ 
b/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxies.yaml
@@ -20,7 +20,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.8.0
+    controller-gen.kubebuilder.io/version: v0.9.0
   creationTimestamp: null
   name: shardingsphereproxies.shardingsphere.apache.org
 spec:
@@ -62,6 +62,488 @@ spec:
               automaticScaling:
                 description: AutomaticScaling HPA configuration
                 properties:
+                  customMetrics:
+                    items:
+                      description: MetricSpec specifies how to scale based on 
a single
+                        metric (only `type` and one other matching field 
should be
+                        set at once).
+                      properties:
+                        containerResource:
+                          description: container resource refers to a resource 
metric
+                            (such as those specified in requests and limits) 
known
+                            to Kubernetes describing a single container in 
each pod
+                            of the current scale target (e.g. CPU or memory). 
Such
+                            metrics are built in to Kubernetes, and have 
special scaling
+                            options on top of those available to normal 
per-pod metrics
+                            using the "pods" source. This is an alpha feature 
and
+                            can be enabled by the HPAContainerMetrics feature 
flag.
+                          properties:
+                            container:
+                              description: container is the name of the 
container
+                                in the pods of the scaling target
+                              type: string
+                            name:
+                              description: name is the name of the resource in 
question.
+                              type: string
+                            target:
+                              description: target specifies the target value 
for the
+                                given metric
+                              properties:
+                                averageUtilization:
+                                  description: averageUtilization is the 
target value
+                                    of the average of the resource metric 
across all
+                                    relevant pods, represented as a percentage 
of
+                                    the requested value of the resource for 
the pods.
+                                    Currently only valid for Resource metric 
source
+                                    type
+                                  format: int32
+                                  type: integer
+                                averageValue:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: averageValue is the target 
value of
+                                    the average of the metric across all 
relevant
+                                    pods (as a quantity)
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                type:
+                                  description: type represents whether the 
metric
+                                    type is Utilization, Value, or AverageValue
+                                  type: string
+                                value:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: value is the target value of 
the metric
+                                    (as a quantity).
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                              required:
+                              - type
+                              type: object
+                          required:
+                          - container
+                          - name
+                          - target
+                          type: object
+                        external:
+                          description: external refers to a global metric that 
is
+                            not associated with any Kubernetes object. It 
allows autoscaling
+                            based on information coming from components 
running outside
+                            of cluster (for example length of queue in cloud 
messaging
+                            service, or QPS from loadbalancer running outside 
of cluster).
+                          properties:
+                            metric:
+                              description: metric identifies the target metric 
by
+                                name and selector
+                              properties:
+                                name:
+                                  description: name is the name of the given 
metric
+                                  type: string
+                                selector:
+                                  description: selector is the string-encoded 
form
+                                    of a standard kubernetes label selector 
for the
+                                    given metric When set, it is passed as an 
additional
+                                    parameter to the metrics server for more 
specific
+                                    metrics scoping. When unset, just the 
metricName
+                                    will be used to gather metrics.
+                                  properties:
+                                    matchExpressions:
+                                      description: matchExpressions is a list 
of label
+                                        selector requirements. The 
requirements are
+                                        ANDed.
+                                      items:
+                                        description: A label selector 
requirement
+                                          is a selector that contains values, 
a key,
+                                          and an operator that relates the key 
and
+                                          values.
+                                        properties:
+                                          key:
+                                            description: key is the label key 
that
+                                              the selector applies to.
+                                            type: string
+                                          operator:
+                                            description: operator represents a 
key's
+                                              relationship to a set of values. 
Valid
+                                              operators are In, NotIn, Exists 
and
+                                              DoesNotExist.
+                                            type: string
+                                          values:
+                                            description: values is an array of 
string
+                                              values. If the operator is In or 
NotIn,
+                                              the values array must be 
non-empty.
+                                              If the operator is Exists or 
DoesNotExist,
+                                              the values array must be empty. 
This
+                                              array is replaced during a 
strategic
+                                              merge patch.
+                                            items:
+                                              type: string
+                                            type: array
+                                        required:
+                                        - key
+                                        - operator
+                                        type: object
+                                      type: array
+                                    matchLabels:
+                                      additionalProperties:
+                                        type: string
+                                      description: matchLabels is a map of 
{key,value}
+                                        pairs. A single {key,value} in the 
matchLabels
+                                        map is equivalent to an element of 
matchExpressions,
+                                        whose key field is "key", the operator 
is
+                                        "In", and the values array contains 
only "value".
+                                        The requirements are ANDed.
+                                      type: object
+                                  type: object
+                              required:
+                              - name
+                              type: object
+                            target:
+                              description: target specifies the target value 
for the
+                                given metric
+                              properties:
+                                averageUtilization:
+                                  description: averageUtilization is the 
target value
+                                    of the average of the resource metric 
across all
+                                    relevant pods, represented as a percentage 
of
+                                    the requested value of the resource for 
the pods.
+                                    Currently only valid for Resource metric 
source
+                                    type
+                                  format: int32
+                                  type: integer
+                                averageValue:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: averageValue is the target 
value of
+                                    the average of the metric across all 
relevant
+                                    pods (as a quantity)
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                type:
+                                  description: type represents whether the 
metric
+                                    type is Utilization, Value, or AverageValue
+                                  type: string
+                                value:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: value is the target value of 
the metric
+                                    (as a quantity).
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                              required:
+                              - type
+                              type: object
+                          required:
+                          - metric
+                          - target
+                          type: object
+                        object:
+                          description: object refers to a metric describing a 
single
+                            kubernetes object (for example, hits-per-second on 
an
+                            Ingress object).
+                          properties:
+                            describedObject:
+                              description: CrossVersionObjectReference 
contains enough
+                                information to let you identify the referred 
resource.
+                              properties:
+                                apiVersion:
+                                  description: API version of the referent
+                                  type: string
+                                kind:
+                                  description: 'Kind of the referent; More 
info: 
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds";'
+                                  type: string
+                                name:
+                                  description: 'Name of the referent; More 
info: http://kubernetes.io/docs/user-guide/identifiers#names'
+                                  type: string
+                              required:
+                              - kind
+                              - name
+                              type: object
+                            metric:
+                              description: metric identifies the target metric 
by
+                                name and selector
+                              properties:
+                                name:
+                                  description: name is the name of the given 
metric
+                                  type: string
+                                selector:
+                                  description: selector is the string-encoded 
form
+                                    of a standard kubernetes label selector 
for the
+                                    given metric When set, it is passed as an 
additional
+                                    parameter to the metrics server for more 
specific
+                                    metrics scoping. When unset, just the 
metricName
+                                    will be used to gather metrics.
+                                  properties:
+                                    matchExpressions:
+                                      description: matchExpressions is a list 
of label
+                                        selector requirements. The 
requirements are
+                                        ANDed.
+                                      items:
+                                        description: A label selector 
requirement
+                                          is a selector that contains values, 
a key,
+                                          and an operator that relates the key 
and
+                                          values.
+                                        properties:
+                                          key:
+                                            description: key is the label key 
that
+                                              the selector applies to.
+                                            type: string
+                                          operator:
+                                            description: operator represents a 
key's
+                                              relationship to a set of values. 
Valid
+                                              operators are In, NotIn, Exists 
and
+                                              DoesNotExist.
+                                            type: string
+                                          values:
+                                            description: values is an array of 
string
+                                              values. If the operator is In or 
NotIn,
+                                              the values array must be 
non-empty.
+                                              If the operator is Exists or 
DoesNotExist,
+                                              the values array must be empty. 
This
+                                              array is replaced during a 
strategic
+                                              merge patch.
+                                            items:
+                                              type: string
+                                            type: array
+                                        required:
+                                        - key
+                                        - operator
+                                        type: object
+                                      type: array
+                                    matchLabels:
+                                      additionalProperties:
+                                        type: string
+                                      description: matchLabels is a map of 
{key,value}
+                                        pairs. A single {key,value} in the 
matchLabels
+                                        map is equivalent to an element of 
matchExpressions,
+                                        whose key field is "key", the operator 
is
+                                        "In", and the values array contains 
only "value".
+                                        The requirements are ANDed.
+                                      type: object
+                                  type: object
+                              required:
+                              - name
+                              type: object
+                            target:
+                              description: target specifies the target value 
for the
+                                given metric
+                              properties:
+                                averageUtilization:
+                                  description: averageUtilization is the 
target value
+                                    of the average of the resource metric 
across all
+                                    relevant pods, represented as a percentage 
of
+                                    the requested value of the resource for 
the pods.
+                                    Currently only valid for Resource metric 
source
+                                    type
+                                  format: int32
+                                  type: integer
+                                averageValue:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: averageValue is the target 
value of
+                                    the average of the metric across all 
relevant
+                                    pods (as a quantity)
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                type:
+                                  description: type represents whether the 
metric
+                                    type is Utilization, Value, or AverageValue
+                                  type: string
+                                value:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: value is the target value of 
the metric
+                                    (as a quantity).
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                              required:
+                              - type
+                              type: object
+                          required:
+                          - describedObject
+                          - metric
+                          - target
+                          type: object
+                        pods:
+                          description: pods refers to a metric describing each 
pod
+                            in the current scale target (for example, 
transactions-processed-per-second).  The
+                            values will be averaged together before being 
compared
+                            to the target value.
+                          properties:
+                            metric:
+                              description: metric identifies the target metric 
by
+                                name and selector
+                              properties:
+                                name:
+                                  description: name is the name of the given 
metric
+                                  type: string
+                                selector:
+                                  description: selector is the string-encoded 
form
+                                    of a standard kubernetes label selector 
for the
+                                    given metric When set, it is passed as an 
additional
+                                    parameter to the metrics server for more 
specific
+                                    metrics scoping. When unset, just the 
metricName
+                                    will be used to gather metrics.
+                                  properties:
+                                    matchExpressions:
+                                      description: matchExpressions is a list 
of label
+                                        selector requirements. The 
requirements are
+                                        ANDed.
+                                      items:
+                                        description: A label selector 
requirement
+                                          is a selector that contains values, 
a key,
+                                          and an operator that relates the key 
and
+                                          values.
+                                        properties:
+                                          key:
+                                            description: key is the label key 
that
+                                              the selector applies to.
+                                            type: string
+                                          operator:
+                                            description: operator represents a 
key's
+                                              relationship to a set of values. 
Valid
+                                              operators are In, NotIn, Exists 
and
+                                              DoesNotExist.
+                                            type: string
+                                          values:
+                                            description: values is an array of 
string
+                                              values. If the operator is In or 
NotIn,
+                                              the values array must be 
non-empty.
+                                              If the operator is Exists or 
DoesNotExist,
+                                              the values array must be empty. 
This
+                                              array is replaced during a 
strategic
+                                              merge patch.
+                                            items:
+                                              type: string
+                                            type: array
+                                        required:
+                                        - key
+                                        - operator
+                                        type: object
+                                      type: array
+                                    matchLabels:
+                                      additionalProperties:
+                                        type: string
+                                      description: matchLabels is a map of 
{key,value}
+                                        pairs. A single {key,value} in the 
matchLabels
+                                        map is equivalent to an element of 
matchExpressions,
+                                        whose key field is "key", the operator 
is
+                                        "In", and the values array contains 
only "value".
+                                        The requirements are ANDed.
+                                      type: object
+                                  type: object
+                              required:
+                              - name
+                              type: object
+                            target:
+                              description: target specifies the target value 
for the
+                                given metric
+                              properties:
+                                averageUtilization:
+                                  description: averageUtilization is the 
target value
+                                    of the average of the resource metric 
across all
+                                    relevant pods, represented as a percentage 
of
+                                    the requested value of the resource for 
the pods.
+                                    Currently only valid for Resource metric 
source
+                                    type
+                                  format: int32
+                                  type: integer
+                                averageValue:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: averageValue is the target 
value of
+                                    the average of the metric across all 
relevant
+                                    pods (as a quantity)
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                type:
+                                  description: type represents whether the 
metric
+                                    type is Utilization, Value, or AverageValue
+                                  type: string
+                                value:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: value is the target value of 
the metric
+                                    (as a quantity).
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                              required:
+                              - type
+                              type: object
+                          required:
+                          - metric
+                          - target
+                          type: object
+                        resource:
+                          description: resource refers to a resource metric 
(such
+                            as those specified in requests and limits) known 
to Kubernetes
+                            describing each pod in the current scale target 
(e.g.
+                            CPU or memory). Such metrics are built in to 
Kubernetes,
+                            and have special scaling options on top of those 
available
+                            to normal per-pod metrics using the "pods" source.
+                          properties:
+                            name:
+                              description: name is the name of the resource in 
question.
+                              type: string
+                            target:
+                              description: target specifies the target value 
for the
+                                given metric
+                              properties:
+                                averageUtilization:
+                                  description: averageUtilization is the 
target value
+                                    of the average of the resource metric 
across all
+                                    relevant pods, represented as a percentage 
of
+                                    the requested value of the resource for 
the pods.
+                                    Currently only valid for Resource metric 
source
+                                    type
+                                  format: int32
+                                  type: integer
+                                averageValue:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: averageValue is the target 
value of
+                                    the average of the metric across all 
relevant
+                                    pods (as a quantity)
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                type:
+                                  description: type represents whether the 
metric
+                                    type is Utilization, Value, or AverageValue
+                                  type: string
+                                value:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  description: value is the target value of 
the metric
+                                    (as a quantity).
+                                  pattern: 
^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                              required:
+                              - type
+                              type: object
+                          required:
+                          - name
+                          - target
+                          type: object
+                        type:
+                          description: 'type is the type of metric source.  It 
should
+                            be one of "ContainerResource", "External", 
"Object", "Pods"
+                            or "Resource", each mapping to a matching field in 
the
+                            object. Note: "ContainerResource" type is 
available on
+                            when the feature-gate HPAContainerMetrics is 
enabled'
+                          type: string
+                      required:
+                      - type
+                      type: object
+                    type: array
                   enable:
                     type: boolean
                   maxInstance:
@@ -656,9 +1138,3 @@ spec:
     storage: true
     subresources:
       status: {}
-status:
-  acceptedNames:
-    kind: ""
-    plural: ""
-  conditions: []
-  storedVersions: []
diff --git 
a/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxyserverconfigs.yaml
 
b/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxyserverconfigs.yaml
index 1b18874..bebd4b6 100644
--- 
a/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxyserverconfigs.yaml
+++ 
b/charts/apache-shardingsphere-operator-charts/crds/shardingsphere.apache.org_shardingsphereproxyserverconfigs.yaml
@@ -20,7 +20,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.8.0
+    controller-gen.kubebuilder.io/version: v0.9.0
   creationTimestamp: null
   name: shardingsphereproxyserverconfigs.shardingsphere.apache.org
 spec:
@@ -205,9 +205,3 @@ spec:
     storage: true
     subresources:
       status: {}
-status:
-  acceptedNames:
-    kind: ""
-    plural: ""
-  conditions: []
-  storedVersions: []
diff --git a/shardingsphere-operator/api/v1alpha1/proxy_types.go 
b/shardingsphere-operator/api/v1alpha1/proxy_types.go
index 7404370..920e308 100644
--- a/shardingsphere-operator/api/v1alpha1/proxy_types.go
+++ b/shardingsphere-operator/api/v1alpha1/proxy_types.go
@@ -18,6 +18,7 @@
 package v1alpha1
 
 import (
+       autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
        v1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
@@ -25,7 +26,7 @@ import (
 // EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
 // NOTE: json tags are required.  Any new fields you add must have json tags 
for the fields to be serialized.
 
-//ServiceType defines the Service in Kubernetes of ShardingSphere-Proxy
+// ServiceType defines the Service in Kubernetes of ShardingSphere-Proxy
 type ServiceType struct {
        // 
+kubebuilder:validation:Enum=ClusterIP;NodePort;LoadBalancer;ExternalName
 
@@ -45,7 +46,7 @@ type ServiceType struct {
        NodePort int32 `json:"nodePort"`
 }
 
-//MySQLDriver Defines the mysql-driven version in ShardingSphere-proxy
+// MySQLDriver Defines the mysql-driven version in ShardingSphere-proxy
 type MySQLDriver struct {
        // 
+kubebuilder:validation:Pattern=`^([1-9]\d|[1-9])(\.([1-9]\d|\d)){2}$`
        // mysql-driven version,must be x.y.z
@@ -66,6 +67,8 @@ type AutomaticScaling struct {
        MaxInstance int32 `json:"maxInstance,omitempty"`
        // +optional
        MinInstance int32 `json:"minInstance,omitempty"`
+       // +optional
+       CustomMetrics []autoscalingv2beta2.MetricSpec 
`json:"customMetrics,omitempty"`
 }
 
 // ProxySpec defines the desired state of ShardingSphereProxy
diff --git a/shardingsphere-operator/api/v1alpha1/zz_generated.deepcopy.go 
b/shardingsphere-operator/api/v1alpha1/zz_generated.deepcopy.go
index e50a798..06c0e31 100644
--- a/shardingsphere-operator/api/v1alpha1/zz_generated.deepcopy.go
+++ b/shardingsphere-operator/api/v1alpha1/zz_generated.deepcopy.go
@@ -22,6 +22,7 @@ limitations under the License.
 package v1alpha1
 
 import (
+       "k8s.io/api/autoscaling/v2beta2"
        "k8s.io/api/core/v1"
        "k8s.io/apimachinery/pkg/runtime"
 )
@@ -54,6 +55,13 @@ func (in *Auth) DeepCopy() *Auth {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *AutomaticScaling) DeepCopyInto(out *AutomaticScaling) {
        *out = *in
+       if in.CustomMetrics != nil {
+               in, out := &in.CustomMetrics, &out.CustomMetrics
+               *out = make([]v2beta2.MetricSpec, len(*in))
+               for i := range *in {
+                       (*in)[i].DeepCopyInto(&(*out)[i])
+               }
+       }
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new AutomaticScaling.
@@ -223,7 +231,7 @@ func (in *ProxySpec) DeepCopyInto(out *ProxySpec) {
        if in.AutomaticScaling != nil {
                in, out := &in.AutomaticScaling, &out.AutomaticScaling
                *out = new(AutomaticScaling)
-               **out = **in
+               (*in).DeepCopyInto(*out)
        }
        if in.ImagePullSecrets != nil {
                in, out := &in.ImagePullSecrets, &out.ImagePullSecrets
diff --git a/shardingsphere-operator/pkg/reconcile/reconcile_test.go 
b/shardingsphere-operator/pkg/reconcile/reconcile_test.go
index d4f35ac..ab6dd55 100644
--- a/shardingsphere-operator/pkg/reconcile/reconcile_test.go
+++ b/shardingsphere-operator/pkg/reconcile/reconcile_test.go
@@ -19,6 +19,9 @@ package reconcile
 
 import (
        "fmt"
+       autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
+       "k8s.io/apimachinery/pkg/api/resource"
+       "k8s.io/utils/pointer"
        "strconv"
        "testing"
 
@@ -637,7 +640,152 @@ func Test_UpdateService(t *testing.T) {
 }
 
 func Test_UpdateHPA(t *testing.T) {
+       cases := []struct {
+               proxy   *v1alpha1.ShardingSphereProxy
+               hpa     *autoscalingv2beta2.HorizontalPodAutoscaler
+               message string
+       }{
+               {
+                       proxy: &v1alpha1.ShardingSphereProxy{
+                               Spec: v1alpha1.ProxySpec{
+                                       AutomaticScaling: 
&v1alpha1.AutomaticScaling{
+                                               Enable:           true,
+                                               ScaleUpWindows:   15,
+                                               ScaleDownWindows: 30,
+                                               MaxInstance:      5,
+                                               MinInstance:      3,
+                                               Target:           70,
+                                       },
+                               },
+                       },
+                       hpa: &autoscalingv2beta2.HorizontalPodAutoscaler{
+                               Spec: 
autoscalingv2beta2.HorizontalPodAutoscalerSpec{
+                                       ScaleTargetRef: 
autoscalingv2beta2.CrossVersionObjectReference{
+                                               Kind:       "Deployment",
+                                               Name:       "test",
+                                               APIVersion: 
appsv1.SchemeGroupVersion.String(),
+                                       },
+                                       MinReplicas: pointer.Int32(3),
+                                       MaxReplicas: 10,
+                                       Metrics: 
[]autoscalingv2beta2.MetricSpec{
+                                               {
+                                                       Type: 
autoscalingv2beta2.ResourceMetricSourceType,
+                                                       Resource: 
&autoscalingv2beta2.ResourceMetricSource{
+                                                               Name: "cpu",
+                                                               Target: 
autoscalingv2beta2.MetricTarget{
+                                                                       Type:   
            autoscalingv2beta2.UtilizationMetricType,
+                                                                       
AverageUtilization: pointer.Int32(60),
+                                                               },
+                                                       },
+                                               },
+                                       },
+                                       Behavior: 
&autoscalingv2beta2.HorizontalPodAutoscalerBehavior{
+                                               ScaleUp: 
&autoscalingv2beta2.HPAScalingRules{
+                                                       
StabilizationWindowSeconds: pointer.Int32(15),
+                                               },
+                                               ScaleDown: 
&autoscalingv2beta2.HPAScalingRules{
+                                                       
StabilizationWindowSeconds: pointer.Int32(60),
+                                                       Policies: 
[]autoscalingv2beta2.HPAScalingPolicy{
+                                                               {
+                                                                       Type:   
       autoscalingv2beta2.PodsScalingPolicy,
+                                                                       Value:  
       1,
+                                                                       
PeriodSeconds: 30,
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       message: "hpa should be updated",
+               },
+       }
+
+       for _, c := range cases {
+               UpdateHPA(c.proxy, c.hpa)
+               assert.Equal(t, c.proxy.Spec.AutomaticScaling.Target, 
*c.hpa.Spec.Metrics[0].Resource.Target.AverageUtilization)
+               assert.Equal(t, c.proxy.Spec.AutomaticScaling.ScaleDownWindows, 
*c.hpa.Spec.Behavior.ScaleDown.StabilizationWindowSeconds)
+       }
+}
 
+func Test_UpdateHPAMetric(t *testing.T) {
+       cases := []struct {
+               proxy   *v1alpha1.ShardingSphereProxy
+               hpa     *autoscalingv2beta2.HorizontalPodAutoscaler
+               message string
+       }{
+               {
+                       proxy: &v1alpha1.ShardingSphereProxy{
+                               Spec: v1alpha1.ProxySpec{
+                                       AutomaticScaling: 
&v1alpha1.AutomaticScaling{
+                                               Enable:           true,
+                                               ScaleUpWindows:   15,
+                                               ScaleDownWindows: 30,
+                                               MaxInstance:      5,
+                                               MinInstance:      3,
+                                               Target:           70,
+                                               CustomMetrics: 
[]autoscalingv2beta2.MetricSpec{
+                                                       {
+                                                               Type: "pods",
+                                                               Pods: 
&autoscalingv2beta2.PodsMetricSource{
+                                                                       Metric: 
autoscalingv2beta2.MetricIdentifier{
+                                                                               
Name: "latency_seconds_test_avg",
+                                                                       },
+                                                                       Target: 
autoscalingv2beta2.MetricTarget{
+                                                                               
Type:         autoscalingv2beta2.AverageValueMetricType,
+                                                                               
AverageValue: resource.NewQuantity(12, resource.DecimalSI),
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       hpa: &autoscalingv2beta2.HorizontalPodAutoscaler{
+                               Spec: 
autoscalingv2beta2.HorizontalPodAutoscalerSpec{
+                                       ScaleTargetRef: 
autoscalingv2beta2.CrossVersionObjectReference{
+                                               Kind:       "Deployment",
+                                               Name:       "test",
+                                               APIVersion: 
appsv1.SchemeGroupVersion.String(),
+                                       },
+                                       MinReplicas: pointer.Int32(3),
+                                       MaxReplicas: 10,
+                                       Metrics: 
[]autoscalingv2beta2.MetricSpec{
+                                               {
+                                                       Type: 
autoscalingv2beta2.ResourceMetricSourceType,
+                                                       Resource: 
&autoscalingv2beta2.ResourceMetricSource{
+                                                               Name: "cpu",
+                                                               Target: 
autoscalingv2beta2.MetricTarget{
+                                                                       Type:   
            autoscalingv2beta2.UtilizationMetricType,
+                                                                       
AverageUtilization: pointer.Int32(60),
+                                                               },
+                                                       },
+                                               },
+                                       },
+                                       Behavior: 
&autoscalingv2beta2.HorizontalPodAutoscalerBehavior{
+                                               ScaleUp: 
&autoscalingv2beta2.HPAScalingRules{
+                                                       
StabilizationWindowSeconds: pointer.Int32(15),
+                                               },
+                                               ScaleDown: 
&autoscalingv2beta2.HPAScalingRules{
+                                                       
StabilizationWindowSeconds: pointer.Int32(60),
+                                                       Policies: 
[]autoscalingv2beta2.HPAScalingPolicy{
+                                                               {
+                                                                       Type:   
       autoscalingv2beta2.PodsScalingPolicy,
+                                                                       Value:  
       1,
+                                                                       
PeriodSeconds: 30,
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       message: "hpa should be updated",
+               },
+       }
+
+       for _, c := range cases {
+               UpdateHPA(c.proxy, c.hpa)
+               assert.Equal(t, c.proxy.Spec.AutomaticScaling.CustomMetrics, 
c.hpa.Spec.Metrics)
+       }
 }
 
 func Test_fromInt32(t *testing.T) {
diff --git a/shardingsphere-operator/pkg/reconcile/resource.go 
b/shardingsphere-operator/pkg/reconcile/resource.go
index c7d8dd1..66f0be0 100644
--- a/shardingsphere-operator/pkg/reconcile/resource.go
+++ b/shardingsphere-operator/pkg/reconcile/resource.go
@@ -256,6 +256,12 @@ func ConstructCascadingConfigmap(proxyConfig 
*v1alpha1.ShardingSphereProxyServer
 
 // ConstructHPA Create HPA if you need
 func ConstructHPA(proxy *v1alpha1.ShardingSphereProxy) 
*autoscalingv2beta2.HorizontalPodAutoscaler {
+       var metrics = 
ConstructDefaultHPAMetric(&proxy.Spec.AutomaticScaling.Target)
+
+       if len(proxy.Spec.AutomaticScaling.CustomMetrics) > 0 {
+               metrics = proxy.Spec.AutomaticScaling.CustomMetrics
+       }
+
        return &autoscalingv2beta2.HorizontalPodAutoscaler{
                ObjectMeta: metav1.ObjectMeta{
                        Name:      proxy.Name,
@@ -272,18 +278,7 @@ func ConstructHPA(proxy *v1alpha1.ShardingSphereProxy) 
*autoscalingv2beta2.Horiz
                        },
                        MinReplicas: &proxy.Spec.AutomaticScaling.MinInstance,
                        MaxReplicas: proxy.Spec.AutomaticScaling.MaxInstance,
-                       Metrics: []autoscalingv2beta2.MetricSpec{
-                               {
-                                       Type: 
autoscalingv2beta2.ResourceMetricSourceType,
-                                       Resource: 
&autoscalingv2beta2.ResourceMetricSource{
-                                               Name: "cpu",
-                                               Target: 
autoscalingv2beta2.MetricTarget{
-                                                       Type:               
autoscalingv2beta2.UtilizationMetricType,
-                                                       AverageUtilization: 
&proxy.Spec.AutomaticScaling.Target,
-                                               },
-                                       },
-                               },
-                       },
+                       Metrics:     metrics,
                        Behavior: 
&autoscalingv2beta2.HorizontalPodAutoscalerBehavior{
                                ScaleUp: &autoscalingv2beta2.HPAScalingRules{
                                        StabilizationWindowSeconds: 
&proxy.Spec.AutomaticScaling.ScaleUpWindows,
@@ -304,6 +299,21 @@ func ConstructHPA(proxy *v1alpha1.ShardingSphereProxy) 
*autoscalingv2beta2.Horiz
 
 }
 
+func ConstructDefaultHPAMetric(target *int32) []autoscalingv2beta2.MetricSpec {
+       return []autoscalingv2beta2.MetricSpec{
+               {
+                       Type: autoscalingv2beta2.ResourceMetricSourceType,
+                       Resource: &autoscalingv2beta2.ResourceMetricSource{
+                               Name: "cpu",
+                               Target: autoscalingv2beta2.MetricTarget{
+                                       Type:               
autoscalingv2beta2.UtilizationMetricType,
+                                       AverageUtilization: target,
+                               },
+                       },
+               },
+       }
+}
+
 // ToYaml Convert ShardingSphereProxyServerConfig spec content to yaml format
 func toYaml(proxyConfig *v1alpha1.ShardingSphereProxyServerConfig) string {
        y, _ := yaml.Marshal(proxyConfig.Spec)
@@ -339,11 +349,16 @@ func UpdateService(proxy *v1alpha1.ShardingSphereProxy, 
runtimeService *v1.Servi
 }
 
 func UpdateHPA(proxy *v1alpha1.ShardingSphereProxy, runtimeHPA 
*autoscalingv2beta2.HorizontalPodAutoscaler) {
-       runtimeHPA.Spec.Metrics[0].Resource.Target.AverageUtilization = 
&proxy.Spec.AutomaticScaling.Target
        runtimeHPA.Spec.Behavior.ScaleDown.StabilizationWindowSeconds = 
&proxy.Spec.AutomaticScaling.ScaleDownWindows
        runtimeHPA.Spec.Behavior.ScaleUp.StabilizationWindowSeconds = 
&proxy.Spec.AutomaticScaling.ScaleUpWindows
        runtimeHPA.Spec.MaxReplicas = proxy.Spec.AutomaticScaling.MaxInstance
        runtimeHPA.Spec.MinReplicas = &proxy.Spec.AutomaticScaling.MinInstance
+       if len(proxy.Spec.AutomaticScaling.CustomMetrics) > 0 {
+               runtimeHPA.Spec.Metrics = 
proxy.Spec.AutomaticScaling.CustomMetrics
+       } else {
+               // We need to reconstruct the default hpa metric when the user 
deletes the custom metric.
+               runtimeHPA.Spec.Metrics = 
ConstructDefaultHPAMetric(&proxy.Spec.AutomaticScaling.Target)
+       }
 }
 
 func fromInt32(val int32) intstr.IntOrString {


Reply via email to