diff --git a/vertical-pod-autoscaler/e2e/go.sum b/vertical-pod-autoscaler/e2e/go.sum index a76a38ad5912..2ed4c72891d3 100644 --- a/vertical-pod-autoscaler/e2e/go.sum +++ b/vertical-pod-autoscaler/e2e/go.sum @@ -165,6 +165,7 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= +github.com/emicklei/go-restful/v3 v3.5.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= diff --git a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go index 3842bcd71912..aff68d6fe406 100644 --- a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go +++ b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go @@ -119,7 +119,7 @@ type PodUpdatePolicy struct { MinReplicas *int32 `json:"minReplicas,omitempty" protobuf:"varint,2,opt,name=minReplicas"` } -// UpdateMode controls when autoscaler applies changes to the pod resoures. +// UpdateMode controls when autoscaler applies changes to the pod resources. // +kubebuilder:validation:Enum=Off;Initial;Recreate;Auto type UpdateMode string diff --git a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta1/types.go b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta1/types.go index 2cdfb84e2624..37f12e2b7d58 100644 --- a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta1/types.go +++ b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta1/types.go @@ -84,7 +84,7 @@ type PodUpdatePolicy struct { UpdateMode *UpdateMode `json:"updateMode,omitempty" protobuf:"bytes,1,opt,name=updateMode"` } -// UpdateMode controls when autoscaler applies changes to the pod resoures. +// UpdateMode controls when autoscaler applies changes to the pod resources. type UpdateMode string const ( diff --git a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/types.go b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/types.go index ccfc1a1bf6da..de4c0843a575 100644 --- a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/types.go +++ b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/types.go @@ -99,7 +99,7 @@ type PodUpdatePolicy struct { UpdateMode *UpdateMode `json:"updateMode,omitempty" protobuf:"bytes,1,opt,name=updateMode"` } -// UpdateMode controls when autoscaler applies changes to the pod resoures. +// UpdateMode controls when autoscaler applies changes to the pod resources. // +kubebuilder:validation:Enum=Off;Initial;Recreate;Auto type UpdateMode string diff --git a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/poc.autoscaling.k8s.io/v1alpha1/types.go b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/poc.autoscaling.k8s.io/v1alpha1/types.go index 43fc2acefa15..b1d43607b644 100644 --- a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/poc.autoscaling.k8s.io/v1alpha1/types.go +++ b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/poc.autoscaling.k8s.io/v1alpha1/types.go @@ -84,7 +84,7 @@ type PodUpdatePolicy struct { UpdateMode *UpdateMode `json:"updateMode,omitempty" protobuf:"bytes,1,opt,name=updateMode"` } -// UpdateMode controls when autoscaler applies changes to the pod resoures. +// UpdateMode controls when autoscaler applies changes to the pod resources. type UpdateMode string const ( diff --git a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/status/status_object.go b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/status/status_object.go index 4d6df0d164ab..8277db362006 100644 --- a/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/status/status_object.go +++ b/vertical-pod-autoscaler/e2e/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/status/status_object.go @@ -97,7 +97,7 @@ func (c *Client) UpdateStatus() error { return err } lease.Spec.RenewTime = &metav1.MicroTime{Time: time.Now()} - lease.Spec.HolderIdentity = pointer.StringPtr(c.holderIdentity) + lease.Spec.HolderIdentity = pointer.String(c.holderIdentity) _, err = c.client.Update(context.TODO(), lease, metav1.UpdateOptions{}) if apierrors.IsConflict(err) { // Lease was updated by an another replica of the component. @@ -126,8 +126,8 @@ func (c *Client) newLease() *apicoordinationv1.Lease { Namespace: c.leaseNamespace, }, Spec: apicoordinationv1.LeaseSpec{ - HolderIdentity: pointer.StringPtr(c.holderIdentity), - LeaseDurationSeconds: pointer.Int32Ptr(c.leaseDurationSeconds), + HolderIdentity: pointer.String(c.holderIdentity), + LeaseDurationSeconds: pointer.Int32(c.leaseDurationSeconds), }, } } diff --git a/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh b/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh new file mode 100755 index 000000000000..cc85a1ec1276 --- /dev/null +++ b/vertical-pod-autoscaler/hack/deploy-for-e2e-locally.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. + +function print_help { + echo "ERROR! Usage: deploy-for-e2e-locally.sh [suite]*" + echo " should be one of:" + echo " - recommender" + echo " - recommender-externalmetrics" + echo "If component is not specified all above will be started." +} + +if [ $# -eq 0 ]; then + print_help + exit 1 +fi + +if [ $# -gt 1 ]; then + print_help + exit 1 +fi + +SUITE=$1 + +case ${SUITE} in + recommender|recommender-externalmetrics) + COMPONENTS="${SUITE}" + ;; + *) + print_help + exit 1 + ;; +esac + +# Local KIND-hosted registry +export REGISTRY=localhost:5001 +export TAG=latest + +rm -f ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml +patch -c ${SCRIPT_ROOT}/deploy/vpa-rbac.yaml -i ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.diff -o ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml +kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/vpa-rbac.yaml +# Other-versioned CRDs are irrelevant as we're running a modern-ish cluster. +kubectl apply -f ${SCRIPT_ROOT}/deploy/vpa-v1-crd-gen.yaml +kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/k8s-metrics-server.yaml + +for i in ${COMPONENTS}; do + if [ $i == admission-controller ] ; then + (cd ${SCRIPT_ROOT}/pkg/${i} && bash ./gencerts.sh || true) + elif [ $i == recommender-externalmetrics ] ; then + i=recommender + fi + ALL_ARCHITECTURES=amd64 make --directory ${SCRIPT_ROOT}/pkg/${i} release REGISTRY=${REGISTRY} TAG=${TAG} + kind load docker-image ${REGISTRY}/vpa-${i}-amd64:${TAG} +done + + +for i in ${COMPONENTS}; do + if [ $i == recommender-externalmetrics ] ; then + kubectl delete namespace monitoring --ignore-not-found=true + kubectl create namespace monitoring + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/prometheus.yaml + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/prometheus-adapter.yaml + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/metrics-pump.yaml + kubectl apply -f ${SCRIPT_ROOT}/hack/e2e/${i}-deployment.yaml + else + REGISTRY=${REGISTRY} TAG=${TAG} ${SCRIPT_ROOT}/hack/vpa-process-yaml.sh ${SCRIPT_ROOT}/deploy/${i}-deployment.yaml | kubectl apply -f - + fi +done diff --git a/vertical-pod-autoscaler/hack/e2e/Dockerfile.externalmetrics-writer b/vertical-pod-autoscaler/hack/e2e/Dockerfile.externalmetrics-writer new file mode 100644 index 000000000000..5af909d2c459 --- /dev/null +++ b/vertical-pod-autoscaler/hack/e2e/Dockerfile.externalmetrics-writer @@ -0,0 +1,18 @@ +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM python:3.10-slim +RUN pip3 install kubernetes argparse requests + +COPY emit-metrics.py / diff --git a/vertical-pod-autoscaler/hack/e2e/k8s-metrics-server.yaml b/vertical-pod-autoscaler/hack/e2e/k8s-metrics-server.yaml new file mode 100644 index 000000000000..25984da14287 --- /dev/null +++ b/vertical-pod-autoscaler/hack/e2e/k8s-metrics-server.yaml @@ -0,0 +1,244 @@ +--- +# Source: metrics-server/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: local-metrics-server + namespace: default + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +--- +# Source: metrics-server/templates/clusterrole-aggregated-reader.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:metrics-server-aggregated-reader + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-view: "true" +rules: + - apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +--- +# Source: metrics-server/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:local-metrics-server + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +rules: + - apiGroups: + - "" + resources: + - nodes/metrics + verbs: + - get + - apiGroups: + - "" + resources: + - pods + - nodes + - namespaces + - configmaps + verbs: + - get + - list + - watch +--- +# Source: metrics-server/templates/clusterrolebinding-auth-delegator.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: local-metrics-server:system:auth-delegator + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - kind: ServiceAccount + name: local-metrics-server + namespace: default +--- +# Source: metrics-server/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:local-metrics-server + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:local-metrics-server +subjects: + - kind: ServiceAccount + name: local-metrics-server + namespace: default +--- +# Source: metrics-server/templates/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: local-metrics-server-auth-reader + namespace: default + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - kind: ServiceAccount + name: local-metrics-server + namespace: default +--- +# Source: metrics-server/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: local-metrics-server + namespace: default + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +spec: + type: ClusterIP + ports: + - name: https + port: 443 + protocol: TCP + targetPort: https + selector: + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server +--- +# Source: metrics-server/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: local-metrics-server + namespace: default + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + template: + metadata: + labels: + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + spec: + schedulerName: + serviceAccountName: local-metrics-server + priorityClassName: "system-cluster-critical" + containers: + - name: metrics-server + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + image: registry.k8s.io/metrics-server/metrics-server:v0.6.2 + imagePullPolicy: IfNotPresent + args: + - --secure-port=10250 + - --cert-dir=/tmp + - --kubelet-insecure-tls + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --metric-resolution=15s + ports: + - name: https + protocol: TCP + containerPort: 10250 + livenessProbe: + failureThreshold: 3 + httpGet: + path: /livez + port: https + scheme: HTTPS + initialDelaySeconds: 0 + periodSeconds: 10 + readinessProbe: + failureThreshold: 3 + httpGet: + path: /readyz + port: https + scheme: HTTPS + initialDelaySeconds: 20 + periodSeconds: 10 + volumeMounts: + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: {} +--- +# Source: metrics-server/templates/apiservice.yaml +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + name: v1beta1.metrics.k8s.io + labels: + helm.sh/chart: metrics-server-3.8.3 + app.kubernetes.io/name: metrics-server + app.kubernetes.io/instance: local-metrics-server + app.kubernetes.io/version: "0.6.2" + app.kubernetes.io/managed-by: Helm +spec: + group: metrics.k8s.io + groupPriorityMinimum: 100 + insecureSkipTLSVerify: true + service: + name: local-metrics-server + namespace: default + port: 443 + version: v1beta1 + versionPriority: 100 diff --git a/vertical-pod-autoscaler/hack/e2e/kind-with-registry.sh b/vertical-pod-autoscaler/hack/e2e/kind-with-registry.sh new file mode 100755 index 000000000000..8dba9f3d9ff4 --- /dev/null +++ b/vertical-pod-autoscaler/hack/e2e/kind-with-registry.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Based on https://kind.sigs.k8s.io/examples/kind-with-registry.sh +set -o errexit + +# Create registry container unless it already exists +reg_name='kind-registry' +reg_port='5001' + +if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then + docker run \ + -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ + registry:2 +fi + +# Create a cluster with the local registry enabled in containerd +cat <>{<<.LabelMatchers>>}) by (name) + resources: + overrides: + kubernetes_namespace: { resource: namespace } + kubernetes_pod_name: { resource: pod } + - seriesQuery: '{__name__="mem"}' + metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (name) + resources: + overrides: + kubernetes_namespace: { resource: namespace } + kubernetes_pod_name: { resource: pod } + rules: + - seriesQuery: '{__name__=~"^container_.*",container!="POD",namespace!="",pod!=""}' + seriesFilters: [] + resources: + overrides: + namespace: + resource: namespace + pod: + resource: pod + name: + matches: ^container_(.*)_seconds_total$ + as: "" + metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>,container!="POD"}[5m])) + by (<<.GroupBy>>) + - seriesQuery: '{__name__=~"^container_.*",container!="POD",namespace!="",pod!=""}' + seriesFilters: + - isNot: ^container_.*_seconds_total$ + resources: + overrides: + namespace: + resource: namespace + pod: + resource: pod + name: + matches: ^container_(.*)_total$ + as: "" + metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>,container!="POD"}[5m])) + by (<<.GroupBy>>) + - seriesQuery: '{__name__=~"^container_.*",container!="POD",namespace!="",pod!=""}' + seriesFilters: + - isNot: ^container_.*_total$ + resources: + overrides: + namespace: + resource: namespace + pod: + resource: pod + name: + matches: ^container_(.*)$ + as: "" + metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>,container!="POD"}) by (<<.GroupBy>>) + - seriesQuery: '{namespace!="",__name__!~"^container_.*"}' + seriesFilters: + - isNot: .*_total$ + resources: + template: <<.Resource>> + name: + matches: "" + as: "" + metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>) + - seriesQuery: '{namespace!="",__name__!~"^container_.*"}' + seriesFilters: + - isNot: .*_seconds_total + resources: + template: <<.Resource>> + name: + matches: ^(.*)_total$ + as: "" + metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[5m])) by (<<.GroupBy>>) + - seriesQuery: '{namespace!="",__name__!~"^container_.*"}' + seriesFilters: [] + resources: + template: <<.Resource>> + name: + matches: ^(.*)_seconds_total$ + as: "" + metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[5m])) by (<<.GroupBy>>) +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: metrics + app.kubernetes.io/instance: prometheus-adapter + app.kubernetes.io/name: prometheus-adapter + name: prometheus-adapter + namespace: monitoring +spec: + progressDeadlineSeconds: 600 + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: prometheus-adapter + app.kubernetes.io/name: prometheus-adapter + template: + metadata: + labels: + app.kubernetes.io/component: metrics + app.kubernetes.io/instance: prometheus-adapter + app.kubernetes.io/name: prometheus-adapter + name: prometheus-adapter + spec: + containers: + - name: prometheus-adapter + args: + - /adapter + - --secure-port=6443 + - --cert-dir=/tmp/cert + - --logtostderr=true + - --prometheus-url=http://prometheus.monitoring.svc:9090 + - --metrics-relist-interval=1m + - --v=4 + - --config=/etc/adapter/config.yaml + image: registry.k8s.io/prometheus-adapter/prometheus-adapter:v0.10.0 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: https + scheme: HTTPS + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + ports: + - containerPort: 6443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: https + scheme: HTTPS + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - all + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 10001 + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /etc/adapter/ + name: config + readOnly: true + - mountPath: /tmp + name: tmp + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccount: prometheus-adapter + serviceAccountName: prometheus-adapter + terminationGracePeriodSeconds: 30 + volumes: + - configMap: + defaultMode: 420 + name: prometheus-adapter + name: config + - emptyDir: {} + name: tmp diff --git a/vertical-pod-autoscaler/hack/e2e/prometheus.yaml b/vertical-pod-autoscaler/hack/e2e/prometheus.yaml new file mode 100644 index 000000000000..651cf81ab256 --- /dev/null +++ b/vertical-pod-autoscaler/hack/e2e/prometheus.yaml @@ -0,0 +1,264 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: prometheus-server-conf + labels: + name: prometheus-server-conf + namespace: monitoring +data: + prometheus.rules: |- + groups: + - name: devopscube demo alert + rules: + - alert: High Pod Memory + expr: sum(container_memory_usage_bytes) > 1 + for: 1m + labels: + severity: slack + annotations: + summary: High Memory Usage + prometheus.yml: |- + global: + scrape_interval: 5s + evaluation_interval: 5s + rule_files: + - /etc/prometheus/prometheus.rules + + scrape_configs: + - job_name: 'kubernetes-apiservers' + + kubernetes_sd_configs: + - role: endpoints + scheme: https + + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: default;kubernetes;https + + - job_name: 'kubernetes-pods' + + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: kubernetes_pod_name + + - job_name: 'kubernetes-service-endpoints' + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: kubernetes_name + + - job_name: "pushgateway" + honor_labels: true + static_configs: + - targets: ['localhost:9091'] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: prometheus +rules: +- apiGroups: [""] + resources: + - nodes + - nodes/proxy + - services + - endpoints + - pods + - configmaps + verbs: ["get", "list", "watch"] +- apiGroups: + - extensions + resources: + - ingresses + verbs: ["get", "list", "watch"] +- nonResourceURLs: ["/metrics"] + verbs: ["get"] +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: ["create"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: prometheus +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prometheus +subjects: +- kind: ServiceAccount + name: prometheus + namespace: monitoring +- kind: ServiceAccount + name: metrics-pump + namespace: monitoring +- kind: ServiceAccount + name: prometheus-adapter + namespace: monitoring + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: prometheus + namespace: monitoring +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: metrics-pump + namespace: monitoring +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: prometheus-adapter + namespace: monitoring + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prometheus + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + spec: + serviceAccountName: prometheus + securityContext: + runAsNonRoot: true + runAsUser: 65534 # nobody + containers: + - name: prometheus + image: prom/prometheus + args: + - "--storage.tsdb.retention.time=12h" + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus/" + ports: + - containerPort: 9090 + name: prometheus + resources: + requests: + cpu: 500m + memory: 500M + limits: + cpu: 1 + memory: 1Gi + volumeMounts: + - name: prometheus-config-volume + mountPath: /etc/prometheus/ + - name: prometheus-storage-volume + mountPath: /prometheus/ + - name: pushgateway + image: prom/pushgateway + ports: + - containerPort: 9091 + name: pushgateway + resources: + requests: + cpu: 500m + memory: 500M + volumes: + - name: prometheus-config-volume + configMap: + defaultMode: 420 + name: prometheus-server-conf + - name: prometheus-storage-volume + emptyDir: {} + +--- +apiVersion: v1 +kind: Service +metadata: + name: prometheus + namespace: monitoring +spec: + selector: + app: prometheus + ports: + - name: prometheus + protocol: TCP + port: 9090 + targetPort: prometheus + - name: pushgateway + protocol: TCP + port: 9091 + targetPort: pushgateway +--- +apiVersion: v1 +kind: Service +metadata: + name: prometheus-adapter + namespace: monitoring +spec: + selector: + app.kubernetes.io/name: prometheus-adapter + ports: + - name: api + protocol: TCP + port: 443 + targetPort: https + diff --git a/vertical-pod-autoscaler/hack/e2e/recommender-externalmetrics-deployment.yaml b/vertical-pod-autoscaler/hack/e2e/recommender-externalmetrics-deployment.yaml new file mode 100644 index 000000000000..bf033a8294ce --- /dev/null +++ b/vertical-pod-autoscaler/hack/e2e/recommender-externalmetrics-deployment.yaml @@ -0,0 +1,42 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vpa-recommender + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app: vpa-recommender + template: + metadata: + labels: + app: vpa-recommender + spec: + serviceAccountName: vpa-recommender + securityContext: + runAsNonRoot: true + runAsUser: 65534 # nobody + containers: + - name: recommender + image: localhost:5001/vpa-recommender-amd64:latest + imagePullPolicy: Never + args: + - /recommender-amd64 + - --use-external-metrics=true + - --external-metrics-cpu-metric=cpu + - --external-metrics-memory-metric=mem + - --v=4 + resources: + limits: + cpu: 200m + memory: 1000Mi + requests: + cpu: 50m + memory: 500Mi + ports: + - name: prometheus + containerPort: 8942 + - name: delve + containerPort: 40000 diff --git a/vertical-pod-autoscaler/hack/e2e/vpa-rbac.diff b/vertical-pod-autoscaler/hack/e2e/vpa-rbac.diff new file mode 100644 index 000000000000..80f0ff45d492 --- /dev/null +++ b/vertical-pod-autoscaler/hack/e2e/vpa-rbac.diff @@ -0,0 +1,18 @@ +*** deploy/vpa-rbac.yaml Wed Jul 5 14:37:35 2023 +--- hack/e2e/vpa-rbac.yaml Thu Jul 6 12:46:19 2023 +*************** +*** 5,10 **** +--- 5,17 ---- + name: system:metrics-reader + rules: + - apiGroups: ++ - "external.metrics.k8s.io" ++ resources: ++ - "*" ++ verbs: ++ - get ++ - list ++ - apiGroups: + - "metrics.k8s.io" + resources: + - pods diff --git a/vertical-pod-autoscaler/hack/emit-metrics.py b/vertical-pod-autoscaler/hack/emit-metrics.py new file mode 100755 index 000000000000..c568536f566f --- /dev/null +++ b/vertical-pod-autoscaler/hack/emit-metrics.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 + +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script runs as a pod, scanning the cluster for other pods. +# It then publishes fake metrics (Gaussian by --mean_* and --stddev_*) +# for each pod into a Prometheus Pushgateway. The Prometheus instance +# connected to that Pushgateway can have a Prometheus Adapter connected +# to it that serves as an External Metrics Provider to Kubernetes. + +import argparse +import base64 +from collections import defaultdict +from kubernetes import client, config +import math +import random +import re +import requests +import sys +import time +import urllib.parse +import pprint + +def parse_arguments(): + parser = argparse.ArgumentParser(description='') + parser.add_argument('--dest', type=str, default='pushservice') + parser.add_argument('--mean_cpu', type=int, default='1000', help='Mean millicores for cpu.') + parser.add_argument('--mean_mem', type=int, default='128', help='Mean megabytes for memory.') + parser.add_argument('--stddev_cpu', type=int, default=150, help='Standard deviation for cpu.') + parser.add_argument('--stddev_mem', type=int, default=15, help='Standard deviation for mem.') + parser.add_argument('--sleep_sec', type=int, default=30, help='Delay between metric-sends, in seconds.') + parser.add_argument('-t','--tags', action='append', nargs=2, metavar=('key','value'), default=[['data', 'emit-metrics']], + help='Additional tags to attach to metrics.') + parser.add_argument('--namespace_pattern', default='monitoring', help='Regex to match namespace names.') + parser.add_argument('--pod_pattern', default='prometheus-[0-9a-f]{9}-[0-9a-z]{5}', help='Regex to match pod names.') + parser.add_argument('--all', default=False, action='store_true', help='Write metrics for all pods.') + parser.add_argument('--job', default='emit-metrics', help='Job name to submit under.') + return parser.parse_args() + +def safestr(s): + '''Is s a URL-safe string?''' + return s.strip('_').isalnum() + +def urlify(key, value): + replacements = { ".": "%2E", "-": "%2D" } + def encode(s): + s = urllib.parse.quote(s, safe='') + for c,repl in replacements.items(): + s = s.replace(c, repl) + return s + if safestr(key) and safestr(value): + return f"{key}/{value}" + elif len(value) == 0: + # Possibly encode the key using URI encoding, but + # definitely use base64 for the value. + return encode(key)+"@base64/=" + else: + return f"{encode(key)}/{encode(value)}" + +def valid_key(key): + invalid_char_re = re.compile(r'.*[./-].*') + invalid_keys = set(["pod-template-hash", "k8s-app", "controller-uid", + "controller-revision-hash", "pod-template-generation"]) + return (key not in invalid_keys) and invalid_char_re.match(key) == None + +def send_metrics(args, job, path, cpuval, memval): + cpuval = cpuval / 1000.0 # Scale from millicores to cores + payload = f"cpu {cpuval:.3f}\nmem {memval:d}.0\n" + path_str = '/'.join([urlify(key,value) for key, value in path.items()]) + url = f'http://{args.dest}/metrics/job/{job}/namespace/{path["namespace"]}/{path_str}' + response = requests.put(url=url, data=bytes(payload, 'utf-8')) + if response.status_code != 200: + print (f"Writing to {url}.\n>> Got {response.status_code}: {response.reason}, {response.text}\n>> Dict was:") + pprint.pprint(path) + else: + print (f"Wrote to {url}: {payload}") + sys.stdout.flush() + +def main(args): + print (f"Starting up.") + sys.stdout.flush() + pod_name_pattern = re.compile(args.pod_pattern) + namespace_name_pattern = re.compile(args.namespace_pattern) + try: + config.load_kube_config() + except: + config.load_incluster_config() + v1 = client.CoreV1Api() + print (f"Initialized. Sleep interval is for {args.sleep_sec} seconds.") + sys.stdout.flush() + pod_cache = dict() + while True: + skipped_keys= set() + time.sleep(args.sleep_sec) + pods = v1.list_pod_for_all_namespaces(watch=False) + all = 0 + found = 0 + for pod in pods.items: + all += 1 + job = args.job + if args.all or (namespace_name_pattern.match(pod.metadata.namespace) and pod_name_pattern.match(pod.metadata.name)): + # Get container names and send metrics for each. + key = f"{pod.metadata.namespace}/{pod.metadata.name}" + if key not in pod_cache: + v1pod = v1.read_namespaced_pod(pod.metadata.name, pod.metadata.namespace, pretty=False) + pod_cache[key] = v1pod + else: + v1pod = pod_cache[key] + containers = [ c.name for c in v1pod.spec.containers ] + found += 1 + path = { "kubernetes_namespace": pod.metadata.namespace, + "kubernetes_pod_name": pod.metadata.name, + "pod": pod.metadata.name, + "namespace": pod.metadata.namespace} + # Append metadata to the data point, add the labels second to overwrite annotations on + # conflict + try: + if v1pod.metadata.annotations: + for k,v in v1pod.metadata.annotations.items(): + if valid_key(k): + path[k] = v + else: + skipped_keys |= set([k]) + if v1pod.metadata.labels: + for k,v in v1pod.metadata.labels.items(): + if valid_key(k): + path[k] = v + else: + skipped_keys |= set([k]) + except ValueError as err: + print (f"{err} on {v1pod.metadata} when getting annotations/labels") + if "job" in path: + job = path["job"] + for container in containers: + cpuval = random.normalvariate(args.mean_cpu, args.stddev_cpu) + memval = random.normalvariate(args.mean_mem, args.stddev_mem) + path['name'] = container + path['container'] = container + send_metrics(args, job, path, math.floor(cpuval), math.floor(memval * 1048576.0)) + print(f"Found {found} out of {all} pods. Skipped keys:") + pprint.pprint(skipped_keys) + +if __name__ == '__main__': + main(parse_arguments()) diff --git a/vertical-pod-autoscaler/hack/local-cluster.md b/vertical-pod-autoscaler/hack/local-cluster.md new file mode 100644 index 000000000000..dbe34048ba1d --- /dev/null +++ b/vertical-pod-autoscaler/hack/local-cluster.md @@ -0,0 +1,26 @@ +# Running Integration Tests locally +Included in parallel with `run-e2e.sh` and `deploy-for-e2e.sh` are two alternate versions +with `-locally` as part of their names. They use Kubernetes in Docker (`kind`) to run a local +cluster in Docker. Using them will require `docker` and `kind` in your `PATH`. + +## External Metrics Tests +The external metrics tests (`recommender-externalmetrics`, available on the `-locally` variants) +use a stack of 4 additional programs to support testing: + +1. `hack/emit-metrics.py` to generate random CPU and RAM metrics for every pod in the local cluster. +2. Prometheus Pushgateway to accept metrics from `hack/emit-metrics`. +3. Prometheus to store the metrics accepted by the Pushgateway. +4. Prometheus Adapter to provide an External Metrics interface to Prometheus. + +The External Metrics tests run by configuring a `recommender` to use the External Metrics interface +from the Prometheus Adapter. With that configuration, it runs the standard `recommender` test suite. + +## Non-recommender tests +The `recommender` and `recommender-externalmetrics` test work locally, but none of the others do; +they require more Makefile work. + +# Configuration Notes +To support the regular `recommender` tests locally, we've added the stock Kubernetes Metrics Server. +Unfortunately, it doesn't work with TLS turned on. The metrics server is being run in insecure mode +to work around this. This only runs in the local `kind` case, not in a real cluster. + diff --git a/vertical-pod-autoscaler/hack/run-e2e-locally.sh b/vertical-pod-autoscaler/hack/run-e2e-locally.sh new file mode 100755 index 000000000000..e6e6b4fed5b2 --- /dev/null +++ b/vertical-pod-autoscaler/hack/run-e2e-locally.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# Copyright 2023 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o nounset +set -o pipefail + +SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. + +function print_help { + echo "ERROR! Usage: run-e2e.sh " + echo " should be one of:" + echo " - recommender" + echo " - recommender-externalmetrics" +} + +if [ $# -eq 0 ]; then + print_help + exit 1 +fi + +if [ $# -gt 1 ]; then + print_help + exit 1 +fi + +SUITE=$1 + +echo "Deleting KIND cluster 'kind'." +kind delete cluster -n kind -q + +echo "Creating KIND cluster 'kind' with builtin registry." +${SCRIPT_ROOT}/hack/e2e/kind-with-registry.sh + +echo "Building metrics-pump image" +docker build -t localhost:5001/write-metrics:dev -f ${SCRIPT_ROOT}/hack/e2e/Dockerfile.externalmetrics-writer ${SCRIPT_ROOT}/hack +echo " pushing image to local registry" +docker push localhost:5001/write-metrics:dev + +case ${SUITE} in + recommender|recommender-externalmetrics) + ${SCRIPT_ROOT}/hack/vpa-down.sh + echo " ** Deploying for suite ${SUITE}" + ${SCRIPT_ROOT}/hack/deploy-for-e2e-locally.sh ${SUITE} + + echo " ** Running suite ${SUITE}" + if [ ${SUITE} == recommender-externalmetrics ]; then + ${SCRIPT_ROOT}/hack/run-e2e-tests.sh recommender + else + ${SCRIPT_ROOT}/hack/run-e2e-tests.sh ${SUITE} + fi + ;; + *) + print_help + exit 1 + ;; +esac + diff --git a/vertical-pod-autoscaler/hack/vpa-process-yamls.sh b/vertical-pod-autoscaler/hack/vpa-process-yamls.sh index aa7aafef04c4..05e4e38b6ccf 100755 --- a/vertical-pod-autoscaler/hack/vpa-process-yamls.sh +++ b/vertical-pod-autoscaler/hack/vpa-process-yamls.sh @@ -40,7 +40,19 @@ if [ $# -gt 2 ]; then fi ACTION=$1 -COMPONENTS="vpa-v1-crd-gen vpa-rbac updater-deployment recommender-deployment admission-controller-deployment" +COMPONENTS="vpa-v1-crd-gen vpa-rbac updater-deployment recommender-deployment admission-controller-deployment recommender-externalmetrics-deployment" +TEST_COMPONENTS=(recommender-externalmetrics-deployment) + +function script_path { + # Regular components have deployment yaml files under /deploy/. But some components only have + # test deployment yaml files that are under hack/e2e. + if printf '%s\0' "${TEST_COMPONENTS[@]}" | grep -Fqxz -- $1; then + echo "${SCRIPT_ROOT}/hack/e2e/${1}.yaml" + else + echo "${SCRIPT_ROOT}/deploy/${1}.yaml" + fi +} + case ${ACTION} in delete|diff) COMPONENTS+=" vpa-beta2-crd" ;; esac @@ -59,8 +71,8 @@ for i in $COMPONENTS; do fi fi if [[ ${ACTION} == print ]]; then - ${SCRIPT_ROOT}/hack/vpa-process-yaml.sh ${SCRIPT_ROOT}/deploy/$i.yaml + ${SCRIPT_ROOT}/hack/vpa-process-yaml.sh $(script_path $i) else - ${SCRIPT_ROOT}/hack/vpa-process-yaml.sh ${SCRIPT_ROOT}/deploy/$i.yaml | kubectl ${ACTION} -f - || true + ${SCRIPT_ROOT}/hack/vpa-process-yaml.sh $(script_path $i) | kubectl ${ACTION} -f - || true fi done diff --git a/vertical-pod-autoscaler/pkg/recommender/Makefile b/vertical-pod-autoscaler/pkg/recommender/Makefile index c51d0e944045..eb3834d8a033 100644 --- a/vertical-pod-autoscaler/pkg/recommender/Makefile +++ b/vertical-pod-autoscaler/pkg/recommender/Makefile @@ -8,6 +8,8 @@ ENVVAR=CGO_ENABLED=0 $(TEST_ENVVAR) GOOS?=linux COMPONENT=recommender FULL_COMPONENT=vpa-${COMPONENT} +# localhost registries need --insecure for some docker commands. +INSECURE=$(subst localhost,--insecure,$(findstring localhost,$(REGISTRY))) ALL_ARCHITECTURES?=amd64 arm arm64 ppc64le s390x export DOCKER_CLI_EXPERIMENTAL=enabled @@ -64,9 +66,9 @@ endif .PHONY: push-multi-arch push-multi-arch: - docker manifest create --amend $(REGISTRY)/${FULL_COMPONENT}:$(TAG) $(shell echo $(ALL_ARCHITECTURES) | sed -e "s~[^ ]*~$(REGISTRY)/${FULL_COMPONENT}\-&:$(TAG)~g") + docker manifest create $(INSECURE) --amend $(REGISTRY)/${FULL_COMPONENT}:$(TAG) $(shell echo $(ALL_ARCHITECTURES) | sed -e "s~[^ ]*~$(REGISTRY)/${FULL_COMPONENT}\-&:$(TAG)~g") @for arch in $(ALL_ARCHITECTURES); do docker manifest annotate --arch $${arch} $(REGISTRY)/${FULL_COMPONENT}:$(TAG) $(REGISTRY)/${FULL_COMPONENT}-$${arch}:${TAG}; done - docker manifest push --purge $(REGISTRY)/${FULL_COMPONENT}:$(TAG) + docker manifest push $(INSECURE) --purge $(REGISTRY)/${FULL_COMPONENT}:$(TAG) docker-builder: docker build -t vpa-autoscaling-builder ../../builder diff --git a/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client.go b/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client.go index 7a55d9641649..a34e928e5c04 100644 --- a/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client.go +++ b/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client.go @@ -22,13 +22,10 @@ import ( k8sapiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" - "k8s.io/klog/v2" - "k8s.io/metrics/pkg/apis/metrics/v1beta1" - resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1" - "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/recommender/model" recommender_metrics "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/metrics/recommender" + "k8s.io/klog/v2" + "k8s.io/metrics/pkg/apis/metrics/v1beta1" ) // ContainerMetricsSnapshot contains information about usage of certain container within defined time window. @@ -51,31 +48,25 @@ type MetricsClient interface { } type metricsClient struct { - metricsGetter resourceclient.PodMetricsesGetter - namespace string - clientName string + source PodMetricsLister + namespace string + clientName string } // NewMetricsClient creates new instance of MetricsClient, which is used by recommender. // namespace limits queries to particular namespace, use k8sapiv1.NamespaceAll to select all namespaces. -func NewMetricsClient(config *rest.Config, namespace, clientName string) MetricsClient { - metricsGetter := resourceclient.NewForConfigOrDie(config) - return newMetricsClient(metricsGetter, namespace, clientName) -} - -func newMetricsClient(metricsGetter resourceclient.PodMetricsesGetter, namespace, clientName string) MetricsClient { +func NewMetricsClient(source PodMetricsLister, namespace, clientName string) MetricsClient { return &metricsClient{ - metricsGetter: metricsGetter, - namespace: namespace, - clientName: clientName, + source: source, + namespace: namespace, + clientName: clientName, } } func (c *metricsClient) GetContainersMetrics() ([]*ContainerMetricsSnapshot, error) { var metricsSnapshots []*ContainerMetricsSnapshot - podMetricsInterface := c.metricsGetter.PodMetricses(c.namespace) - podMetricsList, err := podMetricsInterface.List(context.TODO(), metav1.ListOptions{}) + podMetricsList, err := c.source.List(context.TODO(), c.namespace, metav1.ListOptions{}) recommender_metrics.RecordMetricsServerResponse(err, c.clientName) if err != nil { return nil, err diff --git a/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client_test_util.go b/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client_test_util.go index f2a623fb162a..5f967ae741aa 100644 --- a/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client_test_util.go +++ b/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_client_test_util.go @@ -85,7 +85,7 @@ func (tc *metricsClientTestCase) createFakeMetricsClient() MetricsClient { fakeMetricsGetter.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { return true, tc.getFakePodMetricsList(), nil }) - return newMetricsClient(fakeMetricsGetter.MetricsV1beta1(), "", "fake") + return NewMetricsClient(NewPodMetricsesSource(fakeMetricsGetter.MetricsV1beta1()), "", "fake") } func (tc *metricsClientTestCase) getFakePodMetricsList() *metricsapi.PodMetricsList { diff --git a/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_source.go b/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_source.go new file mode 100644 index 000000000000..04978268baf5 --- /dev/null +++ b/vertical-pod-autoscaler/pkg/recommender/input/metrics/metrics_source.go @@ -0,0 +1,144 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package metrics + +import ( + "context" + k8sapiv1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/recommender/model" + "k8s.io/client-go/rest" + "k8s.io/klog/v2" + "k8s.io/metrics/pkg/apis/metrics/v1beta1" + resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1" + "k8s.io/metrics/pkg/client/external_metrics" + "time" +) + +// PodMetricsLister wraps both metrics-client and External Metrics +type PodMetricsLister interface { + List(ctx context.Context, namespace string, opts v1.ListOptions) (*v1beta1.PodMetricsList, error) +} + +// podMetricsSource is the metrics-client source of metrics. +type podMetricsSource struct { + metricsGetter resourceclient.PodMetricsesGetter +} + +// NewPodMetricsesSource Returns a Source-wrapper around PodMetricsesGetter. +func NewPodMetricsesSource(source resourceclient.PodMetricsesGetter) PodMetricsLister { + return podMetricsSource{metricsGetter: source} +} + +func (s podMetricsSource) List(ctx context.Context, namespace string, opts v1.ListOptions) (*v1beta1.PodMetricsList, error) { + podMetricsInterface := s.metricsGetter.PodMetricses(namespace) + return podMetricsInterface.List(ctx, opts) +} + +// externalMetricsClient is the External Metrics source of metrics. +type externalMetricsClient struct { + externalClient external_metrics.ExternalMetricsClient + options ExternalClientOptions + clusterState *model.ClusterState +} + +// ExternalClientOptions specifies parameters for using an External Metrics Client. +type ExternalClientOptions struct { + ResourceMetrics map[k8sapiv1.ResourceName]string + // Label to use for the container name. + ContainerNameLabel string +} + +// NewExternalClient returns a Source for an External Metrics Client. +func NewExternalClient(c *rest.Config, clusterState *model.ClusterState, options ExternalClientOptions) PodMetricsLister { + extClient, err := external_metrics.NewForConfig(c) + if err != nil { + klog.Fatalf("Failed initializing external metrics client: %v", err) + } + return &externalMetricsClient{ + externalClient: extClient, + options: options, + clusterState: clusterState, + } +} + +func (s *externalMetricsClient) List(ctx context.Context, namespace string, opts v1.ListOptions) (*v1beta1.PodMetricsList, error) { + result := v1beta1.PodMetricsList{} + + for _, vpa := range s.clusterState.Vpas { + if vpa.PodCount == 0 { + continue + } + + if namespace != "" && vpa.ID.Namespace != namespace { + continue + } + + nsClient := s.externalClient.NamespacedMetrics(vpa.ID.Namespace) + pods := s.clusterState.GetMatchingPods(vpa) + + for _, pod := range pods { + podNameReq, err := labels.NewRequirement("pod", selection.Equals, []string{pod.PodName}) + if err != nil { + return nil, err + } + selector := vpa.PodSelector.Add(*podNameReq) + podMets := v1beta1.PodMetrics{ + TypeMeta: v1.TypeMeta{}, + ObjectMeta: v1.ObjectMeta{Namespace: vpa.ID.Namespace, Name: pod.PodName}, + Window: v1.Duration{}, + Containers: make([]v1beta1.ContainerMetrics, 0), + } + // Query each resource in turn, then assemble back to a single []ContainerMetrics. + containerMetrics := make(map[string]k8sapiv1.ResourceList) + for resourceName, metricName := range s.options.ResourceMetrics { + m, err := nsClient.List(metricName, selector) + if err != nil { + return nil, err + } + if m == nil || len(m.Items) == 0 { + klog.V(4).Infof("External Metrics Query for VPA %+v: resource %+v, metric %+v, No items,", vpa.ID, resourceName, metricName) + continue + } + klog.V(4).Infof("External Metrics Query for VPA %+v: resource %+v, metric %+v, %d items, item[0]: %+v", vpa.ID, resourceName, metricName, len(m.Items), m.Items[0]) + podMets.Timestamp = m.Items[0].Timestamp + if m.Items[0].WindowSeconds != nil { + podMets.Window = v1.Duration{Duration: time.Duration(*m.Items[0].WindowSeconds) * time.Second} + } + for _, val := range m.Items { + ctrName, hasCtrName := val.MetricLabels[s.options.ContainerNameLabel] + if !hasCtrName { + continue + } + if containerMetrics[ctrName] == nil { + containerMetrics[ctrName] = make(k8sapiv1.ResourceList) + } + containerMetrics[ctrName][resourceName] = val.Value + } + + } + for cname, res := range containerMetrics { + podMets.Containers = append(podMets.Containers, v1beta1.ContainerMetrics{Name: cname, Usage: res}) + } + result.Items = append(result.Items, podMets) + + } + } + return &result, nil +} diff --git a/vertical-pod-autoscaler/pkg/recommender/main.go b/vertical-pod-autoscaler/pkg/recommender/main.go index a5ceb3fc906b..e6443ff214e1 100644 --- a/vertical-pod-autoscaler/pkg/recommender/main.go +++ b/vertical-pod-autoscaler/pkg/recommender/main.go @@ -19,6 +19,7 @@ package main import ( "context" "flag" + resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1" "time" apiv1 "k8s.io/api/core/v1" @@ -69,6 +70,10 @@ var ( ctrNameLabel = flag.String("container-name-label", "name", `Label name to look for container names`) vpaObjectNamespace = flag.String("vpa-object-namespace", apiv1.NamespaceAll, "Namespace to search for VPA objects and pod stats. Empty means all namespaces will be used.") memorySaver = flag.Bool("memory-saver", false, `If true, only track pods which have an associated VPA`) + // external metrics provider config + useExternalMetrics = flag.Bool("use-external-metrics", false, "Use an external metrics provider instead of metrics_server.") + externalCpuMetric = flag.String("external-metrics-cpu-metric", "", "Metric to use with external metrics provider for CPU usage.") + externalMemoryMetric = flag.String("external-metrics-memory-metric", "", "Metric to use with external metrics provider for memory usage.") ) // Aggregation configuration flags @@ -100,7 +105,7 @@ const ( func main() { klog.InitFlags(nil) kube_flag.InitFlags() - klog.V(1).Infof("Vertical Pod Autoscaler %s Recommender: %v", common.VerticalPodAutoscalerVersion, recommenderName) + klog.V(1).Infof("Vertical Pod Autoscaler %s Recommender: %v", common.VerticalPodAutoscalerVersion, *recommenderName) config := common.CreateKubeConfigOrDie(*kubeconfig, float32(*kubeApiQps), int(*kubeApiBurst)) kubeClient := kube_client.NewForConfigOrDie(config) @@ -122,14 +127,31 @@ func main() { if *postProcessorCPUasInteger { postProcessors = append(postProcessors, &routines.IntegerCPUPostProcessor{}) } + // CappingPostProcessor, should always come in the last position for post-processing postProcessors = append(postProcessors, &routines.CappingPostProcessor{}) + var source input_metrics.PodMetricsLister + if *useExternalMetrics { + resourceMetrics := map[apiv1.ResourceName]string{} + if externalCpuMetric != nil && *externalCpuMetric != "" { + resourceMetrics[apiv1.ResourceCPU] = *externalCpuMetric + } + if externalMemoryMetric != nil && *externalMemoryMetric != "" { + resourceMetrics[apiv1.ResourceMemory] = *externalMemoryMetric + } + externalClientOptions := &input_metrics.ExternalClientOptions{ResourceMetrics: resourceMetrics, ContainerNameLabel: *ctrNameLabel} + klog.V(1).Infof("Using External Metrics: %+v", externalClientOptions) + source = input_metrics.NewExternalClient(config, clusterState, *externalClientOptions) + } else { + klog.V(1).Infof("Using Metrics Server.") + source = input_metrics.NewPodMetricsesSource(resourceclient.NewForConfigOrDie(config)) + } clusterStateFeeder := input.ClusterStateFeederFactory{ PodLister: podLister, OOMObserver: oomObserver, KubeClient: kubeClient, - MetricsClient: input_metrics.NewMetricsClient(config, *vpaObjectNamespace, "default-metrics-client"), + MetricsClient: input_metrics.NewMetricsClient(source, *vpaObjectNamespace, "default-metrics-client"), VpaCheckpointClient: vpa_clientset.NewForConfigOrDie(config).AutoscalingV1(), VpaLister: vpa_api_util.NewVpasLister(vpa_clientset.NewForConfigOrDie(config), make(chan struct{}), *vpaObjectNamespace), ClusterState: clusterState, diff --git a/vertical-pod-autoscaler/pkg/recommender/routines/recommender.go b/vertical-pod-autoscaler/pkg/recommender/routines/recommender.go index 564b9b9845a2..760c0fb5098e 100644 --- a/vertical-pod-autoscaler/pkg/recommender/routines/recommender.go +++ b/vertical-pod-autoscaler/pkg/recommender/routines/recommender.go @@ -126,7 +126,7 @@ func (r *recommender) UpdateVPAs() { r.vpaClient.VerticalPodAutoscalers(vpa.ID.Namespace), vpa.ID.VpaName, vpa.AsStatus(), &observedVpa.Status) if err != nil { klog.Errorf( - "Cannot update VPA %v object. Reason: %+v", vpa.ID.VpaName, err) + "Cannot update VPA %v/%v object. Reason: %+v", vpa.ID.Namespace, vpa.ID.VpaName, err) } } } diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/doc.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/doc.go new file mode 100644 index 000000000000..edf1553ad240 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +groupName=external.metrics.k8s.io + +// Package external_metrics adds support for defining external metrics. +package external_metrics // import "k8s.io/metrics/pkg/apis/external_metrics" diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/register.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/register.go new file mode 100644 index 000000000000..33dca86c9aea --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/register.go @@ -0,0 +1,51 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package external_metrics + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "external.metrics.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns back a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ExternalMetricValue{}, + &ExternalMetricValueList{}, + ) + return nil +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/types.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/types.go new file mode 100644 index 000000000000..2a9c6e3923d1 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/types.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package external_metrics + +import ( + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// a list of values for a given metric for some set labels +type ExternalMetricValueList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + // value of the metric matching a given set of labels + Items []ExternalMetricValue `json:"items"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// a metric value for external metric +// A single metric value is identified by metric name and a set of string labels. +// For one metric there can be multiple values with different sets of labels. +type ExternalMetricValue struct { + metav1.TypeMeta `json:",inline"` + + // the name of the metric + MetricName string `json:"metricName"` + + // a set of labels that identify a single time series for the metric + MetricLabels map[string]string `json:"metricLabels"` + + // indicates the time at which the metrics were produced + Timestamp metav1.Time `json:"timestamp"` + + // indicates the window ([Timestamp-Window, Timestamp]) from + // which these metrics were calculated, when returning rate + // metrics calculated from cumulative metrics (or zero for + // non-calculated instantaneous metrics). + WindowSeconds *int64 `json:"window,omitempty"` + + // the value of the metric + Value resource.Quantity `json:"value"` +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/doc.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/doc.go new file mode 100644 index 000000000000..aa27d102fc97 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:protobuf-gen=package +// +k8s:conversion-gen=k8s.io/metrics/pkg/apis/external_metrics +// +k8s:openapi-gen=true + +// Package v1beta1 is the v1beta1 version of the external metrics API. +package v1beta1 // import "k8s.io/metrics/pkg/apis/external_metrics/v1beta1" diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.pb.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.pb.go new file mode 100644 index 000000000000..ed71bf21a86c --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.pb.go @@ -0,0 +1,879 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: k8s.io/kubernetes/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto + +package v1beta1 + +import ( + fmt "fmt" + + io "io" + + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" + + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +func (m *ExternalMetricValue) Reset() { *m = ExternalMetricValue{} } +func (*ExternalMetricValue) ProtoMessage() {} +func (*ExternalMetricValue) Descriptor() ([]byte, []int) { + return fileDescriptor_76ac204ccf814641, []int{0} +} +func (m *ExternalMetricValue) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExternalMetricValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ExternalMetricValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExternalMetricValue.Merge(m, src) +} +func (m *ExternalMetricValue) XXX_Size() int { + return m.Size() +} +func (m *ExternalMetricValue) XXX_DiscardUnknown() { + xxx_messageInfo_ExternalMetricValue.DiscardUnknown(m) +} + +var xxx_messageInfo_ExternalMetricValue proto.InternalMessageInfo + +func (m *ExternalMetricValueList) Reset() { *m = ExternalMetricValueList{} } +func (*ExternalMetricValueList) ProtoMessage() {} +func (*ExternalMetricValueList) Descriptor() ([]byte, []int) { + return fileDescriptor_76ac204ccf814641, []int{1} +} +func (m *ExternalMetricValueList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExternalMetricValueList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ExternalMetricValueList) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExternalMetricValueList.Merge(m, src) +} +func (m *ExternalMetricValueList) XXX_Size() int { + return m.Size() +} +func (m *ExternalMetricValueList) XXX_DiscardUnknown() { + xxx_messageInfo_ExternalMetricValueList.DiscardUnknown(m) +} + +var xxx_messageInfo_ExternalMetricValueList proto.InternalMessageInfo + +func init() { + proto.RegisterType((*ExternalMetricValue)(nil), "k8s.io.metrics.pkg.apis.external_metrics.v1beta1.ExternalMetricValue") + proto.RegisterMapType((map[string]string)(nil), "k8s.io.metrics.pkg.apis.external_metrics.v1beta1.ExternalMetricValue.MetricLabelsEntry") + proto.RegisterType((*ExternalMetricValueList)(nil), "k8s.io.metrics.pkg.apis.external_metrics.v1beta1.ExternalMetricValueList") +} + +func init() { + proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto", fileDescriptor_76ac204ccf814641) +} + +var fileDescriptor_76ac204ccf814641 = []byte{ + // 554 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4d, 0x6b, 0x1b, 0x3d, + 0x10, 0xc7, 0x2d, 0xfb, 0xf1, 0x43, 0xac, 0x24, 0x10, 0xab, 0x81, 0x1a, 0x1f, 0xd6, 0x26, 0x27, + 0xb7, 0x50, 0x29, 0x36, 0xa5, 0x84, 0x5e, 0x0a, 0x0b, 0x3e, 0x14, 0xe2, 0x42, 0x37, 0x21, 0xa1, + 0x2f, 0x50, 0xe4, 0xf5, 0x74, 0xad, 0xda, 0xfb, 0x82, 0xa4, 0x75, 0xea, 0x5b, 0x3f, 0x42, 0xfb, + 0xad, 0x7c, 0xcc, 0x31, 0x27, 0x53, 0x6f, 0x3e, 0x46, 0x2f, 0x65, 0xdf, 0x62, 0xd7, 0x4e, 0x13, + 0x02, 0xbd, 0xed, 0x68, 0x34, 0xff, 0xf9, 0xcd, 0x5f, 0xc3, 0xe2, 0x77, 0xa3, 0x23, 0x45, 0x85, + 0xcf, 0x46, 0x61, 0x1f, 0xa4, 0x07, 0x1a, 0x14, 0x9b, 0x80, 0x37, 0xf0, 0x25, 0xcb, 0x12, 0x2e, + 0x68, 0x29, 0x6c, 0xc5, 0x82, 0x91, 0xc3, 0x78, 0x20, 0x14, 0x83, 0xaf, 0x1a, 0xa4, 0xc7, 0xc7, + 0x9f, 0xf2, 0xcc, 0xa4, 0xdd, 0x07, 0xcd, 0xdb, 0xcc, 0x01, 0x0f, 0x24, 0xd7, 0x30, 0xa0, 0x81, + 0xf4, 0xb5, 0x4f, 0x0e, 0x53, 0x05, 0x9a, 0xdd, 0xa3, 0xc1, 0xc8, 0xa1, 0xb1, 0x02, 0x5d, 0x57, + 0xa0, 0x99, 0x42, 0xfd, 0x99, 0x23, 0xf4, 0x30, 0xec, 0x53, 0xdb, 0x77, 0x99, 0xe3, 0x3b, 0x3e, + 0x4b, 0x84, 0xfa, 0xe1, 0xe7, 0x24, 0x4a, 0x82, 0xe4, 0x2b, 0x6d, 0x50, 0x7f, 0x9e, 0x21, 0xf2, + 0x40, 0xb8, 0xdc, 0x1e, 0x0a, 0x0f, 0xe4, 0x34, 0xe7, 0x64, 0x12, 0x94, 0x1f, 0x4a, 0x1b, 0xd6, + 0xb1, 0xee, 0xac, 0x52, 0xf1, 0xb8, 0x9c, 0x4d, 0x36, 0x86, 0xa9, 0xb3, 0xbf, 0x55, 0xc9, 0xd0, + 0xd3, 0xc2, 0xdd, 0x6c, 0xf3, 0xe2, 0xbe, 0x02, 0x65, 0x0f, 0xc1, 0xe5, 0xeb, 0x75, 0x07, 0xbf, + 0x4a, 0xf8, 0x51, 0x37, 0x33, 0xa8, 0x97, 0xf8, 0x73, 0xc6, 0xc7, 0x21, 0x90, 0x0e, 0xc6, 0xa9, + 0x5d, 0x6f, 0xb8, 0x0b, 0x35, 0xd4, 0x44, 0xad, 0x8a, 0x49, 0x66, 0xf3, 0x46, 0x21, 0x9a, 0x37, + 0x70, 0xef, 0x26, 0x63, 0xad, 0xdc, 0x22, 0x3f, 0x10, 0xde, 0x49, 0xc3, 0x63, 0xde, 0x87, 0xb1, + 0xaa, 0x15, 0x9b, 0xa5, 0xd6, 0x76, 0xe7, 0x9c, 0x3e, 0xf4, 0x65, 0xe8, 0x2d, 0x44, 0xb4, 0xb7, + 0xa2, 0xdc, 0xf5, 0xb4, 0x9c, 0x9a, 0xfb, 0x19, 0xcf, 0xce, 0x6a, 0xca, 0xfa, 0x03, 0x81, 0x7c, + 0xc0, 0x95, 0x78, 0x7c, 0xa5, 0xb9, 0x1b, 0xd4, 0x4a, 0x4d, 0xd4, 0xda, 0xee, 0x3c, 0xcd, 0x79, + 0x56, 0xbd, 0x5a, 0x42, 0xc5, 0x4f, 0x42, 0x27, 0x6d, 0x7a, 0x2a, 0x5c, 0x30, 0xab, 0x59, 0x8b, + 0xca, 0x69, 0x2e, 0x62, 0x2d, 0xf5, 0xc8, 0x13, 0xfc, 0xff, 0x85, 0xf0, 0x06, 0xfe, 0x45, 0xed, + 0xbf, 0x26, 0x6a, 0x95, 0xcc, 0x6a, 0x34, 0x6f, 0xec, 0x9e, 0x27, 0x27, 0x27, 0x60, 0xfb, 0xde, + 0x40, 0x59, 0xd9, 0x05, 0x72, 0x82, 0xcb, 0x93, 0x78, 0x8c, 0x5a, 0x39, 0x61, 0xa0, 0x77, 0x31, + 0xd0, 0x7c, 0x99, 0xe8, 0xdb, 0x90, 0x7b, 0x5a, 0xe8, 0xa9, 0xb9, 0x9b, 0x71, 0x94, 0x13, 0x2f, + 0xac, 0x54, 0xab, 0xfe, 0x0a, 0x57, 0x37, 0x5c, 0x21, 0x7b, 0xb8, 0x34, 0x82, 0x69, 0xfa, 0x64, + 0x56, 0xfc, 0x49, 0xf6, 0xf3, 0xde, 0xc5, 0xe4, 0x2c, 0x0d, 0x5e, 0x16, 0x8f, 0xd0, 0xc1, 0x35, + 0xc2, 0x8f, 0x6f, 0xf1, 0xfa, 0x58, 0x28, 0x4d, 0x3e, 0xe2, 0xad, 0xd8, 0x8a, 0x01, 0xd7, 0x3c, + 0x11, 0xbb, 0x07, 0x7a, 0x69, 0x5c, 0x5c, 0xdd, 0x03, 0xcd, 0xcd, 0xbd, 0x0c, 0x7a, 0x2b, 0x3f, + 0xb1, 0x6e, 0x14, 0xc9, 0x17, 0x5c, 0x16, 0x1a, 0xdc, 0x7c, 0x47, 0xba, 0xff, 0x64, 0x47, 0x96, + 0x36, 0xbd, 0x8e, 0xb5, 0xad, 0xb4, 0x85, 0x79, 0x36, 0x5b, 0x18, 0x85, 0xcb, 0x85, 0x51, 0xb8, + 0x5a, 0x18, 0x85, 0x6f, 0x91, 0x81, 0x66, 0x91, 0x81, 0x2e, 0x23, 0x03, 0x5d, 0x45, 0x06, 0xfa, + 0x19, 0x19, 0xe8, 0xfb, 0xb5, 0x51, 0x78, 0x7f, 0xf8, 0xd0, 0x3f, 0xd0, 0xef, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x49, 0x7d, 0xf4, 0x2a, 0xcd, 0x04, 0x00, 0x00, +} + +func (m *ExternalMetricValue) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExternalMetricValue) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExternalMetricValue) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Value.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if m.WindowSeconds != nil { + i = encodeVarintGenerated(dAtA, i, uint64(*m.WindowSeconds)) + i-- + dAtA[i] = 0x20 + } + { + size, err := m.Timestamp.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.MetricLabels) > 0 { + keysForMetricLabels := make([]string, 0, len(m.MetricLabels)) + for k := range m.MetricLabels { + keysForMetricLabels = append(keysForMetricLabels, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForMetricLabels) + for iNdEx := len(keysForMetricLabels) - 1; iNdEx >= 0; iNdEx-- { + v := m.MetricLabels[string(keysForMetricLabels[iNdEx])] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintGenerated(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(keysForMetricLabels[iNdEx]) + copy(dAtA[i:], keysForMetricLabels[iNdEx]) + i = encodeVarintGenerated(dAtA, i, uint64(len(keysForMetricLabels[iNdEx]))) + i-- + dAtA[i] = 0xa + i = encodeVarintGenerated(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + i -= len(m.MetricName) + copy(dAtA[i:], m.MetricName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.MetricName))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ExternalMetricValueList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExternalMetricValueList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExternalMetricValueList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Items) > 0 { + for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { + offset -= sovGenerated(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ExternalMetricValue) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MetricName) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.MetricLabels) > 0 { + for k, v := range m.MetricLabels { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + l = m.Timestamp.Size() + n += 1 + l + sovGenerated(uint64(l)) + if m.WindowSeconds != nil { + n += 1 + sovGenerated(uint64(*m.WindowSeconds)) + } + l = m.Value.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ExternalMetricValueList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func sovGenerated(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenerated(x uint64) (n int) { + return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *ExternalMetricValue) String() string { + if this == nil { + return "nil" + } + keysForMetricLabels := make([]string, 0, len(this.MetricLabels)) + for k := range this.MetricLabels { + keysForMetricLabels = append(keysForMetricLabels, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForMetricLabels) + mapStringForMetricLabels := "map[string]string{" + for _, k := range keysForMetricLabels { + mapStringForMetricLabels += fmt.Sprintf("%v: %v,", k, this.MetricLabels[k]) + } + mapStringForMetricLabels += "}" + s := strings.Join([]string{`&ExternalMetricValue{`, + `MetricName:` + fmt.Sprintf("%v", this.MetricName) + `,`, + `MetricLabels:` + mapStringForMetricLabels + `,`, + `Timestamp:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Timestamp), "Time", "v1.Time", 1), `&`, ``, 1) + `,`, + `WindowSeconds:` + valueToStringGenerated(this.WindowSeconds) + `,`, + `Value:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Value), "Quantity", "resource.Quantity", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ExternalMetricValueList) String() string { + if this == nil { + return "nil" + } + repeatedStringForItems := "[]ExternalMetricValue{" + for _, f := range this.Items { + repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "ExternalMetricValue", "ExternalMetricValue", 1), `&`, ``, 1) + "," + } + repeatedStringForItems += "}" + s := strings.Join([]string{`&ExternalMetricValueList{`, + `ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v1.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + repeatedStringForItems + `,`, + `}`, + }, "") + return s +} +func valueToStringGenerated(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *ExternalMetricValue) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExternalMetricValue: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExternalMetricValue: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MetricName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MetricName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MetricLabels", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MetricLabels == nil { + m.MetricLabels = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.MetricLabels[mapkey] = mapvalue + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Timestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field WindowSeconds", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.WindowSeconds = &v + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Value.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExternalMetricValueList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExternalMetricValueList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExternalMetricValueList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, ExternalMetricValue{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenerated(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenerated + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenerated + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenerated + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenerated = fmt.Errorf("proto: unexpected end of group") +) diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto new file mode 100644 index 000000000000..c5552ac79548 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/generated.proto @@ -0,0 +1,62 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +// This file was autogenerated by go-to-protobuf. Do not edit it manually! + +syntax = "proto2"; + +package k8s.io.metrics.pkg.apis.external_metrics.v1beta1; + +import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; +import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; + +// Package-wide variables from generator "generated". +option go_package = "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"; + +// ExternalMetricValue is a metric value for external metric +// A single metric value is identified by metric name and a set of string labels. +// For one metric there can be multiple values with different sets of labels. +message ExternalMetricValue { + // the name of the metric + optional string metricName = 1; + + // a set of labels that identify a single time series for the metric + map metricLabels = 2; + + // indicates the time at which the metrics were produced + optional k8s.io.apimachinery.pkg.apis.meta.v1.Time timestamp = 3; + + // indicates the window ([Timestamp-Window, Timestamp]) from + // which these metrics were calculated, when returning rate + // metrics calculated from cumulative metrics (or zero for + // non-calculated instantaneous metrics). + optional int64 window = 4; + + // the value of the metric + optional k8s.io.apimachinery.pkg.api.resource.Quantity value = 5; +} + +// ExternalMetricValueList is a list of values for a given metric for some set labels +message ExternalMetricValueList { + optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + // value of the metric matching a given set of labels + repeated ExternalMetricValue items = 2; +} + diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/register.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/register.go new file mode 100644 index 000000000000..85dfc5b1d9dd --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/register.go @@ -0,0 +1,51 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "external.metrics.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder points to a list of functions added to Scheme. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + localSchemeBuilder = &SchemeBuilder + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = localSchemeBuilder.AddToScheme +) + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ExternalMetricValue{}, + &ExternalMetricValueList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/types.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/types.go new file mode 100644 index 000000000000..56210539a5b0 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/types.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExternalMetricValueList is a list of values for a given metric for some set labels +type ExternalMetricValueList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // value of the metric matching a given set of labels + Items []ExternalMetricValue `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExternalMetricValue is a metric value for external metric +// A single metric value is identified by metric name and a set of string labels. +// For one metric there can be multiple values with different sets of labels. +type ExternalMetricValue struct { + metav1.TypeMeta `json:",inline"` + + // the name of the metric + MetricName string `json:"metricName" protobuf:"bytes,1,name=metricName"` + + // a set of labels that identify a single time series for the metric + MetricLabels map[string]string `json:"metricLabels" protobuf:"bytes,2,rep,name=metricLabels"` + + // indicates the time at which the metrics were produced + Timestamp metav1.Time `json:"timestamp" protobuf:"bytes,3,name=timestamp"` + + // indicates the window ([Timestamp-Window, Timestamp]) from + // which these metrics were calculated, when returning rate + // metrics calculated from cumulative metrics (or zero for + // non-calculated instantaneous metrics). + WindowSeconds *int64 `json:"window,omitempty" protobuf:"bytes,4,opt,name=window"` + + // the value of the metric + Value resource.Quantity `json:"value" protobuf:"bytes,5,name=value"` +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.conversion.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.conversion.go new file mode 100644 index 000000000000..0380ace59162 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.conversion.go @@ -0,0 +1,110 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1beta1 + +import ( + unsafe "unsafe" + + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + externalmetrics "k8s.io/metrics/pkg/apis/external_metrics" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*ExternalMetricValue)(nil), (*externalmetrics.ExternalMetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ExternalMetricValue_To_external_metrics_ExternalMetricValue(a.(*ExternalMetricValue), b.(*externalmetrics.ExternalMetricValue), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*externalmetrics.ExternalMetricValue)(nil), (*ExternalMetricValue)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_external_metrics_ExternalMetricValue_To_v1beta1_ExternalMetricValue(a.(*externalmetrics.ExternalMetricValue), b.(*ExternalMetricValue), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ExternalMetricValueList)(nil), (*externalmetrics.ExternalMetricValueList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ExternalMetricValueList_To_external_metrics_ExternalMetricValueList(a.(*ExternalMetricValueList), b.(*externalmetrics.ExternalMetricValueList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*externalmetrics.ExternalMetricValueList)(nil), (*ExternalMetricValueList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_external_metrics_ExternalMetricValueList_To_v1beta1_ExternalMetricValueList(a.(*externalmetrics.ExternalMetricValueList), b.(*ExternalMetricValueList), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_ExternalMetricValue_To_external_metrics_ExternalMetricValue(in *ExternalMetricValue, out *externalmetrics.ExternalMetricValue, s conversion.Scope) error { + out.MetricName = in.MetricName + out.MetricLabels = *(*map[string]string)(unsafe.Pointer(&in.MetricLabels)) + out.Timestamp = in.Timestamp + out.WindowSeconds = (*int64)(unsafe.Pointer(in.WindowSeconds)) + out.Value = in.Value + return nil +} + +// Convert_v1beta1_ExternalMetricValue_To_external_metrics_ExternalMetricValue is an autogenerated conversion function. +func Convert_v1beta1_ExternalMetricValue_To_external_metrics_ExternalMetricValue(in *ExternalMetricValue, out *externalmetrics.ExternalMetricValue, s conversion.Scope) error { + return autoConvert_v1beta1_ExternalMetricValue_To_external_metrics_ExternalMetricValue(in, out, s) +} + +func autoConvert_external_metrics_ExternalMetricValue_To_v1beta1_ExternalMetricValue(in *externalmetrics.ExternalMetricValue, out *ExternalMetricValue, s conversion.Scope) error { + out.MetricName = in.MetricName + out.MetricLabels = *(*map[string]string)(unsafe.Pointer(&in.MetricLabels)) + out.Timestamp = in.Timestamp + out.WindowSeconds = (*int64)(unsafe.Pointer(in.WindowSeconds)) + out.Value = in.Value + return nil +} + +// Convert_external_metrics_ExternalMetricValue_To_v1beta1_ExternalMetricValue is an autogenerated conversion function. +func Convert_external_metrics_ExternalMetricValue_To_v1beta1_ExternalMetricValue(in *externalmetrics.ExternalMetricValue, out *ExternalMetricValue, s conversion.Scope) error { + return autoConvert_external_metrics_ExternalMetricValue_To_v1beta1_ExternalMetricValue(in, out, s) +} + +func autoConvert_v1beta1_ExternalMetricValueList_To_external_metrics_ExternalMetricValueList(in *ExternalMetricValueList, out *externalmetrics.ExternalMetricValueList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]externalmetrics.ExternalMetricValue)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_v1beta1_ExternalMetricValueList_To_external_metrics_ExternalMetricValueList is an autogenerated conversion function. +func Convert_v1beta1_ExternalMetricValueList_To_external_metrics_ExternalMetricValueList(in *ExternalMetricValueList, out *externalmetrics.ExternalMetricValueList, s conversion.Scope) error { + return autoConvert_v1beta1_ExternalMetricValueList_To_external_metrics_ExternalMetricValueList(in, out, s) +} + +func autoConvert_external_metrics_ExternalMetricValueList_To_v1beta1_ExternalMetricValueList(in *externalmetrics.ExternalMetricValueList, out *ExternalMetricValueList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + out.Items = *(*[]ExternalMetricValue)(unsafe.Pointer(&in.Items)) + return nil +} + +// Convert_external_metrics_ExternalMetricValueList_To_v1beta1_ExternalMetricValueList is an autogenerated conversion function. +func Convert_external_metrics_ExternalMetricValueList_To_v1beta1_ExternalMetricValueList(in *externalmetrics.ExternalMetricValueList, out *ExternalMetricValueList, s conversion.Scope) error { + return autoConvert_external_metrics_ExternalMetricValueList_To_v1beta1_ExternalMetricValueList(in, out, s) +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.deepcopy.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 000000000000..45c653f6d067 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,98 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1beta1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExternalMetricValue) DeepCopyInto(out *ExternalMetricValue) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.MetricLabels != nil { + in, out := &in.MetricLabels, &out.MetricLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + in.Timestamp.DeepCopyInto(&out.Timestamp) + if in.WindowSeconds != nil { + in, out := &in.WindowSeconds, &out.WindowSeconds + *out = new(int64) + **out = **in + } + out.Value = in.Value.DeepCopy() + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalMetricValue. +func (in *ExternalMetricValue) DeepCopy() *ExternalMetricValue { + if in == nil { + return nil + } + out := new(ExternalMetricValue) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExternalMetricValue) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExternalMetricValueList) DeepCopyInto(out *ExternalMetricValueList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ExternalMetricValue, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalMetricValueList. +func (in *ExternalMetricValueList) DeepCopy() *ExternalMetricValueList { + if in == nil { + return nil + } + out := new(ExternalMetricValueList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExternalMetricValueList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/zz_generated.deepcopy.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/zz_generated.deepcopy.go new file mode 100644 index 000000000000..e79ff826841d --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/apis/external_metrics/zz_generated.deepcopy.go @@ -0,0 +1,98 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package external_metrics + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExternalMetricValue) DeepCopyInto(out *ExternalMetricValue) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.MetricLabels != nil { + in, out := &in.MetricLabels, &out.MetricLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + in.Timestamp.DeepCopyInto(&out.Timestamp) + if in.WindowSeconds != nil { + in, out := &in.WindowSeconds, &out.WindowSeconds + *out = new(int64) + **out = **in + } + out.Value = in.Value.DeepCopy() + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalMetricValue. +func (in *ExternalMetricValue) DeepCopy() *ExternalMetricValue { + if in == nil { + return nil + } + out := new(ExternalMetricValue) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExternalMetricValue) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExternalMetricValueList) DeepCopyInto(out *ExternalMetricValueList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ExternalMetricValue, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalMetricValueList. +func (in *ExternalMetricValueList) DeepCopy() *ExternalMetricValueList { + if in == nil { + return nil + } + out := new(ExternalMetricValueList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExternalMetricValueList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/client/external_metrics/client.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/client/external_metrics/client.go new file mode 100644 index 000000000000..d18d9e124780 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/client/external_metrics/client.go @@ -0,0 +1,100 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package external_metrics + +import ( + "context" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/client-go/util/flowcontrol" + "k8s.io/metrics/pkg/apis/external_metrics/v1beta1" +) + +type externalMetricsClient struct { + client rest.Interface +} + +func New(client rest.Interface) ExternalMetricsClient { + return &externalMetricsClient{ + client: client, + } +} + +func NewForConfig(c *rest.Config) (ExternalMetricsClient, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + configShallowCopy.APIPath = "/apis" + if configShallowCopy.UserAgent == "" { + configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() + } + configShallowCopy.GroupVersion = &v1beta1.SchemeGroupVersion + configShallowCopy.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + client, err := rest.RESTClientFor(&configShallowCopy) + if err != nil { + return nil, err + } + + return New(client), nil +} + +func NewForConfigOrDie(c *rest.Config) ExternalMetricsClient { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +func (c *externalMetricsClient) NamespacedMetrics(namespace string) MetricsInterface { + return &namespacedMetrics{ + client: c, + namespace: namespace, + } +} + +type namespacedMetrics struct { + client *externalMetricsClient + namespace string +} + +func (m *namespacedMetrics) List(metricName string, metricSelector labels.Selector) (*v1beta1.ExternalMetricValueList, error) { + res := &v1beta1.ExternalMetricValueList{} + err := m.client.client.Get(). + Namespace(m.namespace). + Resource(metricName). + VersionedParams(&metav1.ListOptions{ + LabelSelector: metricSelector.String(), + }, metav1.ParameterCodec). + Do(context.TODO()). + Into(res) + + if err != nil { + return nil, err + } + + return res, nil +} diff --git a/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/client/external_metrics/interfaces.go b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/client/external_metrics/interfaces.go new file mode 100644 index 000000000000..d98c161aaf49 --- /dev/null +++ b/vertical-pod-autoscaler/vendor/k8s.io/metrics/pkg/client/external_metrics/interfaces.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package external_metrics + +import ( + "k8s.io/apimachinery/pkg/labels" + "k8s.io/metrics/pkg/apis/external_metrics/v1beta1" +) + +// ExternalMetricsClient is a client for fetching external metrics. +type ExternalMetricsClient interface { + NamespacedMetricsGetter +} + +// NamespacedMetricsGetter provides access to an interface for fetching +// metrics in a particular namespace. +type NamespacedMetricsGetter interface { + NamespacedMetrics(namespace string) MetricsInterface +} + +// MetricsInterface provides access to external metrics. +type MetricsInterface interface { + // List fetches the metric for the given namespace that maches the given + // metricSelector. + List(metricName string, metricSelector labels.Selector) (*v1beta1.ExternalMetricValueList, error) +} diff --git a/vertical-pod-autoscaler/vendor/modules.txt b/vertical-pod-autoscaler/vendor/modules.txt index b218be2a9417..caed2c4ec3f4 100644 --- a/vertical-pod-autoscaler/vendor/modules.txt +++ b/vertical-pod-autoscaler/vendor/modules.txt @@ -652,6 +652,8 @@ k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/validation/spec # k8s.io/metrics v0.25.0 => k8s.io/metrics v0.26.1 ## explicit; go 1.19 +k8s.io/metrics/pkg/apis/external_metrics +k8s.io/metrics/pkg/apis/external_metrics/v1beta1 k8s.io/metrics/pkg/apis/metrics k8s.io/metrics/pkg/apis/metrics/v1alpha1 k8s.io/metrics/pkg/apis/metrics/v1beta1