From dfeae82cae5e484d3dd52ab0dcf12e5c367fc138 Mon Sep 17 00:00:00 2001 From: Arjun Date: Wed, 3 Apr 2019 10:23:52 +0200 Subject: [PATCH] Upgrade all pacakges to autoscalingv2beta2 (#39) Signed-off-by: Arjun Naik --- go.mod | 22 ++-- go.sum | 46 ++++--- pkg/annotations/parser.go | 100 +++++++++++++++ pkg/annotations/parser_test.go | 83 +++++++++++++ pkg/collector/aws_collector.go | 27 +++-- pkg/collector/collector.go | 155 +++++------------------- pkg/collector/object_collector.go | 20 --- pkg/collector/pod_collector.go | 21 ++-- pkg/collector/prometheus_collector.go | 16 +-- pkg/collector/skipper_collector.go | 22 ++-- pkg/collector/skipper_collector_test.go | 38 +++--- pkg/collector/zmon_collector.go | 30 +++-- pkg/collector/zmon_collector_test.go | 30 +++-- pkg/provider/hpa.go | 20 ++- pkg/provider/metric_store.go | 36 +++--- pkg/provider/metrics_store_test.go | 104 ++++++++-------- 16 files changed, 429 insertions(+), 341 deletions(-) create mode 100644 pkg/annotations/parser.go create mode 100644 pkg/annotations/parser_test.go delete mode 100644 pkg/collector/object_collector.go diff --git a/go.mod b/go.mod index f950147..af6c2a4 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,12 @@ module github.com/zalando-incubator/kube-metrics-adapter require ( bitbucket.org/ww/goautoneg v0.0.0-20120707110453-75cd24fc2f2c // indirect + github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/BurntSushi/toml v0.3.0 // indirect github.com/NYTimes/gziphandler v1.0.1 // indirect github.com/PuerkitoBio/purell v1.1.0 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/Sirupsen/logrus v1.0.6 // indirect github.com/aws/aws-sdk-go v1.16.6 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect github.com/boltdb/bolt v1.3.1 // indirect @@ -14,12 +16,12 @@ require ( github.com/coreos/go-semver v0.2.0 // indirect github.com/coreos/go-systemd v0.0.0-20180705093442-88bfeed483d3 // indirect github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/docker/docker v1.13.1 // indirect github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect github.com/emicklei/go-restful v2.8.0+incompatible // indirect github.com/emicklei/go-restful-swagger12 v0.0.0-20170926063155-7524189396c6 // indirect - github.com/evanphx/json-patch v3.0.0+incompatible // indirect + github.com/evanphx/json-patch v4.1.1-0.20190203004735-bbf30d639737+incompatible // indirect github.com/fsnotify/fsnotify v1.4.7 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-openapi/jsonpointer v0.0.0-20180322222829-3a0015ad55fa // indirect @@ -42,7 +44,7 @@ require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jonboulle/clockwork v0.1.0 // indirect github.com/json-iterator/go v1.1.5 // indirect - github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20180824182428-26e5299457d3 + github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20190116221620-b7016fc85e1c github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -52,12 +54,11 @@ require ( github.com/onsi/gomega v1.4.1 // indirect github.com/pborman/uuid v0.0.0-20180122190007-c65b2f87fee3 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v0.9.0-pre1.0.20180824101016-4eb539fa85a2 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 // indirect - github.com/sirupsen/logrus v1.0.6 + github.com/sirupsen/logrus v1.3.0 github.com/soheilhy/cmux v0.1.4 // indirect github.com/spf13/cobra v0.0.3 github.com/spf13/pflag v1.0.2 // indirect @@ -70,7 +71,6 @@ require ( golang.org/x/net v0.0.0-20180824152047-4bcd98cce591 // indirect golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect - golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87 // indirect golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 // indirect google.golang.org/appengine v1.2.0 // indirect google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 // indirect @@ -82,10 +82,10 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.2.1 // indirect - k8s.io/api v0.0.0-20180628040859-072894a440bd - k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d - k8s.io/apiserver v0.0.0-20180628044425-01459b68eb5f - k8s.io/client-go v8.0.0+incompatible + k8s.io/api v0.0.0-20190226173710-145d52631d00 + k8s.io/apimachinery v0.0.0-20190221084156-01f179d85dbc + k8s.io/apiserver v0.0.0-20190226174732-cf2f1d68202d + k8s.io/client-go v2.0.0-alpha.0.0.20190226174127-78295b709ec6+incompatible k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c // indirect - k8s.io/metrics v0.0.0-20180718014405-6efa0bfaa5c1 + k8s.io/metrics v0.0.0-20190226180357-f3f09b9076d1 ) diff --git a/go.sum b/go.sum index 46897eb..032c957 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ bitbucket.org/ww/goautoneg v0.0.0-20120707110453-75cd24fc2f2c h1:t+Ra932MCC0eeyD/vigXqMbZTzgZjd4JOfBJWC6VSMI= bitbucket.org/ww/goautoneg v0.0.0-20120707110453-75cd24fc2f2c/go.mod h1:1vhO7Mn/FZMgOgDVGLy5X1mE6rq1HbkBdkF/yj8zkcg= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY= github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/NYTimes/gziphandler v1.0.1 h1:iLrQrdwjDd52kHDA5op2UBJFjmOb9g+7scBan4RN8F0= @@ -8,6 +10,8 @@ github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVk github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Sirupsen/logrus v1.0.6 h1:HCAGQRk48dRVPA5Y+Yh0qdCSTzPOyU1tBJ7Q9YzotII= +github.com/Sirupsen/logrus v1.0.6/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U= github.com/aws/aws-sdk-go v1.16.6 h1:pig/KdfESvIv4gUu1B8nVAJAURxbPCTt6e5u79Nqxqc= github.com/aws/aws-sdk-go v1.16.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= @@ -28,14 +32,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= +github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/emicklei/go-restful v2.8.0+incompatible h1:wN8GCRDPGHguIynsnBartv5GUgGUg1LAU7+xnSn1j7Q= github.com/emicklei/go-restful v2.8.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful-swagger12 v0.0.0-20170926063155-7524189396c6 h1:V94anc0ZG3Pa/cAMwP2m1aQW3+/FF8Qmw/GsFyTJAp4= github.com/emicklei/go-restful-swagger12 v0.0.0-20170926063155-7524189396c6/go.mod h1:qr0VowGBT4CS4Q8vFF8BSeKz34PuqKGxs/L0IAQA9DQ= -github.com/evanphx/json-patch v3.0.0+incompatible h1:l91aby7TzBXBdmF8heZqjskeH9f3g7ZOL8/sSe+vTlU= -github.com/evanphx/json-patch v3.0.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.1.1-0.20190203004735-bbf30d639737+incompatible h1:zmRDnAOQ9imo/243rC0ZWlO7NUDCT/OipvoIi672uOg= +github.com/evanphx/json-patch v4.1.1-0.20190203004735-bbf30d639737+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -84,8 +90,10 @@ github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20180824182428-26e5299457d3 h1:X22IRs6vbuj0xu3ZuMYMI2Qe0IDmxv0RJvWEwLw2nSg= -github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20180824182428-26e5299457d3/go.mod h1:KWRxWvzVCNvDtG9ejU5UdpgvxdCZFMUZu0xroKWG8Bo= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20190116221620-b7016fc85e1c h1:CtT8/S2j5ENQ5UniZ7uymL2OyVEBUQsJXSzqKkpnwIU= +github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20190116221620-b7016fc85e1c/go.mod h1:KWRxWvzVCNvDtG9ejU5UdpgvxdCZFMUZu0xroKWG8Bo= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -114,14 +122,15 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e h1:n/3MEhJQjQxrO github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 h1:lYIiVDtZnyTWlNwiAxLj0bbpTcx1BWCFhXjfsvmPdNc= @@ -132,6 +141,7 @@ github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 h1:MPPkRncZLN9Kh4M github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/zalando-incubator/cluster-lifecycle-manager v0.0.0-20180921141935-824b77fb1f84 h1:LirBPRU6n8qjPFWCTIlTDh+1FW2M4z2RFS7lCzNkKgA= github.com/zalando-incubator/cluster-lifecycle-manager v0.0.0-20180921141935-824b77fb1f84/go.mod h1:6GNNHCquvS1cn0APtLvgYNYEMYK+JRwp6ZTGxi+pc+w= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e h1:IzypfodbhbnViNUO/MEh0FzCUooG97cIGfdggUrUSyU= golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -141,8 +151,8 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87 h1:GqwDwfvIpC33dK9bA1fD+JiDUNsuAiQiEkpHqUKze4o= -golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 h1:+DCIGbF/swA92ohVg0//6X2IVY3KZs6p9mix0ziNYJM= @@ -169,15 +179,15 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -k8s.io/api v0.0.0-20180628040859-072894a440bd h1:HzgYeLDS1jLxw8DGr68KJh9cdQ5iZJizG0HZWstIhfQ= -k8s.io/api v0.0.0-20180628040859-072894a440bd/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= -k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d h1:MZjlsu9igBoVPZkXpIGoxI6EonqNsXXZU7hhvfQLkd4= -k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= -k8s.io/apiserver v0.0.0-20180628044425-01459b68eb5f h1:eCb6E7epnzes186KGtXgA3PE2mLim3ceVSbCXQ8v5e8= -k8s.io/apiserver v0.0.0-20180628044425-01459b68eb5f/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w= -k8s.io/client-go v8.0.0+incompatible h1:tTI4hRmb1DRMl4fG6Vclfdi6nTM82oIrTT7HfitmxC4= -k8s.io/client-go v8.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/api v0.0.0-20190226173710-145d52631d00 h1:xYfyMq0qxTGAg3O9GK23GMbNrBcpnFg9IeA6isDgIXk= +k8s.io/api v0.0.0-20190226173710-145d52631d00/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apimachinery v0.0.0-20190221084156-01f179d85dbc h1:7z9/6jKWBqkK9GI1RRB0B5fZcmkatLQ/nv8kysch24o= +k8s.io/apimachinery v0.0.0-20190221084156-01f179d85dbc/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/apiserver v0.0.0-20190226174732-cf2f1d68202d h1:WiGjO9v3LoXlNF6ftQFBufl0rySK2aidwUFhxzIeF4c= +k8s.io/apiserver v0.0.0-20190226174732-cf2f1d68202d/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w= +k8s.io/client-go v2.0.0-alpha.0.0.20190226174127-78295b709ec6+incompatible h1:k3zcwEH4YFZUjuSI1m4qEFmLlXiTp9tSDf7lIhHyy3g= +k8s.io/client-go v2.0.0-alpha.0.0.20190226174127-78295b709ec6+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c h1:3KSCztE7gPitlZmWbNwue/2U0YruD65DqX3INopDAQM= k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= -k8s.io/metrics v0.0.0-20180718014405-6efa0bfaa5c1 h1:7l3a6VjAMN3vKX7iN6pJLIn+wVzdIdHm+YWJfV4sg2s= -k8s.io/metrics v0.0.0-20180718014405-6efa0bfaa5c1/go.mod h1:a25VAbm3QT3xiVl1jtoF1ueAKQM149UdZ+L93ePfV3M= +k8s.io/metrics v0.0.0-20190226180357-f3f09b9076d1 h1:uHZS9QZJpC4ZdZp0Eu34vz/57SC7RO/PXIWH3tYA1Zw= +k8s.io/metrics v0.0.0-20190226180357-f3f09b9076d1/go.mod h1:a25VAbm3QT3xiVl1jtoF1ueAKQM149UdZ+L93ePfV3M= diff --git a/pkg/annotations/parser.go b/pkg/annotations/parser.go new file mode 100644 index 0000000..b0a7cd4 --- /dev/null +++ b/pkg/annotations/parser.go @@ -0,0 +1,100 @@ +package annotations + +import ( + "fmt" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" + "strings" + "time" +) + +const ( + customMetricsPrefix = "metric-config." + perReplicaMetricsConfKey = "per-replica" + intervalMetricsConfKey = "interval" +) + +type AnnotationConfigs struct { + CollectorName string + Configs map[string]string + PerReplica bool + Interval time.Duration +} + +type MetricConfigKey struct { + Type autoscalingv2.MetricSourceType + MetricName string +} + +type AnnotationConfigMap map[MetricConfigKey]*AnnotationConfigs + +func (m AnnotationConfigMap) Parse(annotations map[string]string) error { + for key, val := range annotations { + if !strings.HasPrefix(key, customMetricsPrefix) { + continue + } + + parts := strings.Split(key, "/") + if len(parts) != 2 { + // TODO: error? + continue + } + + configs := strings.Split(parts[0], ".") + if len(configs) != 4 { + // TODO: error? + continue + } + + key := MetricConfigKey{ + MetricName: configs[2], + } + + switch configs[1] { + case "pods": + key.Type = autoscalingv2.PodsMetricSourceType + case "object": + key.Type = autoscalingv2.ObjectMetricSourceType + default: + key.Type = autoscalingv2.ExternalMetricSourceType + } + + metricCollector := configs[3] + + config, ok := m[key] + if !ok { + config = &AnnotationConfigs{ + CollectorName: metricCollector, + Configs: map[string]string{}, + } + m[key] = config + } + + // TODO: fail if collector name doesn't match + if config.CollectorName != metricCollector { + continue + } + + if parts[1] == perReplicaMetricsConfKey { + config.PerReplica = true + continue + } + + if parts[1] == intervalMetricsConfKey { + interval, err := time.ParseDuration(val) + if err != nil { + return fmt.Errorf("failed to parse interval value %s for %s: %v", val, key, err) + } + config.Interval = interval + continue + } + + config.Configs[parts[1]] = val + } + return nil +} + +func (m AnnotationConfigMap) GetAnnotationConfig(metricName string, metricType autoscalingv2.MetricSourceType) (*AnnotationConfigs, bool) { + key := MetricConfigKey{MetricName: metricName, Type: metricType} + config, ok := m[key] + return config, ok +} diff --git a/pkg/annotations/parser_test.go b/pkg/annotations/parser_test.go new file mode 100644 index 0000000..942bc58 --- /dev/null +++ b/pkg/annotations/parser_test.go @@ -0,0 +1,83 @@ +package annotations + +import ( + "github.com/stretchr/testify/require" + "testing" + + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" +) + +func TestParser(t *testing.T) { + for _, tc := range []struct { + Name string + Annotations map[string]string + MetricName string + MetricType autoscalingv2.MetricSourceType + ExpectedConfig map[string]string + PerReplica bool + }{ + { + Name: "no annotations", + Annotations: map[string]string{}, + ExpectedConfig: map[string]string{}, + }, + { + Name: "pod metrics", + Annotations: map[string]string{ + "metric-config.pods.requests-per-second.json-path/json-key": "$.http_server.rps", + "metric-config.pods.requests-per-second.json-path/path": "/metrics", + "metric-config.pods.requests-per-second.json-path/port": "9090", + }, + MetricName: "requests-per-second", + MetricType: autoscalingv2.PodsMetricSourceType, + ExpectedConfig: map[string]string{ + "json-key": "$.http_server.rps", + "path": "/metrics", + "port": "9090", + }, + }, + { + Name: "prometheus metrics", + Annotations: map[string]string{ + "metric-config.object.processed-events-per-second.prometheus/query": "scalar(sum(rate(event-service_events_count{application=\"event-service\",processed=\"true\"}[1m])))", + "metric-config.object.processed-events-per-second.prometheus/per-replica": "true", + }, + MetricName: "processed-events-per-second", + MetricType: autoscalingv2.ObjectMetricSourceType, + ExpectedConfig: map[string]string{ + "query": "scalar(sum(rate(event-service_events_count{application=\"event-service\",processed=\"true\"}[1m])))", + }, + PerReplica: true, + }, + { + Name: "zmon collector", + Annotations: map[string]string{ + "metric-config.external.zmon-check.zmon/key": "custom.*", + "metric-config.external.zmon-check.zmon/tag-application": "my-custom-app-*", + }, + MetricName: "zmon-check", + MetricType: autoscalingv2.ExternalMetricSourceType, + ExpectedConfig: map[string]string{ + "key": "custom.*", + "tag-application": "my-custom-app-*", + }, + PerReplica: false, + }, + } { + t.Run(tc.Name, func(t *testing.T) { + hpaMap := make(AnnotationConfigMap) + err := hpaMap.Parse(tc.Annotations) + require.NoError(t, err) + config, present := hpaMap.GetAnnotationConfig(tc.MetricName, tc.MetricType) + if len(tc.ExpectedConfig) == 0 { + require.False(t, present) + return + } + require.True(t, present) + for k, v := range tc.ExpectedConfig { + require.Equal(t, v, config.Configs[k]) + } + require.Equal(t, tc.PerReplica, config.PerReplica) + }) + } +} diff --git a/pkg/collector/aws_collector.go b/pkg/collector/aws_collector.go index fca1403..2fb3e7a 100644 --- a/pkg/collector/aws_collector.go +++ b/pkg/collector/aws_collector.go @@ -9,7 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/sqs" "github.com/aws/aws-sdk-go/service/sqs/sqsiface" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/metrics/pkg/apis/external_metrics" @@ -32,13 +32,13 @@ func NewAWSCollectorPlugin(sessions map[string]*session.Session) *AWSCollectorPl } // NewCollector initializes a new skipper collector from the specified HPA. -func (c *AWSCollectorPlugin) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { - switch config.Name { +func (c *AWSCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { + switch config.Metric.Name { case AWSSQSQueueLengthMetric: return NewAWSSQSCollector(c.sessions, config, interval) } - return nil, fmt.Errorf("metric '%s' not supported", config.Name) + return nil, fmt.Errorf("metric '%s' not supported", config.Metric.Name) } type AWSSQSCollector struct { @@ -47,18 +47,20 @@ type AWSSQSCollector struct { region string queueURL string queueName string - labels map[string]string - metricName string - metricType autoscalingv2beta1.MetricSourceType + metric autoscalingv2.MetricIdentifier + metricType autoscalingv2.MetricSourceType } func NewAWSSQSCollector(sessions map[string]*session.Session, config *MetricConfig, interval time.Duration) (*AWSSQSCollector, error) { + if config.Metric.Selector == nil { + return nil, fmt.Errorf("selector for queue is not specified") + } - name, ok := config.Labels[sqsQueueNameLabelKey] + name, ok := config.Metric.Selector.MatchLabels[sqsQueueNameLabelKey] if !ok { return nil, fmt.Errorf("sqs queue name not specified on metric") } - region, ok := config.Labels[sqsQueueRegionLabelKey] + region, ok := config.Metric.Selector.MatchLabels[sqsQueueRegionLabelKey] if !ok { return nil, fmt.Errorf("sqs queue region is not specified on metric") } @@ -83,9 +85,8 @@ func NewAWSSQSCollector(sessions map[string]*session.Session, config *MetricConf interval: interval, queueURL: aws.StringValue(resp.QueueUrl), queueName: name, - metricName: config.Name, + metric: config.Metric, metricType: config.Type, - labels: config.Labels, }, nil } @@ -109,8 +110,8 @@ func (c *AWSSQSCollector) GetMetrics() ([]CollectedMetric, error) { metricValue := CollectedMetric{ Type: c.metricType, External: external_metrics.ExternalMetricValue{ - MetricName: c.metricName, - MetricLabels: c.labels, + MetricName: c.metric.Name, + MetricLabels: c.metric.Selector.MatchLabels, Timestamp: metav1.Time{Time: time.Now().UTC()}, Value: *resource.NewQuantity(int64(i), resource.DecimalSI), }, diff --git a/pkg/collector/collector.go b/pkg/collector/collector.go index 76bf541..7f992e2 100644 --- a/pkg/collector/collector.go +++ b/pkg/collector/collector.go @@ -2,22 +2,16 @@ package collector import ( "fmt" - "strings" "time" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + "github.com/zalando-incubator/kube-metrics-adapter/pkg/annotations" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/metrics/pkg/apis/custom_metrics" "k8s.io/metrics/pkg/apis/external_metrics" ) -const ( - customMetricsPrefix = "metric-config." - perReplicaMetricsConfKey = "per-replica" - intervalMetricsConfKey = "interval" -) - type ObjectReference struct { - autoscalingv2beta1.CrossVersionObjectReference + autoscalingv2.CrossVersionObjectReference Namespace string } @@ -49,7 +43,7 @@ func NewCollectorFactory() *CollectorFactory { } type CollectorPlugin interface { - NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) + NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) } func (c *CollectorFactory) RegisterPodsCollector(metricCollector string, plugin CollectorPlugin) error { @@ -106,9 +100,9 @@ func (c *CollectorFactory) RegisterExternalCollector(metrics []string, plugin Co } } -func (c *CollectorFactory) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { +func (c *CollectorFactory) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { switch config.Type { - case autoscalingv2beta1.PodsMetricSourceType: + case autoscalingv2.PodsMetricSourceType: // first try to find a plugin by format if plugin, ok := c.podsPlugins.Named[config.CollectorName]; ok { return plugin.NewCollector(hpa, config, interval) @@ -118,7 +112,7 @@ func (c *CollectorFactory) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAut if c.podsPlugins.Any != nil { return c.podsPlugins.Any.NewCollector(hpa, config, interval) } - case autoscalingv2beta1.ObjectMetricSourceType: + case autoscalingv2.ObjectMetricSourceType: // first try to find a plugin by kind if kinds, ok := c.objectPlugins.Named[config.ObjectReference.Kind]; ok { if plugin, ok := kinds.Named[config.CollectorName]; ok { @@ -139,8 +133,8 @@ func (c *CollectorFactory) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAut if c.objectPlugins.Any.Any != nil { return c.objectPlugins.Any.Any.NewCollector(hpa, config, interval) } - case autoscalingv2beta1.ExternalMetricSourceType: - if plugin, ok := c.externalPlugins[config.Name]; ok { + case autoscalingv2.ExternalMetricSourceType: + if plugin, ok := c.externalPlugins[config.Metric.Name]; ok { return plugin.NewCollector(hpa, config, interval) } } @@ -148,31 +142,15 @@ func (c *CollectorFactory) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAut return nil, fmt.Errorf("no plugin found for %s", config.MetricTypeName) } -func getObjectReference(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, metricName string) (custom_metrics.ObjectReference, error) { - for _, metric := range hpa.Spec.Metrics { - if metric.Type == autoscalingv2beta1.ObjectMetricSourceType && metric.Object.MetricName == metricName { - return custom_metrics.ObjectReference{ - APIVersion: metric.Object.Target.APIVersion, - Kind: metric.Object.Target.Kind, - Name: metric.Object.Target.Name, - Namespace: hpa.Namespace, - }, nil - } - } - - return custom_metrics.ObjectReference{}, fmt.Errorf("failed to find object reference") -} - type MetricTypeName struct { - Type autoscalingv2beta1.MetricSourceType - Name string + Type autoscalingv2.MetricSourceType + Metric autoscalingv2.MetricIdentifier } type CollectedMetric struct { - Type autoscalingv2beta1.MetricSourceType + Type autoscalingv2.MetricSourceType Custom custom_metrics.MetricValue External external_metrics.ExternalMetricValue - Labels map[string]string } type Collector interface { @@ -187,83 +165,17 @@ type MetricConfig struct { ObjectReference custom_metrics.ObjectReference PerReplica bool Interval time.Duration - Labels map[string]string -} - -func parseCustomMetricsAnnotations(annotations map[string]string) (map[MetricTypeName]*MetricConfig, error) { - metrics := make(map[MetricTypeName]*MetricConfig) - for key, val := range annotations { - if !strings.HasPrefix(key, customMetricsPrefix) { - continue - } - - parts := strings.Split(key, "/") - if len(parts) != 2 { - // TODO: error? - continue - } - - configs := strings.Split(parts[0], ".") - if len(configs) != 4 { - // TODO: error? - continue - } - - metricTypeName := MetricTypeName{ - Name: configs[2], - } - - switch configs[1] { - case "pods": - metricTypeName.Type = autoscalingv2beta1.PodsMetricSourceType - case "object": - metricTypeName.Type = autoscalingv2beta1.ObjectMetricSourceType - } - - metricCollector := configs[3] - - config, ok := metrics[metricTypeName] - if !ok { - config = &MetricConfig{ - MetricTypeName: metricTypeName, - CollectorName: metricCollector, - Config: map[string]string{}, - } - metrics[metricTypeName] = config - } - - // TODO: fail if collector name doesn't match - if config.CollectorName != metricCollector { - continue - } - - if parts[1] == perReplicaMetricsConfKey { - config.PerReplica = true - continue - } - - if parts[1] == intervalMetricsConfKey { - interval, err := time.ParseDuration(val) - if err != nil { - return nil, fmt.Errorf("failed to parse interval value %s for %s: %v", val, key, err) - } - config.Interval = interval - continue - } - - config.Config[parts[1]] = val - } - - return metrics, nil + Configuration map[string]string } // ParseHPAMetrics parses the HPA object into a list of metric configurations. -func ParseHPAMetrics(hpa *autoscalingv2beta1.HorizontalPodAutoscaler) ([]*MetricConfig, error) { +func ParseHPAMetrics(hpa *autoscalingv2.HorizontalPodAutoscaler) ([]*MetricConfig, error) { metricConfigs := make([]*MetricConfig, 0, len(hpa.Spec.Metrics)) // TODO: validate that the specified metric names are defined // in the HPA - configs, err := parseCustomMetricsAnnotations(hpa.Annotations) + var parser annotations.AnnotationConfigMap + err := parser.Parse(hpa.Annotations) if err != nil { return nil, err } @@ -275,39 +187,36 @@ func ParseHPAMetrics(hpa *autoscalingv2beta1.HorizontalPodAutoscaler) ([]*Metric var ref custom_metrics.ObjectReference switch metric.Type { - case autoscalingv2beta1.PodsMetricSourceType: - typeName.Name = metric.Pods.MetricName - case autoscalingv2beta1.ObjectMetricSourceType: - typeName.Name = metric.Object.MetricName + case autoscalingv2.PodsMetricSourceType: + typeName.Metric = metric.Pods.Metric + case autoscalingv2.ObjectMetricSourceType: + typeName.Metric = metric.Object.Metric ref = custom_metrics.ObjectReference{ - APIVersion: metric.Object.Target.APIVersion, - Kind: metric.Object.Target.Kind, - Name: metric.Object.Target.Name, + APIVersion: metric.Object.DescribedObject.APIVersion, + Kind: metric.Object.DescribedObject.Kind, + Name: metric.Object.DescribedObject.Name, Namespace: hpa.Namespace, } - case autoscalingv2beta1.ExternalMetricSourceType: - typeName.Name = metric.External.MetricName - case autoscalingv2beta1.ResourceMetricSourceType: + case autoscalingv2.ExternalMetricSourceType: + typeName.Metric = metric.External.Metric + case autoscalingv2.ResourceMetricSourceType: continue // kube-metrics-adapter does not collect resource metrics } - if config, ok := configs[typeName]; ok { - config.ObjectReference = ref - metricConfigs = append(metricConfigs, config) - continue - } - config := &MetricConfig{ MetricTypeName: typeName, ObjectReference: ref, Config: map[string]string{}, } - if metric.Type == autoscalingv2beta1.ExternalMetricSourceType { - config.Labels = metric.External.MetricSelector.MatchLabels + annotationConfigs, present := parser.GetAnnotationConfig(typeName.Metric.Name, typeName.Type) + if present { + config.CollectorName = annotationConfigs.CollectorName + config.Interval = annotationConfigs.Interval + config.PerReplica = annotationConfigs.PerReplica + config.Config = annotationConfigs.Configs } metricConfigs = append(metricConfigs, config) } - return metricConfigs, nil } diff --git a/pkg/collector/object_collector.go b/pkg/collector/object_collector.go deleted file mode 100644 index 5fb5d08..0000000 --- a/pkg/collector/object_collector.go +++ /dev/null @@ -1,20 +0,0 @@ -package collector - -import autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" - -type ObjectMetricsGetter interface { - GetObjectMetric(namespace string, reference *autoscalingv2beta1.CrossVersionObjectReference) (float64, error) -} - -// type PodCollector struct { -// client kubernetes.Interface -// Getter PodMetricsGetter -// podLabelSelector string -// namespace string -// metricName string -// interval time.Duration -// } - -// func NewObjectCollector(client kubernetes.Interface, hpa *autoscalingv2beta1.HorizontalPodAutoscaler, metricName string, config *MetricConfig, interval time.Duration) (Collector, error) { -// switch -// } diff --git a/pkg/collector/pod_collector.go b/pkg/collector/pod_collector.go index f7dfed9..0c024dd 100644 --- a/pkg/collector/pod_collector.go +++ b/pkg/collector/pod_collector.go @@ -5,7 +5,7 @@ import ( "time" log "github.com/sirupsen/logrus" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -24,7 +24,7 @@ func NewPodCollectorPlugin(client kubernetes.Interface) *PodCollectorPlugin { } } -func (p *PodCollectorPlugin) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { +func (p *PodCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { return NewPodCollector(p.client, hpa, config, interval) } @@ -33,8 +33,8 @@ type PodCollector struct { Getter PodMetricsGetter podLabelSelector string namespace string - metricName string - metricType autoscalingv2beta1.MetricSourceType + metric autoscalingv2.MetricIdentifier + metricType autoscalingv2.MetricSourceType interval time.Duration logger *log.Entry } @@ -43,7 +43,7 @@ type PodMetricsGetter interface { GetMetric(pod *v1.Pod) (float64, error) } -func NewPodCollector(client kubernetes.Interface, hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (*PodCollector, error) { +func NewPodCollector(client kubernetes.Interface, hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (*PodCollector, error) { // get pod selector based on HPA scale target ref selector, err := getPodLabelSelector(client, hpa) if err != nil { @@ -53,7 +53,7 @@ func NewPodCollector(client kubernetes.Interface, hpa *autoscalingv2beta1.Horizo c := &PodCollector{ client: client, namespace: hpa.Namespace, - metricName: config.Name, + metric: config.Metric, metricType: config.Type, interval: interval, podLabelSelector: selector, @@ -106,11 +106,10 @@ func (c *PodCollector) GetMetrics() ([]CollectedMetric, error) { Name: pod.Name, Namespace: pod.Namespace, }, - MetricName: c.metricName, - Timestamp: metav1.Time{Time: time.Now().UTC()}, - Value: *resource.NewMilliQuantity(int64(value*1000), resource.DecimalSI), + Metric: custom_metrics.MetricIdentifier{Name: c.metric.Name, Selector: c.metric.Selector}, + Timestamp: metav1.Time{Time: time.Now().UTC()}, + Value: *resource.NewMilliQuantity(int64(value*1000), resource.DecimalSI), }, - Labels: pod.Labels, } values = append(values, metricValue) @@ -123,7 +122,7 @@ func (c *PodCollector) Interval() time.Duration { return c.interval } -func getPodLabelSelector(client kubernetes.Interface, hpa *autoscalingv2beta1.HorizontalPodAutoscaler) (string, error) { +func getPodLabelSelector(client kubernetes.Interface, hpa *autoscalingv2.HorizontalPodAutoscaler) (string, error) { switch hpa.Spec.ScaleTargetRef.Kind { case "Deployment": deployment, err := client.AppsV1().Deployments(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{}) diff --git a/pkg/collector/prometheus_collector.go b/pkg/collector/prometheus_collector.go index e22accc..1700313 100644 --- a/pkg/collector/prometheus_collector.go +++ b/pkg/collector/prometheus_collector.go @@ -9,7 +9,7 @@ import ( "github.com/prometheus/client_golang/api" promv1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/prometheus/common/model" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -38,7 +38,7 @@ func NewPrometheusCollectorPlugin(client kubernetes.Interface, prometheusServer }, nil } -func (p *PrometheusCollectorPlugin) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { +func (p *PrometheusCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { return NewPrometheusCollector(p.client, p.promAPI, hpa, config, interval) } @@ -46,19 +46,19 @@ type PrometheusCollector struct { client kubernetes.Interface promAPI promv1.API query string - metricName string - metricType autoscalingv2beta1.MetricSourceType + metric autoscalingv2.MetricIdentifier + metricType autoscalingv2.MetricSourceType objectReference custom_metrics.ObjectReference interval time.Duration perReplica bool - hpa *autoscalingv2beta1.HorizontalPodAutoscaler + hpa *autoscalingv2.HorizontalPodAutoscaler } -func NewPrometheusCollector(client kubernetes.Interface, promAPI promv1.API, hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (*PrometheusCollector, error) { +func NewPrometheusCollector(client kubernetes.Interface, promAPI promv1.API, hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (*PrometheusCollector, error) { c := &PrometheusCollector{ client: client, objectReference: config.ObjectReference, - metricName: config.Name, + metric: config.Metric, metricType: config.Type, interval: interval, promAPI: promAPI, @@ -117,7 +117,7 @@ func (c *PrometheusCollector) GetMetrics() ([]CollectedMetric, error) { Type: c.metricType, Custom: custom_metrics.MetricValue{ DescribedObject: c.objectReference, - MetricName: c.metricName, + Metric: custom_metrics.MetricIdentifier{Name: c.metric.Name, Selector: c.metric.Selector}, Timestamp: metav1.Time{Time: time.Now().UTC()}, Value: *resource.NewMilliQuantity(int64(sampleValue*1000), resource.DecimalSI), }, diff --git a/pkg/collector/skipper_collector.go b/pkg/collector/skipper_collector.go index 4c60c6a..f70376d 100644 --- a/pkg/collector/skipper_collector.go +++ b/pkg/collector/skipper_collector.go @@ -7,7 +7,7 @@ import ( "strings" "time" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/metrics/pkg/apis/custom_metrics" @@ -37,27 +37,27 @@ func NewSkipperCollectorPlugin(client kubernetes.Interface, prometheusPlugin *Pr } // NewCollector initializes a new skipper collector from the specified HPA. -func (c *SkipperCollectorPlugin) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { - if strings.HasPrefix(config.Name, rpsMetricName) { +func (c *SkipperCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { + if strings.HasPrefix(config.Metric.Name, rpsMetricName) { backend := "" - if len(config.Name) > len(rpsMetricName) { - metricNameParts := strings.Split(config.Name, rpsMetricBackendSeparator) + if len(config.Metric.Name) > len(rpsMetricName) { + metricNameParts := strings.Split(config.Metric.Name, rpsMetricBackendSeparator) if len(metricNameParts) == 2 { backend = metricNameParts[1] } } return NewSkipperCollector(c.client, c.plugin, hpa, config, interval, c.backendAnnotations, backend) } - return nil, fmt.Errorf("metric '%s' not supported", config.Name) + return nil, fmt.Errorf("metric '%s' not supported", config.Metric.Name) } // SkipperCollector is a metrics collector for getting skipper ingress metrics. // It depends on the prometheus collector for getting the metrics. type SkipperCollector struct { client kubernetes.Interface - metricName string + metric autoscalingv2.MetricIdentifier objectReference custom_metrics.ObjectReference - hpa *autoscalingv2beta1.HorizontalPodAutoscaler + hpa *autoscalingv2.HorizontalPodAutoscaler interval time.Duration plugin CollectorPlugin config MetricConfig @@ -66,13 +66,13 @@ type SkipperCollector struct { } // NewSkipperCollector initializes a new SkipperCollector. -func NewSkipperCollector(client kubernetes.Interface, plugin CollectorPlugin, hpa *autoscalingv2beta1.HorizontalPodAutoscaler, +func NewSkipperCollector(client kubernetes.Interface, plugin CollectorPlugin, hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration, backendAnnotations []string, backend string) (*SkipperCollector, error) { return &SkipperCollector{ client: client, objectReference: config.ObjectReference, hpa: hpa, - metricName: config.Name, + metric: config.Metric, interval: interval, plugin: plugin, config: *config, @@ -190,7 +190,7 @@ func (c *SkipperCollector) Interval() time.Duration { return c.interval } -func targetRefReplicas(client kubernetes.Interface, hpa *autoscalingv2beta1.HorizontalPodAutoscaler) (int32, error) { +func targetRefReplicas(client kubernetes.Interface, hpa *autoscalingv2.HorizontalPodAutoscaler) (int32, error) { var replicas int32 switch hpa.Spec.ScaleTargetRef.Kind { case "Deployment": diff --git a/pkg/collector/skipper_collector_test.go b/pkg/collector/skipper_collector_test.go index f465433..c58567e 100644 --- a/pkg/collector/skipper_collector_test.go +++ b/pkg/collector/skipper_collector_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/require" "k8s.io/api/apps/v1" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" ) @@ -32,7 +32,7 @@ func TestTargetRefReplicasDeployments(t *testing.T) { require.NoError(t, err) // Create an HPA with the deployment as ref - hpa, err := client.AutoscalingV2beta1().HorizontalPodAutoscalers(deployment.Namespace). + hpa, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers(deployment.Namespace). Create(newHPA(defaultNamespace, name, "Deployment")) require.NoError(t, err) @@ -49,7 +49,7 @@ func TestTargetRefReplicasStatefulSets(t *testing.T) { require.NoError(t, err) // Create an HPA with the statefulSet as ref - hpa, err := client.AutoscalingV2beta1().HorizontalPodAutoscalers(statefulSet.Namespace). + hpa, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers(statefulSet.Namespace). Create(newHPA(defaultNamespace, name, "StatefulSet")) require.NoError(t, err) @@ -58,18 +58,18 @@ func TestTargetRefReplicasStatefulSets(t *testing.T) { require.Equal(t, statefulSet.Status.Replicas, replicas) } -func newHPA(namesapce string, refName string, refKind string) *autoscalingv2beta1.HorizontalPodAutoscaler { - return &autoscalingv2beta1.HorizontalPodAutoscaler{ +func newHPA(namesapce string, refName string, refKind string) *autoscalingv2.HorizontalPodAutoscaler { + return &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ Name: namesapce, }, - Spec: autoscalingv2beta1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv2beta1.CrossVersionObjectReference{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Name: refName, Kind: refKind, }, }, - Status: autoscalingv2beta1.HorizontalPodAutoscalerStatus{}, + Status: autoscalingv2.HorizontalPodAutoscalerStatus{}, } } @@ -253,19 +253,19 @@ func makeIngress(client kubernetes.Interface, namespace, ingressName, backend st return err } -func makeHPA(ingressName, backend string) *autoscalingv2beta1.HorizontalPodAutoscaler { - return &autoscalingv2beta1.HorizontalPodAutoscaler{ - Spec: autoscalingv2beta1.HorizontalPodAutoscalerSpec{ - ScaleTargetRef: autoscalingv2beta1.CrossVersionObjectReference{ +func makeHPA(ingressName, backend string) *autoscalingv2.HorizontalPodAutoscaler { + return &autoscalingv2.HorizontalPodAutoscaler{ + Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ + ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", Name: backend, }, - Metrics: []autoscalingv2beta1.MetricSpec{ + Metrics: []autoscalingv2.MetricSpec{ { - Type: autoscalingv2beta1.ObjectMetricSourceType, - Object: &autoscalingv2beta1.ObjectMetricSource{ - Target: autoscalingv2beta1.CrossVersionObjectReference{Name: ingressName, APIVersion: "extensions/v1", Kind: "Ingress"}, - MetricName: fmt.Sprintf("%s,%s", rpsMetricName, backend), + Type: autoscalingv2.ObjectMetricSourceType, + Object: &autoscalingv2.ObjectMetricSource{ + DescribedObject: autoscalingv2.CrossVersionObjectReference{Name: ingressName, APIVersion: "extensions/v1", Kind: "Ingress"}, + Metric: autoscalingv2.MetricIdentifier{Name: fmt.Sprintf("%s,%s", rpsMetricName, backend)}, }, }, }, @@ -274,7 +274,7 @@ func makeHPA(ingressName, backend string) *autoscalingv2beta1.HorizontalPodAutos } func makeConfig(backend string) *MetricConfig { return &MetricConfig{ - MetricTypeName: MetricTypeName{Name: fmt.Sprintf("%s,%s", rpsMetricName, backend)}, + MetricTypeName: MetricTypeName{Metric: autoscalingv2.MetricIdentifier{Name: fmt.Sprintf("%s,%s", rpsMetricName, backend)}}, } } @@ -294,7 +294,7 @@ func (FakeCollector) Interval() time.Duration { return time.Minute } -func (p *FakeCollectorPlugin) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { +func (p *FakeCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { return &FakeCollector{metrics: p.metrics}, nil } diff --git a/pkg/collector/zmon_collector.go b/pkg/collector/zmon_collector.go index 8104131..22499d3 100644 --- a/pkg/collector/zmon_collector.go +++ b/pkg/collector/zmon_collector.go @@ -7,7 +7,7 @@ import ( "time" "github.com/zalando-incubator/kube-metrics-adapter/pkg/zmon" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/metrics/pkg/apis/external_metrics" @@ -41,8 +41,8 @@ func NewZMONCollectorPlugin(zmon zmon.ZMON) (*ZMONCollectorPlugin, error) { } // NewCollector initializes a new ZMON collector from the specified HPA. -func (c *ZMONCollectorPlugin) NewCollector(hpa *autoscalingv2beta1.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { - switch config.Name { +func (c *ZMONCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) { + switch config.Metric.Name { case ZMONCheckMetric: annotations := map[string]string{} if hpa != nil { @@ -51,7 +51,7 @@ func (c *ZMONCollectorPlugin) NewCollector(hpa *autoscalingv2beta1.HorizontalPod return NewZMONCollector(c.zmon, config, annotations, interval) } - return nil, fmt.Errorf("metric '%s' not supported", config.Name) + return nil, fmt.Errorf("metric '%s' not supported", config.Metric.Name) } // ZMONCollector defines a collector that is able to collect metrics from ZMON. @@ -60,17 +60,16 @@ type ZMONCollector struct { interval time.Duration checkID int key string - labels map[string]string tags map[string]string duration time.Duration aggregators []string - metricName string - metricType autoscalingv2beta1.MetricSourceType + metric autoscalingv2.MetricIdentifier + metricType autoscalingv2.MetricSourceType } // NewZMONCollector initializes a new ZMONCollector. func NewZMONCollector(zmon zmon.ZMON, config *MetricConfig, annotations map[string]string, interval time.Duration) (*ZMONCollector, error) { - checkIDStr, ok := config.Labels[zmonCheckIDLabelKey] + checkIDStr, ok := config.Configuration[zmonCheckIDLabelKey] if !ok { return nil, fmt.Errorf("ZMON check ID not specified on metric") } @@ -83,7 +82,7 @@ func NewZMONCollector(zmon zmon.ZMON, config *MetricConfig, annotations map[stri key := "" // get optional key - if k, ok := config.Labels[zmonKeyLabelKey]; ok { + if k, ok := config.Configuration[zmonKeyLabelKey]; ok { key = k } @@ -95,7 +94,7 @@ func NewZMONCollector(zmon zmon.ZMON, config *MetricConfig, annotations map[stri duration := defaultQueryDuration // parse optional duration value - if d, ok := config.Labels[zmonDurationLabelKey]; ok { + if d, ok := config.Configuration[zmonDurationLabelKey]; ok { duration, err = time.ParseDuration(d) if err != nil { return nil, err @@ -104,7 +103,7 @@ func NewZMONCollector(zmon zmon.ZMON, config *MetricConfig, annotations map[stri // parse tags tags := make(map[string]string) - for k, v := range config.Labels { + for k, v := range config.Configuration { if strings.HasPrefix(k, zmonTagPrefixLabelKey) { key := strings.TrimPrefix(k, zmonTagPrefixLabelKey) tags[key] = v @@ -123,7 +122,7 @@ func NewZMONCollector(zmon zmon.ZMON, config *MetricConfig, annotations map[stri // default aggregator is last aggregators := []string{"last"} - if k, ok := config.Labels[zmonAggregatorsLabelKey]; ok { + if k, ok := config.Configuration[zmonAggregatorsLabelKey]; ok { aggregators = strings.Split(k, ",") } @@ -135,9 +134,8 @@ func NewZMONCollector(zmon zmon.ZMON, config *MetricConfig, annotations map[stri tags: tags, duration: duration, aggregators: aggregators, - metricName: config.Name, + metric: config.Metric, metricType: config.Type, - labels: config.Labels, }, nil } @@ -159,8 +157,8 @@ func (c *ZMONCollector) GetMetrics() ([]CollectedMetric, error) { metricValue := CollectedMetric{ Type: c.metricType, External: external_metrics.ExternalMetricValue{ - MetricName: c.metricName, - MetricLabels: c.labels, + MetricName: c.metric.Name, + MetricLabels: c.metric.Selector.MatchLabels, Timestamp: metav1.Time{Time: point.Time}, Value: *resource.NewMilliQuantity(int64(point.Value*1000), resource.DecimalSI), }, diff --git a/pkg/collector/zmon_collector_test.go b/pkg/collector/zmon_collector_test.go index 51ac63f..364b0cd 100644 --- a/pkg/collector/zmon_collector_test.go +++ b/pkg/collector/zmon_collector_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" "github.com/zalando-incubator/kube-metrics-adapter/pkg/zmon" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/metrics/pkg/apis/external_metrics" @@ -26,9 +26,9 @@ func TestZMONCollectorNewCollector(t *testing.T) { config := &MetricConfig{ MetricTypeName: MetricTypeName{ - Name: ZMONCheckMetric, + Metric: newMetricIdentifier(ZMONCheckMetric), }, - Labels: map[string]string{ + Configuration: map[string]string{ zmonCheckIDLabelKey: "1234", zmonAggregatorsLabelKey: "max", zmonTagPrefixLabelKey + "alias": "cluster_alias", @@ -37,7 +37,7 @@ func TestZMONCollectorNewCollector(t *testing.T) { }, } - hpa := &autoscalingv2beta1.HorizontalPodAutoscaler{} + hpa := &autoscalingv2.HorizontalPodAutoscaler{} collector, err := collectPlugin.NewCollector(hpa, config, 1*time.Second) require.NoError(t, err) @@ -65,24 +65,30 @@ func TestZMONCollectorNewCollector(t *testing.T) { require.Equal(t, map[string]string{"alias": "cluster_alias_annotation"}, zmonCollector.tags) // should fail if the metric name isn't ZMON - config.Name = "non-zmon-check" + config.Metric = newMetricIdentifier("non-zmon-check") _, err = collectPlugin.NewCollector(nil, config, 1*time.Second) require.Error(t, err) // should fail if the check id is not specified. - delete(config.Labels, zmonCheckIDLabelKey) - config.Name = ZMONCheckMetric + delete(config.Configuration, zmonCheckIDLabelKey) + config.Metric.Name = ZMONCheckMetric _, err = collectPlugin.NewCollector(nil, config, 1*time.Second) require.Error(t, err) } +func newMetricIdentifier(metricName string) autoscalingv2.MetricIdentifier { + selector := metav1.LabelSelector{} + return autoscalingv2.MetricIdentifier{Name: metricName, Selector: &selector} +} + func TestZMONCollectorGetMetrics(tt *testing.T) { + config := &MetricConfig{ MetricTypeName: MetricTypeName{ - Name: ZMONCheckMetric, - Type: "foo", + Metric: newMetricIdentifier(ZMONCheckMetric), + Type: "foo", }, - Labels: map[string]string{ + Configuration: map[string]string{ zmonCheckIDLabelKey: "1234", zmonAggregatorsLabelKey: "max", zmonTagPrefixLabelKey + "alias": "cluster_alias", @@ -108,8 +114,8 @@ func TestZMONCollectorGetMetrics(tt *testing.T) { { Type: config.Type, External: external_metrics.ExternalMetricValue{ - MetricName: config.Name, - MetricLabels: config.Labels, + MetricName: config.Metric.Name, + MetricLabels: config.Metric.Selector.MatchLabels, Timestamp: metav1.Time{Time: time.Time{}}, Value: *resource.NewMilliQuantity(int64(1.0)*1000, resource.DecimalSI), }, diff --git a/pkg/provider/hpa.go b/pkg/provider/hpa.go index 2009431..0d6b673 100644 --- a/pkg/provider/hpa.go +++ b/pkg/provider/hpa.go @@ -12,7 +12,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/zalando-incubator/kube-metrics-adapter/pkg/collector" "github.com/zalando-incubator/kube-metrics-adapter/pkg/recorder" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -46,10 +46,6 @@ var ( }) ) -type objectCollector struct { - ObjectReference *autoscalingv2beta1.CrossVersionObjectReference -} - // HPAProvider is a base provider for initializing metric collectors based on // HPA resources. type HPAProvider struct { @@ -58,7 +54,7 @@ type HPAProvider struct { collectorScheduler *CollectorScheduler collectorInterval time.Duration metricSink chan metricCollection - hpaCache map[resourceReference]autoscalingv2beta1.HorizontalPodAutoscaler + hpaCache map[resourceReference]autoscalingv2.HorizontalPodAutoscaler metricStore *MetricStore collectorFactory *collector.CollectorFactory recorder kube_record.EventRecorder @@ -120,12 +116,12 @@ func (p *HPAProvider) Run(ctx context.Context) { func (p *HPAProvider) updateHPAs() error { p.logger.Info("Looking for HPAs") - hpas, err := p.client.AutoscalingV2beta1().HorizontalPodAutoscalers(metav1.NamespaceAll).List(metav1.ListOptions{}) + hpas, err := p.client.AutoscalingV2beta2().HorizontalPodAutoscalers(metav1.NamespaceAll).List(metav1.ListOptions{}) if err != nil { return err } - newHPACache := make(map[resourceReference]autoscalingv2beta1.HorizontalPodAutoscaler, len(hpas.Items)) + newHPACache := make(map[resourceReference]autoscalingv2.HorizontalPodAutoscaler, len(hpas.Items)) newHPAs := 0 @@ -187,7 +183,7 @@ func (p *HPAProvider) updateHPAs() error { } // equalHPA returns true if two HPAs are identical (apart from their status). -func equalHPA(a, b autoscalingv2beta1.HorizontalPodAutoscaler) bool { +func equalHPA(a, b autoscalingv2.HorizontalPodAutoscaler) bool { // reset resource version to not compare it since this will change // whenever the status of the object is updated. We only want to // compare the metadata and the spec. @@ -225,15 +221,15 @@ func (p *HPAProvider) collectMetrics(ctx context.Context) { p.logger.Infof("Collected %d new metric(s)", len(collection.Values)) for _, value := range collection.Values { switch value.Type { - case autoscalingv2beta1.ObjectMetricSourceType, autoscalingv2beta1.PodsMetricSourceType: + case autoscalingv2.ObjectMetricSourceType, autoscalingv2.PodsMetricSourceType: p.logger.Infof("Collected new custom metric '%s' (%s) for %s %s/%s", - value.Custom.MetricName, + value.Custom.Metric.Name, value.Custom.Value.String(), value.Custom.DescribedObject.Kind, value.Custom.DescribedObject.Namespace, value.Custom.DescribedObject.Name, ) - case autoscalingv2beta1.ExternalMetricSourceType: + case autoscalingv2.ExternalMetricSourceType: p.logger.Infof("Collected new external metric '%s' (%s) [%s]", value.External.MetricName, value.External.Value.String(), diff --git a/pkg/provider/metric_store.go b/pkg/provider/metric_store.go index 31b6351..d086486 100644 --- a/pkg/provider/metric_store.go +++ b/pkg/provider/metric_store.go @@ -9,7 +9,7 @@ import ( "github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/provider" "github.com/zalando-incubator/kube-metrics-adapter/pkg/collector" - autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" @@ -20,9 +20,8 @@ import ( // customMetricsStoredMetric is a wrapper around custom_metrics.MetricValue with a metricsTTL used // to clean up stale metrics from the customMetricsStore. type customMetricsStoredMetric struct { - Value custom_metrics.MetricValue - Labels map[string]string - TTL time.Time + Value custom_metrics.MetricValue + TTL time.Time } type externalMetricsStoredMetric struct { @@ -50,15 +49,15 @@ func NewMetricStore(ttlCalculator func() time.Time) *MetricStore { // Insert inserts a collected metric into the metric customMetricsStore. func (s *MetricStore) Insert(value collector.CollectedMetric) { switch value.Type { - case autoscalingv2beta1.ObjectMetricSourceType, autoscalingv2beta1.PodsMetricSourceType: - s.insertCustomMetric(value.Custom, value.Labels) - case autoscalingv2beta1.ExternalMetricSourceType: + case autoscalingv2.ObjectMetricSourceType, autoscalingv2.PodsMetricSourceType: + s.insertCustomMetric(value.Custom) + case autoscalingv2.ExternalMetricSourceType: s.insertExternalMetric(value.External) } } // insertCustomMetric inserts a custom metric plus labels into the store. -func (s *MetricStore) insertCustomMetric(value custom_metrics.MetricValue, labels map[string]string) { +func (s *MetricStore) insertCustomMetric(value custom_metrics.MetricValue) { s.Lock() defer s.Unlock() @@ -77,15 +76,14 @@ func (s *MetricStore) insertCustomMetric(value custom_metrics.MetricValue, label } metric := customMetricsStoredMetric{ - Value: value, - Labels: labels, - TTL: s.metricsTTLCalculator(), // TODO: make TTL configurable + Value: value, + TTL: s.metricsTTLCalculator(), // TODO: make TTL configurable } - metrics, ok := s.customMetricsStore[value.MetricName] + metrics, ok := s.customMetricsStore[value.Metric.Name] if !ok { - s.customMetricsStore[value.MetricName] = map[schema.GroupResource]map[string]map[string]customMetricsStoredMetric{ - groupResource: map[string]map[string]customMetricsStoredMetric{ + s.customMetricsStore[value.Metric.Name] = map[schema.GroupResource]map[string]map[string]customMetricsStoredMetric{ + groupResource: { value.DescribedObject.Namespace: map[string]customMetricsStoredMetric{ value.DescribedObject.Name: metric, }, @@ -97,7 +95,7 @@ func (s *MetricStore) insertCustomMetric(value custom_metrics.MetricValue, label group, ok := metrics[groupResource] if !ok { metrics[groupResource] = map[string]map[string]customMetricsStoredMetric{ - value.DescribedObject.Namespace: map[string]customMetricsStoredMetric{ + value.DescribedObject.Namespace: { value.DescribedObject.Name: metric, }, } @@ -168,14 +166,14 @@ func (s *MetricStore) GetMetricsBySelector(namespace string, selector labels.Sel if !info.Namespaced { for _, metricMap := range group { for _, metric := range metricMap { - if selector.Matches(labels.Set(metric.Labels)) { + if selector.Matches(labels.Set(metric.Value.Metric.Selector.MatchLabels)) { matchedMetrics = append(matchedMetrics, metric.Value) } } } } else if metricMap, ok := group[namespace]; ok { for _, metric := range metricMap { - if selector.Matches(labels.Set(metric.Labels)) { + if selector.Matches(labels.Set(metric.Value.Metric.Selector.MatchLabels)) { matchedMetrics = append(matchedMetrics, metric.Value) } } @@ -222,13 +220,13 @@ func (s *MetricStore) ListAllMetrics() []provider.CustomMetricInfo { metrics := make([]provider.CustomMetricInfo, 0, len(s.customMetricsStore)) - for metricName, customMetricsStoredMetrics := range s.customMetricsStore { + for metric, customMetricsStoredMetrics := range s.customMetricsStore { for groupResource, group := range customMetricsStoredMetrics { for namespace := range group { metric := provider.CustomMetricInfo{ GroupResource: groupResource, Namespaced: namespace != "", - Metric: metricName, + Metric: metric, } metrics = append(metrics, metric) } diff --git a/pkg/provider/metrics_store_test.go b/pkg/provider/metrics_store_test.go index 3fa3040..a773b30 100644 --- a/pkg/provider/metrics_store_test.go +++ b/pkg/provider/metrics_store_test.go @@ -4,8 +4,9 @@ import ( "github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/provider" "github.com/stretchr/testify/require" "github.com/zalando-incubator/kube-metrics-adapter/pkg/collector" - "k8s.io/api/autoscaling/v2beta1" + autoscalingv2 "k8s.io/api/autoscaling/v2beta2" "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" @@ -15,6 +16,13 @@ import ( "time" ) +func newMetricIdentifier(metricName string) custom_metrics.MetricIdentifier { + selector := metav1.LabelSelector{} + return custom_metrics.MetricIdentifier{ + Name: metricName, + Selector: &selector, + } +} func TestInternalMetricStorage(t *testing.T) { var metricStoreTests = []struct { test string @@ -33,10 +41,10 @@ func TestInternalMetricStorage(t *testing.T) { { test: "insert/list/get a namespaced resource metric", insert: collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "default", @@ -80,10 +88,10 @@ func TestInternalMetricStorage(t *testing.T) { { test: "insert/list/get a Pod metric", insert: collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "default", @@ -136,10 +144,10 @@ func TestInternalMetricStorage(t *testing.T) { { test: "insert/list/get a non-namespaced resource metric", insert: collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Kind: "Node", @@ -182,10 +190,10 @@ func TestInternalMetricStorage(t *testing.T) { { test: "insert/list/get an Ingress metric", insert: collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Kind: "Ingress", @@ -286,10 +294,10 @@ func TestMultipleMetricValues(t *testing.T) { test: "insert/list/get multiple Ingress metrics", insert: []collector.CollectedMetric{ { - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Kind: "Ingress", @@ -298,10 +306,10 @@ func TestMultipleMetricValues(t *testing.T) { }, }, { - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(1, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(1, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Kind: "Ingress", @@ -355,10 +363,10 @@ func TestMultipleMetricValues(t *testing.T) { test: "insert/list/get multiple namespaced resource metrics", insert: []collector.CollectedMetric{ { - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "default", @@ -368,10 +376,10 @@ func TestMultipleMetricValues(t *testing.T) { }, }, { - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(1, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(1, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "default", @@ -489,10 +497,10 @@ func TestCustomMetricsStorageErrors(t *testing.T) { { test: "test that not all Kinds are mapped to a group/resource", insert: collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "default", @@ -581,10 +589,10 @@ func TestCustomMetricsStorageErrors(t *testing.T) { test: "insert/list/get multiple metrics in different groups", insert: []collector.CollectedMetric{ { - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "default", @@ -594,10 +602,10 @@ func TestCustomMetricsStorageErrors(t *testing.T) { }, }, { - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(1, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(1, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "default", @@ -607,10 +615,10 @@ func TestCustomMetricsStorageErrors(t *testing.T) { }, }, { - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(1, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(1, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Namespace: "new-namespace", @@ -684,7 +692,7 @@ func TestExternalMetricStorage(t *testing.T) { { test: "insert/list/get an external metric", insert: collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("External"), + Type: autoscalingv2.MetricSourceType("External"), External: external_metrics.ExternalMetricValue{ MetricName: "metric-per-unit", Value: *resource.NewQuantity(0, ""), @@ -744,7 +752,7 @@ func TestMultipleExternalMetricStorage(t *testing.T) { test: "the latest value overrides the last one", insert: []collector.CollectedMetric{ { - Type: v2beta1.MetricSourceType("External"), + Type: autoscalingv2.MetricSourceType("External"), External: external_metrics.ExternalMetricValue{ MetricName: "metric-per-unit", Value: *resource.NewQuantity(0, ""), @@ -752,7 +760,7 @@ func TestMultipleExternalMetricStorage(t *testing.T) { }, }, { - Type: v2beta1.MetricSourceType("External"), + Type: autoscalingv2.MetricSourceType("External"), External: external_metrics.ExternalMetricValue{ MetricName: "metric-per-unit", Value: *resource.NewQuantity(1, ""), @@ -808,10 +816,10 @@ func TestMetricsExpiration(t *testing.T) { }) customMetric := collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Kind: "Node", @@ -821,7 +829,7 @@ func TestMetricsExpiration(t *testing.T) { } externalMetric := collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("External"), + Type: autoscalingv2.MetricSourceType("External"), External: external_metrics.ExternalMetricValue{ MetricName: "metric-per-unit", Value: *resource.NewQuantity(0, ""), @@ -847,10 +855,10 @@ func TestMetricsNonExpiration(t *testing.T) { }) customMetric := collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("Object"), + Type: autoscalingv2.MetricSourceType("Object"), Custom: custom_metrics.MetricValue{ - MetricName: "metric-per-unit", - Value: *resource.NewQuantity(0, ""), + Metric: newMetricIdentifier("metric-per-unit"), + Value: *resource.NewQuantity(0, ""), DescribedObject: custom_metrics.ObjectReference{ Name: "metricObject", Kind: "Node", @@ -860,7 +868,7 @@ func TestMetricsNonExpiration(t *testing.T) { } externalMetric := collector.CollectedMetric{ - Type: v2beta1.MetricSourceType("External"), + Type: autoscalingv2.MetricSourceType("External"), External: external_metrics.ExternalMetricValue{ MetricName: "metric-per-unit", Value: *resource.NewQuantity(0, ""),