diff --git a/go.mod b/go.mod index e542917cee..82b9990e1a 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( gopkg.in/inf.v0 v0.9.0 // indirect k8s.io/api v0.0.0-20190313235455-40a48860b5ab k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1 + k8s.io/autoscaler v0.0.0-20190612121530-8bb2354d9af9 k8s.io/client-go v2.0.0-alpha.0.0.20190313235726-6ee68ca5fd83+incompatible k8s.io/klog v0.3.0 k8s.io/kube-openapi v0.0.0-20190320154901-5e45bb682580 // indirect diff --git a/go.sum b/go.sum index b75b07cfe8..5e0d5714c3 100644 --- a/go.sum +++ b/go.sum @@ -111,6 +111,8 @@ k8s.io/api v0.0.0-20190313235455-40a48860b5ab h1:DG9A67baNpoeweOy2spF1OWHhnVY5KR k8s.io/api v0.0.0-20190313235455-40a48860b5ab/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1 h1:IS7K02iBkQXpCeieSiyJjGoLSdVOv2DbPaWHJ+ZtgKg= k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/autoscaler v0.0.0-20190612121530-8bb2354d9af9 h1:+GB3VH3tw7T8PZw4RPa9XLmYdqTnSB3qa/Zern1bhOk= +k8s.io/autoscaler v0.0.0-20190612121530-8bb2354d9af9/go.mod h1:QEXezc9uKPT91dwqhSJq3GNI3B1HxFRQHiku9kmrsSA= k8s.io/client-go v2.0.0-alpha.0.0.20190313235726-6ee68ca5fd83+incompatible h1:+SiikveGdttGGsPhWZsGg+RD1ziNvr+PL8zKqLDIrbE= k8s.io/client-go v2.0.0-alpha.0.0.20190313235726-6ee68ca5fd83+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= diff --git a/internal/store/builder.go b/internal/store/builder.go index f13102dd1b..af22890e49 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -32,7 +32,9 @@ import ( extensions "k8s.io/api/extensions/v1beta1" policy "k8s.io/api/policy/v1beta1" storagev1 "k8s.io/api/storage/v1" + vpaautoscaling "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2" clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/kube-state-metrics/pkg/metric" metricsstore "k8s.io/kube-state-metrics/pkg/metrics_store" @@ -48,6 +50,7 @@ type whiteBlackLister interface { // (https://en.wikipedia.org/wiki/Builder_pattern). type Builder struct { kubeClient clientset.Interface + kubeCfg *rest.Config namespaces options.NamespaceList ctx context.Context enabledResources []string @@ -83,6 +86,11 @@ func (b *Builder) WithKubeClient(c clientset.Interface) { b.kubeClient = c } +// WithKubeCfg sets the kubeCfg property of a Builder. +func (b *Builder) WithKubeCfg(c *rest.Config) { + b.kubeCfg = c +} + // WithWhiteBlackList configures the white or blacklisted metric to be exposed // by the store build by the Builder. func (b *Builder) WithWhiteBlackList(l whiteBlackLister) { @@ -136,6 +144,7 @@ var availableStores = map[string]func(f *Builder) *metricsstore.MetricsStore{ "services": func(b *Builder) *metricsstore.MetricsStore { return b.buildServiceStore() }, "statefulsets": func(b *Builder) *metricsstore.MetricsStore { return b.buildStatefulSetStore() }, "storageclasses": func(b *Builder) *metricsstore.MetricsStore { return b.buildStorageClassStore() }, + "verticalpodautoscalers": func(b *Builder) *metricsstore.MetricsStore { return b.buildVPAStore() }, } func (b *Builder) buildConfigMapStore() *metricsstore.MetricsStore { @@ -230,6 +239,10 @@ func (b *Builder) buildCsrStore() *metricsstore.MetricsStore { return b.buildStore(csrMetricFamilies, &certv1beta1.CertificateSigningRequest{}, createCSRListWatch) } +func (b *Builder) buildVPAStore() *metricsstore.MetricsStore { + return b.buildStore(vpaMetricFamilies, &vpaautoscaling.VerticalPodAutoscaler{}, createVPAListWatchFunc(b.kubeCfg)) +} + func (b *Builder) buildStore( metricFamilies []metric.FamilyGenerator, expectedType interface{}, diff --git a/internal/store/vpa.go b/internal/store/vpa.go new file mode 100644 index 0000000000..e99d96e295 --- /dev/null +++ b/internal/store/vpa.go @@ -0,0 +1,421 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +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 store + +import ( + "fmt" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + + autoscaling "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2" + vpaclientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/cache" + "k8s.io/kube-state-metrics/pkg/metric" +) + +var ( + descVerticalPodAutoscalerLabelsName = "kube_vpa_labels" + descVerticalPodAutoscalerLabelsHelp = "Kubernetes labels converted to Prometheus labels." + descVerticalPodAutoscalerLabelsDefaultLabels = []string{"namespace", "vpa", "targetRef"} + + vpaMetricFamilies = []metric.FamilyGenerator{ + { + Name: descVerticalPodAutoscalerLabelsName, + Type: metric.Gauge, + Help: descVerticalPodAutoscalerLabelsHelp, + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + labelKeys, labelValues := kubeLabelsToPrometheusLabels(a.Labels) + return &metric.Family{ + Metrics: []*metric.Metric{ + { + LabelKeys: labelKeys, + LabelValues: labelValues, + Value: 1, + }, + }, + } + }), + }, + { + Name: "kube_vpa_update_mode", + Type: metric.Gauge, + Help: "Update mode of the VPA.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + + if a.Spec.UpdatePolicy.UpdateMode == nil { + return &metric.Family{ + Metrics: ms, + } + } + + for _, mode := range []autoscaling.UpdateMode{ + autoscaling.UpdateModeOff, + autoscaling.UpdateModeInitial, + autoscaling.UpdateModeRecreate, + autoscaling.UpdateModeAuto, + } { + var v float64 + if *a.Spec.UpdatePolicy.UpdateMode == mode { + v = 1 + } else { + v = 0 + } + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"update_mode"}, + LabelValues: []string{string(mode)}, + Value: v, + }) + } + + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_resource_policy_min_cpu_cores", + Type: metric.Gauge, + Help: "Minimum CPU cores the VPA can set for containers matching the name.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + for _, c := range a.Spec.ResourcePolicy.ContainerPolicies { + min := c.MinAllowed + if cpu, ok := min[v1.ResourceCPU]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(cpu.MilliValue()) / 1000, + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_resource_policy_min_memory_bytes", + Type: metric.Gauge, + Help: "Minimum memory bytes the VPA can set for containers matching the name.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + for _, c := range a.Spec.ResourcePolicy.ContainerPolicies { + min := c.MinAllowed + if mem, ok := min[v1.ResourceMemory]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(mem.Value()), + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_resource_policy_max_cpu_cores", + Type: metric.Gauge, + Help: "Maximum CPU cores the VPA can set for containers matching the name.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + for _, c := range a.Spec.ResourcePolicy.ContainerPolicies { + max := c.MaxAllowed + if cpu, ok := max[v1.ResourceCPU]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(cpu.MilliValue()) / 1000, + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_resource_policy_max_memory_bytes", + Type: metric.Gauge, + Help: "Maximum memory bytes the VPA can set for containers matching the name.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + for _, c := range a.Spec.ResourcePolicy.ContainerPolicies { + max := c.MaxAllowed + if mem, ok := max[v1.ResourceMemory]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(mem.Value()), + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_lower_bound_cpu_cores", + Type: metric.Gauge, + Help: "Minimum CPU cores the container can use before the VPA updater evicts it.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.LowerBound + if cpu, ok := v[v1.ResourceCPU]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(cpu.MilliValue()) / 1000, + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_lower_bound_memory_bytes", + Type: metric.Gauge, + Help: "Minimum memory bytes the container can use before the VPA updater evicts it.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.LowerBound + if mem, ok := v[v1.ResourceMemory]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(mem.Value()), + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_upper_bound_cpu_cores", + Type: metric.Gauge, + Help: "Maximum CPU cores the container can use before the VPA updater evicts it.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.UpperBound + if cpu, ok := v[v1.ResourceCPU]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(cpu.MilliValue()) / 1000, + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_upper_bound_memory_bytes", + Type: metric.Gauge, + Help: "Maximum memory bytes the container can use before the VPA updater evicts it.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.UpperBound + if mem, ok := v[v1.ResourceMemory]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(mem.Value()), + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_target_cpu_cores", + Type: metric.Gauge, + Help: "Target CPU cores the VPA recommends for the container.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.Target + if cpu, ok := v[v1.ResourceCPU]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(cpu.MilliValue()) / 1000, + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_target_memory_bytes", + Type: metric.Gauge, + Help: "Target memory bytes the VPA recommends for the container.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.Target + if mem, ok := v[v1.ResourceMemory]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(mem.Value()), + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_uncapped_target_cpu_cores", + Type: metric.Gauge, + Help: "Target CPU cores the VPA recommends for the container ignoring bounds.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.UncappedTarget + if cpu, ok := v[v1.ResourceCPU]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(cpu.MilliValue()) / 1000, + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + { + Name: "kube_vpa_container_status_recommendation_uncapped_target_memory_bytes", + Type: metric.Gauge, + Help: "Target memory bytes the VPA recommends for the container ignoring bounds.", + GenerateFunc: wrapVPAFunc(func(a *autoscaling.VerticalPodAutoscaler) *metric.Family { + ms := []*metric.Metric{} + if a.Status.Recommendation == nil || a.Status.Recommendation.ContainerRecommendations == nil { + return &metric.Family{ + Metrics: ms, + } + } + for _, c := range a.Status.Recommendation.ContainerRecommendations { + v := c.UncappedTarget + if mem, ok := v[v1.ResourceMemory]; ok { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{"container_name"}, + LabelValues: []string{c.ContainerName}, + Value: float64(mem.Value()), + }) + } + } + return &metric.Family{ + Metrics: ms, + } + }), + }, + } +) + +func wrapVPAFunc(f func(*autoscaling.VerticalPodAutoscaler) *metric.Family) func(interface{}) *metric.Family { + return func(obj interface{}) *metric.Family { + vpa := obj.(*autoscaling.VerticalPodAutoscaler) + + metricFamily := f(vpa) + targetRef := fmt.Sprintf("%s/%s/%s", vpa.Spec.TargetRef.APIVersion, vpa.Spec.TargetRef.Kind, vpa.Spec.TargetRef.Name) + + for _, m := range metricFamily.Metrics { + m.LabelKeys = append(descVerticalPodAutoscalerLabelsDefaultLabels, m.LabelKeys...) + m.LabelValues = append([]string{vpa.Namespace, vpa.Name, targetRef}, m.LabelValues...) + } + + return metricFamily + } +} + +func createVPAListWatchFunc(kubeCfg *rest.Config) func(kubeClient clientset.Interface, ns string) cache.ListerWatcher { + vpaClient, err := vpaclientset.NewForConfig(kubeCfg) + if err != nil { + panic(fmt.Sprintf("error creating VerticalPodAutoscaler client: %s", err.Error())) + } + return func(kubeClient clientset.Interface, ns string) cache.ListerWatcher { + return &cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { + return vpaClient.AutoscalingV1beta2().VerticalPodAutoscalers(ns).List(opts) + }, + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { + return vpaClient.AutoscalingV1beta2().VerticalPodAutoscalers(ns).Watch(opts) + }, + } + } +} diff --git a/internal/store/vpa_test.go b/internal/store/vpa_test.go new file mode 100644 index 0000000000..638f38d0dc --- /dev/null +++ b/internal/store/vpa_test.go @@ -0,0 +1,132 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +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 store + +import ( + "testing" + + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + k8sautoscaling "k8s.io/api/autoscaling/v1" + autoscaling "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2" + "k8s.io/kube-state-metrics/pkg/metric" +) + +func TestVPAStore(t *testing.T) { + + const metadata = ` + ` + + updateMode := autoscaling.UpdateModeRecreate + + v1Resource := func(cpu, mem string) v1.ResourceList { + return v1.ResourceList{ + v1.ResourceCPU: resource.MustParse(cpu), + v1.ResourceMemory: resource.MustParse(mem), + } + } + + cases := []generateMetricsTestCase{ + { + Obj: &autoscaling.VerticalPodAutoscaler{ + ObjectMeta: metav1.ObjectMeta{ + Generation: 2, + Name: "vpa1", + Namespace: "ns1", + Labels: map[string]string{ + "app": "foobar", + }, + }, + Spec: autoscaling.VerticalPodAutoscalerSpec{ + TargetRef: &k8sautoscaling.CrossVersionObjectReference{ + APIVersion: "extensions/v1beta1", + Kind: "Deployment", + Name: "deployment1", + }, + UpdatePolicy: &autoscaling.PodUpdatePolicy{ + UpdateMode: &updateMode, + }, + ResourcePolicy: &autoscaling.PodResourcePolicy{ + ContainerPolicies: []autoscaling.ContainerResourcePolicy{ + { + ContainerName: "*", + MinAllowed: v1Resource("1", "4Gi"), + MaxAllowed: v1Resource("4", "8Gi"), + }, + }, + }, + }, + Status: autoscaling.VerticalPodAutoscalerStatus{ + Recommendation: &autoscaling.RecommendedPodResources{ + ContainerRecommendations: []autoscaling.RecommendedContainerResources{ + { + ContainerName: "container1", + LowerBound: v1Resource("1", "4Gi"), + UpperBound: v1Resource("4", "8Gi"), + Target: v1Resource("3", "7Gi"), + UncappedTarget: v1Resource("6", "10Gi"), + }, + }, + }, + }, + }, + Want: ` + kube_vpa_container_resource_policy_max_cpu_cores{container_name="*",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 4 + kube_vpa_container_resource_policy_max_memory_bytes{container_name="*",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 8.589934592e+09 + kube_vpa_container_resource_policy_min_cpu_cores{container_name="*",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 1 + kube_vpa_container_resource_policy_min_memory_bytes{container_name="*",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 4.294967296e+09 + kube_vpa_container_status_recommendation_lower_bound_cpu_cores{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 1 + kube_vpa_container_status_recommendation_lower_bound_memory_bytes{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 4.294967296e+09 + kube_vpa_container_status_recommendation_target_cpu_cores{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 3 + kube_vpa_container_status_recommendation_target_memory_bytes{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 7.516192768e+09 + kube_vpa_container_status_recommendation_uncapped_target_cpu_cores{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 6 + kube_vpa_container_status_recommendation_uncapped_target_memory_bytes{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 1.073741824e+10 + kube_vpa_container_status_recommendation_upper_bound_cpu_cores{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 4 + kube_vpa_container_status_recommendation_upper_bound_memory_bytes{container_name="container1",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 8.589934592e+09 + kube_vpa_labels{label_app="foobar",namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",vpa="vpa1"} 1 + kube_vpa_update_mode{namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",update_mode="Auto",vpa="vpa1"} 0 + kube_vpa_update_mode{namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",update_mode="Initial",vpa="vpa1"} 0 + kube_vpa_update_mode{namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",update_mode="Off",vpa="vpa1"} 0 + kube_vpa_update_mode{namespace="ns1",targetRef="extensions/v1beta1/Deployment/deployment1",update_mode="Recreate",vpa="vpa1"} 1 + `, + MetricNames: []string{ + "kube_vpa_labels", + "kube_vpa_update_mode", + "kube_vpa_container_resource_policy_min_cpu_cores", + "kube_vpa_container_resource_policy_min_memory_bytes", + "kube_vpa_container_resource_policy_max_cpu_cores", + "kube_vpa_container_resource_policy_max_memory_bytes", + "kube_vpa_container_status_recommendation_lower_bound_cpu_cores", + "kube_vpa_container_status_recommendation_lower_bound_memory_bytes", + "kube_vpa_container_status_recommendation_upper_bound_cpu_cores", + "kube_vpa_container_status_recommendation_upper_bound_memory_bytes", + "kube_vpa_container_status_recommendation_target_cpu_cores", + "kube_vpa_container_status_recommendation_target_memory_bytes", + "kube_vpa_container_status_recommendation_uncapped_target_cpu_cores", + "kube_vpa_container_status_recommendation_uncapped_target_memory_bytes", + }, + }, + } + for i, c := range cases { + c.Func = metric.ComposeMetricGenFuncs(vpaMetricFamilies) + if err := c.run(); err != nil { + t.Errorf("unexpected collecting result in %vth run:\n%s", i, err) + } + } +} diff --git a/main.go b/main.go index d6b1128564..0bef2b93ba 100644 --- a/main.go +++ b/main.go @@ -36,6 +36,7 @@ import ( clientset "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/klog" "k8s.io/kube-state-metrics/internal/store" @@ -132,11 +133,12 @@ func main() { proc.StartReaper() - kubeClient, err := createKubeClient(opts.Apiserver, opts.Kubeconfig) + kubeClient, kubeCfg, err := createKubeClient(opts.Apiserver, opts.Kubeconfig) if err != nil { klog.Fatalf("Failed to create client: %v", err) } storeBuilder.WithKubeClient(kubeClient) + storeBuilder.WithKubeCfg(kubeCfg) ksmMetricsRegistry := prometheus.NewRegistry() ksmMetricsRegistry.Register(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) @@ -148,10 +150,10 @@ func main() { serveMetrics(stores, opts.Host, opts.Port, opts.EnableGZIPEncoding) } -func createKubeClient(apiserver string, kubeconfig string) (clientset.Interface, error) { +func createKubeClient(apiserver string, kubeconfig string) (clientset.Interface, *rest.Config, error) { config, err := clientcmd.BuildConfigFromFlags(apiserver, kubeconfig) if err != nil { - return nil, err + return nil, nil, err } config.UserAgent = version.GetVersion().String() @@ -160,7 +162,7 @@ func createKubeClient(apiserver string, kubeconfig string) (clientset.Interface, kubeClient, err := clientset.NewForConfig(config) if err != nil { - return nil, err + return nil, nil, err } // Informers don't seem to do a good job logging error messages when it @@ -169,13 +171,13 @@ func createKubeClient(apiserver string, kubeconfig string) (clientset.Interface, klog.Infof("Testing communication with server") v, err := kubeClient.Discovery().ServerVersion() if err != nil { - return nil, errors.Wrap(err, "ERROR communicating with apiserver") + return nil, nil, errors.Wrap(err, "ERROR communicating with apiserver") } klog.Infof("Running with Kubernetes cluster version: v%s.%s. git version: %s. git tree state: %s. commit: %s. platform: %s", v.Major, v.Minor, v.GitVersion, v.GitTreeState, v.GitCommit, v.Platform) klog.Infof("Communication with server successful") - return kubeClient, nil + return kubeClient, config, nil } func telemetryServer(registry prometheus.Gatherer, host string, port int) { diff --git a/pkg/options/collector.go b/pkg/options/collector.go index 56345c342a..bf2a67d27c 100644 --- a/pkg/options/collector.go +++ b/pkg/options/collector.go @@ -49,5 +49,6 @@ var ( "services": struct{}{}, "statefulsets": struct{}{}, "storageclasses": struct{}{}, + "verticalpodautoscalers": struct{}{}, } ) diff --git a/vendor/k8s.io/autoscaler/LICENSE b/vendor/k8s.io/autoscaler/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/k8s.io/autoscaler/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/doc.go b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/doc.go new file mode 100644 index 0000000000..bd274686bd --- /dev/null +++ b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2019 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,register + +// Package v1beta2 contains definitions of Vertical Pod Autoscaler related objects. +// +groupName=autoscaling.k8s.io +package v1beta2 diff --git a/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/register.go b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/register.go new file mode 100644 index 0000000000..c8328488c9 --- /dev/null +++ b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/register.go @@ -0,0 +1,58 @@ +/* +Copyright 2019 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 v1beta2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: "autoscaling.k8s.io", Version: "v1beta2"} + +// 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.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &VerticalPodAutoscaler{}, + &VerticalPodAutoscalerList{}, + &VerticalPodAutoscalerCheckpoint{}, + &VerticalPodAutoscalerCheckpointList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/types.go b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/types.go new file mode 100644 index 0000000000..74c73ba015 --- /dev/null +++ b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/types.go @@ -0,0 +1,339 @@ +/* +Copyright 2019 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 v1beta2 contains definitions of Vertical Pod Autoscaler related objects. +package v1beta2 + +import ( + autoscaling "k8s.io/api/autoscaling/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VerticalPodAutoscalerList is a list of VerticalPodAutoscaler objects. +type VerticalPodAutoscalerList struct { + metav1.TypeMeta `json:",inline"` + // metadata is the standard list metadata. + // +optional + metav1.ListMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"` + + // items is the list of vertical pod autoscaler objects. + Items []VerticalPodAutoscaler `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VerticalPodAutoscaler is the configuration for a vertical pod +// autoscaler, which automatically manages pod resources based on historical and +// real time resource utilization. +type VerticalPodAutoscaler struct { + metav1.TypeMeta `json:",inline"` + // Standard object metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Specification of the behavior of the autoscaler. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. + Spec VerticalPodAutoscalerSpec `json:"spec" protobuf:"bytes,2,name=spec"` + + // Current information about the autoscaler. + // +optional + Status VerticalPodAutoscalerStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// VerticalPodAutoscalerSpec is the specification of the behavior of the autoscaler. +type VerticalPodAutoscalerSpec struct { + + // TargetRef points to the controller managing the set of pods for the + // autoscaler to control - e.g. Deployment, StatefulSet. VerticalPodAutoscaler + // can be targeted at controller implementing scale subresource (the pod set is + // retrieved from the controller's ScaleStatus) or some well known controllers + // (e.g. for DaemonSet the pod set is read from the controller's spec). + // If VerticalPodAutoscaler cannot use specified target it will report + // ConfigUnsupported condition. + // Note that VerticalPodAutoscaler does not require full implementation + // of scale subresource - it will not use it to modify the replica count. + // The only thing retrieved is a label selector matching pods grouped by + // the target resource. + TargetRef *autoscaling.CrossVersionObjectReference `json:"targetRef" protobuf:"bytes,1,name=targetRef"` + + // Describes the rules on how changes are applied to the pods. + // If not specified, all fields in the `PodUpdatePolicy` are set to their + // default values. + // +optional + UpdatePolicy *PodUpdatePolicy `json:"updatePolicy,omitempty" protobuf:"bytes,2,opt,name=updatePolicy"` + + // Controls how the autoscaler computes recommended resources. + // The resource policy may be used to set constraints on the recommendations + // for individual containers. If not specified, the autoscaler computes recommended + // resources for all containers in the pod, without additional constraints. + // +optional + ResourcePolicy *PodResourcePolicy `json:"resourcePolicy,omitempty" protobuf:"bytes,3,opt,name=resourcePolicy"` +} + +// PodUpdatePolicy describes the rules on how changes are applied to the pods. +type PodUpdatePolicy struct { + // Controls when autoscaler applies changes to the pod resources. + // The default is 'Auto'. + // +optional + UpdateMode *UpdateMode `json:"updateMode,omitempty" protobuf:"bytes,1,opt,name=updateMode"` +} + +// UpdateMode controls when autoscaler applies changes to the pod resoures. +type UpdateMode string + +const ( + // UpdateModeOff means that autoscaler never changes Pod resources. + // The recommender still sets the recommended resources in the + // VerticalPodAutoscaler object. This can be used for a "dry run". + UpdateModeOff UpdateMode = "Off" + // UpdateModeInitial means that autoscaler only assigns resources on pod + // creation and does not change them during the lifetime of the pod. + UpdateModeInitial UpdateMode = "Initial" + // UpdateModeRecreate means that autoscaler assigns resources on pod + // creation and additionally can update them during the lifetime of the + // pod by deleting and recreating the pod. + UpdateModeRecreate UpdateMode = "Recreate" + // UpdateModeAuto means that autoscaler assigns resources on pod creation + // and additionally can update them during the lifetime of the pod, + // using any available update method. Currently this is equivalent to + // Recreate, which is the only available update method. + UpdateModeAuto UpdateMode = "Auto" +) + +// PodResourcePolicy controls how autoscaler computes the recommended resources +// for containers belonging to the pod. There can be at most one entry for every +// named container and optionally a single wildcard entry with `containerName` = '*', +// which handles all containers that don't have individual policies. +type PodResourcePolicy struct { + // Per-container resource policies. + // +optional + // +patchMergeKey=containerName + // +patchStrategy=merge + ContainerPolicies []ContainerResourcePolicy `json:"containerPolicies,omitempty" patchStrategy:"merge" patchMergeKey:"containerName" protobuf:"bytes,1,rep,name=containerPolicies"` +} + +// ContainerResourcePolicy controls how autoscaler computes the recommended +// resources for a specific container. +type ContainerResourcePolicy struct { + // Name of the container or DefaultContainerResourcePolicy, in which + // case the policy is used by the containers that don't have their own + // policy specified. + ContainerName string `json:"containerName,omitempty" protobuf:"bytes,1,opt,name=containerName"` + // Whether autoscaler is enabled for the container. The default is "Auto". + // +optional + Mode *ContainerScalingMode `json:"mode,omitempty" protobuf:"bytes,2,opt,name=mode"` + // Specifies the minimal amount of resources that will be recommended + // for the container. The default is no minimum. + // +optional + MinAllowed v1.ResourceList `json:"minAllowed,omitempty" protobuf:"bytes,3,rep,name=minAllowed,casttype=ResourceList,castkey=ResourceName"` + // Specifies the maximum amount of resources that will be recommended + // for the container. The default is no maximum. + // +optional + MaxAllowed v1.ResourceList `json:"maxAllowed,omitempty" protobuf:"bytes,4,rep,name=maxAllowed,casttype=ResourceList,castkey=ResourceName"` +} + +const ( + // DefaultContainerResourcePolicy can be passed as + // ContainerResourcePolicy.ContainerName to specify the default policy. + DefaultContainerResourcePolicy = "*" +) + +// ContainerScalingMode controls whether autoscaler is enabled for a specific +// container. +type ContainerScalingMode string + +const ( + // ContainerScalingModeAuto means autoscaling is enabled for a container. + ContainerScalingModeAuto ContainerScalingMode = "Auto" + // ContainerScalingModeOff means autoscaling is disabled for a container. + ContainerScalingModeOff ContainerScalingMode = "Off" +) + +// VerticalPodAutoscalerStatus describes the runtime state of the autoscaler. +type VerticalPodAutoscalerStatus struct { + // The most recently computed amount of resources recommended by the + // autoscaler for the controlled pods. + // +optional + Recommendation *RecommendedPodResources `json:"recommendation,omitempty" protobuf:"bytes,1,opt,name=recommendation"` + + // Conditions is the set of conditions required for this autoscaler to scale its target, + // and indicates whether or not those conditions are met. + // +optional + // +patchMergeKey=type + // +patchStrategy=merge + Conditions []VerticalPodAutoscalerCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,rep,name=conditions"` +} + +// RecommendedPodResources is the recommendation of resources computed by +// autoscaler. It contains a recommendation for each container in the pod +// (except for those with `ContainerScalingMode` set to 'Off'). +type RecommendedPodResources struct { + // Resources recommended by the autoscaler for each container. + // +optional + ContainerRecommendations []RecommendedContainerResources `json:"containerRecommendations,omitempty" protobuf:"bytes,1,rep,name=containerRecommendations"` +} + +// RecommendedContainerResources is the recommendation of resources computed by +// autoscaler for a specific container. Respects the container resource policy +// if present in the spec. In particular the recommendation is not produced for +// containers with `ContainerScalingMode` set to 'Off'. +type RecommendedContainerResources struct { + // Name of the container. + ContainerName string `json:"containerName,omitempty" protobuf:"bytes,1,opt,name=containerName"` + // Recommended amount of resources. Observes ContainerResourcePolicy. + Target v1.ResourceList `json:"target" protobuf:"bytes,2,rep,name=target,casttype=ResourceList,castkey=ResourceName"` + // Minimum recommended amount of resources. Observes ContainerResourcePolicy. + // This amount is not guaranteed to be sufficient for the application to operate in a stable way, however + // running with less resources is likely to have significant impact on performance/availability. + // +optional + LowerBound v1.ResourceList `json:"lowerBound,omitempty" protobuf:"bytes,3,rep,name=lowerBound,casttype=ResourceList,castkey=ResourceName"` + // Maximum recommended amount of resources. Observes ContainerResourcePolicy. + // Any resources allocated beyond this value are likely wasted. This value may be larger than the maximum + // amount of application is actually capable of consuming. + // +optional + UpperBound v1.ResourceList `json:"upperBound,omitempty" protobuf:"bytes,4,rep,name=upperBound,casttype=ResourceList,castkey=ResourceName"` + // The most recent recommended resources target computed by the autoscaler + // for the controlled pods, based only on actual resource usage, not taking + // into account the ContainerResourcePolicy. + // May differ from the Recommendation if the actual resource usage causes + // the target to violate the ContainerResourcePolicy (lower than MinAllowed + // or higher that MaxAllowed). + // Used only as status indication, will not affect actual resource assignment. + // +optional + UncappedTarget v1.ResourceList `json:"uncappedTarget,omitempty" protobuf:"bytes,5,opt,name=uncappedTarget"` +} + +// VerticalPodAutoscalerConditionType are the valid conditions of +// a VerticalPodAutoscaler. +type VerticalPodAutoscalerConditionType string + +var ( + // RecommendationProvided indicates whether the VPA recommender was able to calculate a recommendation. + RecommendationProvided VerticalPodAutoscalerConditionType = "RecommendationProvided" + // LowConfidence indicates whether the VPA recommender has low confidence in the recommendation for + // some of containers. + LowConfidence VerticalPodAutoscalerConditionType = "LowConfidence" + // NoPodsMatched indicates that label selector used with VPA object didn't match any pods. + NoPodsMatched VerticalPodAutoscalerConditionType = "NoPodsMatched" + // FetchingHistory indicates that VPA recommender is in the process of loading additional history samples. + FetchingHistory VerticalPodAutoscalerConditionType = "FetchingHistory" + // ConfigDeprecated indicates that this VPA configuration is deprecated + // and will stop being supported soon. + ConfigDeprecated VerticalPodAutoscalerConditionType = "ConfigDeprecated" + // ConfigUnsupported indicates that this VPA configuration is unsupported + // and recommendations will not be provided for it. + ConfigUnsupported VerticalPodAutoscalerConditionType = "ConfigUnsupported" +) + +// VerticalPodAutoscalerCondition describes the state of +// a VerticalPodAutoscaler at a certain point. +type VerticalPodAutoscalerCondition struct { + // type describes the current condition + Type VerticalPodAutoscalerConditionType `json:"type" protobuf:"bytes,1,name=type"` + // status is the status of the condition (True, False, Unknown) + Status v1.ConditionStatus `json:"status" protobuf:"bytes,2,name=status"` + // lastTransitionTime is the last time the condition transitioned from + // one status to another + // +optional + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,3,opt,name=lastTransitionTime"` + // reason is the reason for the condition's last transition. + // +optional + Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"` + // message is a human-readable explanation containing details about + // the transition + // +optional + Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` +} + +// +genclient +// +genclient:noStatus +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VerticalPodAutoscalerCheckpoint is the checkpoint of the internal state of VPA that +// is used for recovery after recommender's restart. +type VerticalPodAutoscalerCheckpoint struct { + metav1.TypeMeta `json:",inline"` + // Standard object metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Specification of the checkpoint. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. + // +optional + Spec VerticalPodAutoscalerCheckpointSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` + + // Data of the checkpoint. + // +optional + Status VerticalPodAutoscalerCheckpointStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VerticalPodAutoscalerCheckpointList is a list of VerticalPodAutoscalerCheckpoint objects. +type VerticalPodAutoscalerCheckpointList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []VerticalPodAutoscalerCheckpoint `json:"items"` +} + +// VerticalPodAutoscalerCheckpointSpec is the specification of the checkpoint object. +type VerticalPodAutoscalerCheckpointSpec struct { + // Name of the VPA object that stored VerticalPodAutoscalerCheckpoint object. + VPAObjectName string `json:"vpaObjectName,omitempty" protobuf:"bytes,1,opt,name=vpaObjectName"` + + // Name of the checkpointed container. + ContainerName string `json:"containerName,omitempty" protobuf:"bytes,2,opt,name=containerName"` +} + +// VerticalPodAutoscalerCheckpointStatus contains data of the checkpoint. +type VerticalPodAutoscalerCheckpointStatus struct { + // The time when the status was last refreshed. + LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty" protobuf:"bytes,1,opt,name=lastUpdateTime"` + + // Version of the format of the stored data. + Version string `json:"version,omitempty" protobuf:"bytes,2,opt,name=version"` + + // Checkpoint of histogram for consumption of CPU. + CPUHistogram HistogramCheckpoint `json:"cpuHistogram,omitempty" protobuf:"bytes,3,rep,name=cpuHistograms"` + + // Checkpoint of histogram for consumption of memory. + MemoryHistogram HistogramCheckpoint `json:"memoryHistogram,omitempty" protobuf:"bytes,4,rep,name=memoryHistogram"` + + // Timestamp of the fist sample from the histograms. + FirstSampleStart metav1.Time `json:"firstSampleStart,omitempty" protobuf:"bytes,5,opt,name=firstSampleStart"` + + // Timestamp of the last sample from the histograms. + LastSampleStart metav1.Time `json:"lastSampleStart,omitempty" protobuf:"bytes,6,opt,name=lastSampleStart"` + + // Total number of samples in the histograms. + TotalSamplesCount int `json:"totalSamplesCount,omitempty" protobuf:"bytes,7,opt,name=totalSamplesCount"` +} + +// HistogramCheckpoint contains data needed to reconstruct the histogram. +type HistogramCheckpoint struct { + // Reference timestamp for samples collected within this histogram. + ReferenceTimestamp metav1.Time `json:"referenceTimestamp,omitempty" protobuf:"bytes,1,opt,name=referenceTimestamp"` + + // Map from bucket index to bucket weight. + BucketWeights map[int]uint32 `json:"bucketWeights,omitempty" protobuf:"bytes,2,opt,name=bucketWeights"` + + // Sum of samples to be used as denominator for weights from BucketWeights. + TotalWeight float64 `json:"totalWeight,omitempty" protobuf:"bytes,3,opt,name=totalWeight"` +} diff --git a/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/zz_generated.deepcopy.go b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/zz_generated.deepcopy.go new file mode 100644 index 0000000000..c7f00f1242 --- /dev/null +++ b/vendor/k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2/zz_generated.deepcopy.go @@ -0,0 +1,432 @@ +// +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 v1beta2 + +import ( + autoscalingv1 "k8s.io/api/autoscaling/v1" + v1 "k8s.io/api/core/v1" + 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 *ContainerResourcePolicy) DeepCopyInto(out *ContainerResourcePolicy) { + *out = *in + if in.Mode != nil { + in, out := &in.Mode, &out.Mode + *out = new(ContainerScalingMode) + **out = **in + } + if in.MinAllowed != nil { + in, out := &in.MinAllowed, &out.MinAllowed + *out = make(v1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.MaxAllowed != nil { + in, out := &in.MaxAllowed, &out.MaxAllowed + *out = make(v1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerResourcePolicy. +func (in *ContainerResourcePolicy) DeepCopy() *ContainerResourcePolicy { + if in == nil { + return nil + } + out := new(ContainerResourcePolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HistogramCheckpoint) DeepCopyInto(out *HistogramCheckpoint) { + *out = *in + in.ReferenceTimestamp.DeepCopyInto(&out.ReferenceTimestamp) + if in.BucketWeights != nil { + in, out := &in.BucketWeights, &out.BucketWeights + *out = make(map[int]uint32, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HistogramCheckpoint. +func (in *HistogramCheckpoint) DeepCopy() *HistogramCheckpoint { + if in == nil { + return nil + } + out := new(HistogramCheckpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodResourcePolicy) DeepCopyInto(out *PodResourcePolicy) { + *out = *in + if in.ContainerPolicies != nil { + in, out := &in.ContainerPolicies, &out.ContainerPolicies + *out = make([]ContainerResourcePolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodResourcePolicy. +func (in *PodResourcePolicy) DeepCopy() *PodResourcePolicy { + if in == nil { + return nil + } + out := new(PodResourcePolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodUpdatePolicy) DeepCopyInto(out *PodUpdatePolicy) { + *out = *in + if in.UpdateMode != nil { + in, out := &in.UpdateMode, &out.UpdateMode + *out = new(UpdateMode) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodUpdatePolicy. +func (in *PodUpdatePolicy) DeepCopy() *PodUpdatePolicy { + if in == nil { + return nil + } + out := new(PodUpdatePolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RecommendedContainerResources) DeepCopyInto(out *RecommendedContainerResources) { + *out = *in + if in.Target != nil { + in, out := &in.Target, &out.Target + *out = make(v1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.LowerBound != nil { + in, out := &in.LowerBound, &out.LowerBound + *out = make(v1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.UpperBound != nil { + in, out := &in.UpperBound, &out.UpperBound + *out = make(v1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.UncappedTarget != nil { + in, out := &in.UncappedTarget, &out.UncappedTarget + *out = make(v1.ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RecommendedContainerResources. +func (in *RecommendedContainerResources) DeepCopy() *RecommendedContainerResources { + if in == nil { + return nil + } + out := new(RecommendedContainerResources) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RecommendedPodResources) DeepCopyInto(out *RecommendedPodResources) { + *out = *in + if in.ContainerRecommendations != nil { + in, out := &in.ContainerRecommendations, &out.ContainerRecommendations + *out = make([]RecommendedContainerResources, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RecommendedPodResources. +func (in *RecommendedPodResources) DeepCopy() *RecommendedPodResources { + if in == nil { + return nil + } + out := new(RecommendedPodResources) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VerticalPodAutoscaler) DeepCopyInto(out *VerticalPodAutoscaler) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscaler. +func (in *VerticalPodAutoscaler) DeepCopy() *VerticalPodAutoscaler { + if in == nil { + return nil + } + out := new(VerticalPodAutoscaler) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VerticalPodAutoscaler) 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 *VerticalPodAutoscalerCheckpoint) DeepCopyInto(out *VerticalPodAutoscalerCheckpoint) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerCheckpoint. +func (in *VerticalPodAutoscalerCheckpoint) DeepCopy() *VerticalPodAutoscalerCheckpoint { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerCheckpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VerticalPodAutoscalerCheckpoint) 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 *VerticalPodAutoscalerCheckpointList) DeepCopyInto(out *VerticalPodAutoscalerCheckpointList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VerticalPodAutoscalerCheckpoint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerCheckpointList. +func (in *VerticalPodAutoscalerCheckpointList) DeepCopy() *VerticalPodAutoscalerCheckpointList { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerCheckpointList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VerticalPodAutoscalerCheckpointList) 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 *VerticalPodAutoscalerCheckpointSpec) DeepCopyInto(out *VerticalPodAutoscalerCheckpointSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerCheckpointSpec. +func (in *VerticalPodAutoscalerCheckpointSpec) DeepCopy() *VerticalPodAutoscalerCheckpointSpec { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerCheckpointSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VerticalPodAutoscalerCheckpointStatus) DeepCopyInto(out *VerticalPodAutoscalerCheckpointStatus) { + *out = *in + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) + in.CPUHistogram.DeepCopyInto(&out.CPUHistogram) + in.MemoryHistogram.DeepCopyInto(&out.MemoryHistogram) + in.FirstSampleStart.DeepCopyInto(&out.FirstSampleStart) + in.LastSampleStart.DeepCopyInto(&out.LastSampleStart) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerCheckpointStatus. +func (in *VerticalPodAutoscalerCheckpointStatus) DeepCopy() *VerticalPodAutoscalerCheckpointStatus { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerCheckpointStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VerticalPodAutoscalerCondition) DeepCopyInto(out *VerticalPodAutoscalerCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerCondition. +func (in *VerticalPodAutoscalerCondition) DeepCopy() *VerticalPodAutoscalerCondition { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VerticalPodAutoscalerList) DeepCopyInto(out *VerticalPodAutoscalerList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VerticalPodAutoscaler, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerList. +func (in *VerticalPodAutoscalerList) DeepCopy() *VerticalPodAutoscalerList { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VerticalPodAutoscalerList) 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 *VerticalPodAutoscalerSpec) DeepCopyInto(out *VerticalPodAutoscalerSpec) { + *out = *in + if in.TargetRef != nil { + in, out := &in.TargetRef, &out.TargetRef + *out = new(autoscalingv1.CrossVersionObjectReference) + **out = **in + } + if in.UpdatePolicy != nil { + in, out := &in.UpdatePolicy, &out.UpdatePolicy + *out = new(PodUpdatePolicy) + (*in).DeepCopyInto(*out) + } + if in.ResourcePolicy != nil { + in, out := &in.ResourcePolicy, &out.ResourcePolicy + *out = new(PodResourcePolicy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerSpec. +func (in *VerticalPodAutoscalerSpec) DeepCopy() *VerticalPodAutoscalerSpec { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VerticalPodAutoscalerStatus) DeepCopyInto(out *VerticalPodAutoscalerStatus) { + *out = *in + if in.Recommendation != nil { + in, out := &in.Recommendation, &out.Recommendation + *out = new(RecommendedPodResources) + (*in).DeepCopyInto(*out) + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VerticalPodAutoscalerCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticalPodAutoscalerStatus. +func (in *VerticalPodAutoscalerStatus) DeepCopy() *VerticalPodAutoscalerStatus { + if in == nil { + return nil + } + out := new(VerticalPodAutoscalerStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 71476e4ef8..c88918c43d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -128,8 +128,8 @@ k8s.io/api/extensions/v1beta1 k8s.io/api/policy/v1beta1 k8s.io/api/storage/v1 k8s.io/api/apps/v1beta1 -k8s.io/api/admissionregistration/v1beta1 k8s.io/api/autoscaling/v1 +k8s.io/api/admissionregistration/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/auditregistration/v1alpha1 k8s.io/api/authentication/v1 @@ -177,6 +177,7 @@ k8s.io/apimachinery/pkg/util/sets k8s.io/apimachinery/pkg/util/validation/field k8s.io/apimachinery/pkg/util/net k8s.io/apimachinery/pkg/api/errors +k8s.io/apimachinery/pkg/runtime/serializer/streaming k8s.io/apimachinery/pkg/util/cache k8s.io/apimachinery/pkg/util/clock k8s.io/apimachinery/pkg/util/diff @@ -184,7 +185,6 @@ k8s.io/apimachinery/pkg/util/wait k8s.io/apimachinery/pkg/apis/meta/v1beta1 k8s.io/apimachinery/pkg/runtime/serializer k8s.io/apimachinery/pkg/version -k8s.io/apimachinery/pkg/runtime/serializer/streaming k8s.io/apimachinery/pkg/util/yaml k8s.io/apimachinery/pkg/runtime/serializer/json k8s.io/apimachinery/pkg/runtime/serializer/versioning @@ -197,10 +197,13 @@ k8s.io/apimachinery/pkg/apis/meta/v1/unstructured k8s.io/apimachinery/pkg/util/strategicpatch k8s.io/apimachinery/pkg/util/mergepatch k8s.io/apimachinery/third_party/forked/golang/json +# k8s.io/autoscaler v0.0.0-20190612121530-8bb2354d9af9 +k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1beta2 # k8s.io/client-go v2.0.0-alpha.0.0.20190313235726-6ee68ca5fd83+incompatible k8s.io/client-go/kubernetes k8s.io/client-go/plugin/pkg/client/auth k8s.io/client-go/tools/clientcmd +k8s.io/client-go/rest k8s.io/client-go/tools/cache k8s.io/client-go/discovery k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1 @@ -239,7 +242,6 @@ k8s.io/client-go/kubernetes/typed/settings/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1 k8s.io/client-go/kubernetes/typed/storage/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1beta1 -k8s.io/client-go/rest k8s.io/client-go/util/flowcontrol k8s.io/client-go/plugin/pkg/client/auth/azure k8s.io/client-go/plugin/pkg/client/auth/gcp @@ -250,16 +252,16 @@ k8s.io/client-go/tools/clientcmd/api k8s.io/client-go/tools/clientcmd/api/latest k8s.io/client-go/util/homedir k8s.io/client-go/kubernetes/fake -k8s.io/client-go/tools/pager -k8s.io/client-go/util/retry -k8s.io/client-go/kubernetes/scheme -k8s.io/client-go/tools/reference k8s.io/client-go/pkg/version k8s.io/client-go/plugin/pkg/client/auth/exec k8s.io/client-go/rest/watch k8s.io/client-go/tools/metrics k8s.io/client-go/transport k8s.io/client-go/util/cert +k8s.io/client-go/tools/pager +k8s.io/client-go/util/retry +k8s.io/client-go/kubernetes/scheme +k8s.io/client-go/tools/reference k8s.io/client-go/util/jsonpath k8s.io/client-go/tools/clientcmd/api/v1 k8s.io/client-go/discovery/fake