Compare commits

...

19 Commits

Author SHA1 Message Date
be7567efea Fix handling of invalid/empty json response (#209)
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
2020-10-02 10:57:53 +02:00
b677e814be Update dependencies (#200)
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
2020-10-02 10:55:42 +02:00
deec4727ee Merge pull request #192 from zalando-incubator/extend-jsonpath-support
Support bracket notation in jsonPath
2020-09-30 12:18:39 +02:00
cf369639d8 Support bracket notation in jsonPath
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
2020-08-13 09:51:05 +02:00
262a35c2ec Merge pull request #177 from zalando-incubator/update-deps
Update dependencies
2020-07-15 17:45:01 +02:00
607386834b Update dependencies
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
2020-07-15 17:00:13 +02:00
4bdce4da4d Merge pull request #176 from zalando-incubator/ingress-weights-float64
Correctly treat ingress weight values as float64
2020-07-15 16:56:33 +02:00
801e5d7a47 Correctly treat ingress weight values as float64
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
2020-07-15 15:42:59 +02:00
4df21ae2b4 Merge pull request #174 from zalando-incubator/dependabot/add-v2-config-file
Create Dependabot config file
2020-07-10 13:31:55 +02:00
7f639baeee Create Dependabot config file 2020-07-10 09:49:34 +00:00
88ddb6f10e Merge pull request #173 from zalando-incubator/arjun-has-left-the-zalando
Update MAINTAINERS
2020-07-01 15:14:25 +02:00
d9cf2e0858 Update MAINTAINERS
Signed-off-by: Arjun Naik <arjun@arjunnaik.in>
2020-07-01 15:04:31 +02:00
c3b18e784b Update client-go (#162)
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
2020-06-27 18:39:12 +02:00
c3a03fd758 Merge pull request #157 from zalando-incubator/dependabot/go_modules/github.com/aws/aws-sdk-go-1.31.7
Bump github.com/aws/aws-sdk-go from 1.30.24 to 1.31.7
2020-06-02 09:43:49 +02:00
05704c0a6b Merge pull request #158 from zalando-incubator/dependabot/go_modules/github.com/stretchr/testify-1.6.0
Bump github.com/stretchr/testify from 1.5.1 to 1.6.0
2020-06-02 09:43:27 +02:00
f3a608fcf7 Merge pull request #159 from zalando-incubator/dependabot/go_modules/github.com/prometheus/common-0.10.0
Bump github.com/prometheus/common from 0.9.1 to 0.10.0
2020-06-02 09:43:03 +02:00
223ec9fd89 Bump github.com/prometheus/common from 0.9.1 to 0.10.0
Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.9.1 to 0.10.0.
- [Release notes](https://github.com/prometheus/common/releases)
- [Commits](https://github.com/prometheus/common/compare/v0.9.1...v0.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-01 10:47:03 +00:00
81255aa956 Bump github.com/stretchr/testify from 1.5.1 to 1.6.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.5.1 to 1.6.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.5.1...v1.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-01 10:46:34 +00:00
dac44965e3 Bump github.com/aws/aws-sdk-go from 1.30.24 to 1.31.7
Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.30.24 to 1.31.7.
- [Release notes](https://github.com/aws/aws-sdk-go/releases)
- [Changelog](https://github.com/aws/aws-sdk-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go/compare/v1.30.24...v1.31.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-01 10:46:23 +00:00
17 changed files with 464 additions and 317 deletions

35
.github/CODEOWNERS vendored
View File

@ -1,35 +0,0 @@
# These owners will be the default owners for everything in
# the repo.
* @arjunrn
# Samples for assigning codeowners below:
# Order is important; the last matching pattern takes the most
# precedence. When someone opens a pull request that only
# modifies JS files, only @js-owner and not the global
# owner(s) will be requested for a review.
# *.js @js-owner
# You can also use email addresses if you prefer. They'll be
# used to look up users just like we do for commit author
# emails.
# *.go docs@example.com
# In this example, @doctocat owns any files in the build/logs
# directory at the root of the repository and any of its
# subdirectories.
# /build/logs/ @doctocat
# The `docs/*` pattern will match files like
# `docs/getting-started.md` but not further nested files like
# `docs/build-app/troubleshooting.md`.
# docs/* docs@example.com
# In this example, @octocat owns any file in an apps directory
# anywhere in your repository.
# apps/ @octocat
# In this example, @doctocat owns any file in the `/docs`
# directory in the root of your repository.
# /docs/ @doctocat

14
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,14 @@
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: monthly
time: "07:00"
open-pull-requests-limit: 10
- package-ecosystem: docker
directory: "/"
schedule:
interval: monthly
time: "07:00"
open-pull-requests-limit: 10

View File

@ -1,3 +1,2 @@
Mikkel Larsen <mikkel.larsen@zalando.de> Mikkel Larsen <mikkel.larsen@zalando.de>
Arjun Naik <arjun.naik@zalando.de>
Team Teapot <team-teapot@zalando.de> Team Teapot <team-teapot@zalando.de>

View File

@ -142,7 +142,7 @@ example the following JSON data would be expected:
``` ```
The json-path query support depends on the The json-path query support depends on the
[github.com/oliveagle/jsonpath](https://github.com/oliveagle/jsonpath) library. [github.com/spyzhov/ajson](https://github.com/spyzhov/ajson) library.
See the README for possible queries. It's expected that the metric you query See the README for possible queries. It's expected that the metric you query
returns something that can be turned into a `float64`. returns something that can be turned into a `float64`.

27
go.mod
View File

@ -2,31 +2,30 @@ module github.com/zalando-incubator/kube-metrics-adapter
require ( require (
github.com/NYTimes/gziphandler v1.0.1 // indirect github.com/NYTimes/gziphandler v1.0.1 // indirect
github.com/aws/aws-sdk-go v1.30.24 github.com/aws/aws-sdk-go v1.35.0
github.com/googleapis/gnostic v0.2.0 // indirect github.com/googleapis/gnostic v0.2.0 // indirect
github.com/influxdata/influxdb-client-go v0.1.5 github.com/influxdata/influxdb-client-go v0.1.5
github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20200323093244-5046ce1afe6b github.com/kubernetes-incubator/custom-metrics-apiserver v0.0.0-20200618121405-54026617ec44
github.com/lib/pq v1.2.0 // indirect github.com/lib/pq v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.4 // indirect github.com/mattn/go-colorable v0.1.4 // indirect
github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852
github.com/onsi/ginkgo v1.11.0 // indirect
github.com/onsi/gomega v1.8.1 // indirect github.com/onsi/gomega v1.8.1 // indirect
github.com/prometheus/client_golang v1.6.0 github.com/prometheus/client_golang v1.7.1
github.com/prometheus/common v0.9.1 github.com/prometheus/common v0.14.0
github.com/sirupsen/logrus v1.6.0 github.com/sirupsen/logrus v1.7.0
github.com/spf13/cobra v0.0.7 github.com/spf13/cobra v0.0.7
github.com/stretchr/testify v1.5.1 github.com/spyzhov/ajson v0.4.2
github.com/stretchr/testify v1.6.1
github.com/zalando-incubator/cluster-lifecycle-manager v0.0.0-20180921141935-824b77fb1f84 github.com/zalando-incubator/cluster-lifecycle-manager v0.0.0-20180921141935-824b77fb1f84
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 // indirect
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
golang.org/x/tools v0.0.0-20200204192400-7124308813f3 // indirect golang.org/x/tools v0.0.0-20200204192400-7124308813f3 // indirect
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e // indirect
honnef.co/go/tools v0.0.1-2020.1.3 // indirect honnef.co/go/tools v0.0.1-2020.1.3 // indirect
k8s.io/api v0.17.3 k8s.io/api v0.18.8
k8s.io/apimachinery v0.17.4 k8s.io/apimachinery v0.18.8
k8s.io/client-go v0.17.3 k8s.io/client-go v0.18.8
k8s.io/component-base v0.17.3 k8s.io/component-base v0.18.8
k8s.io/klog v1.0.0 k8s.io/klog v1.0.0
k8s.io/metrics v0.17.3 k8s.io/metrics v0.18.8
) )
go 1.13 go 1.13

337
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@ import (
"github.com/zalando-incubator/kube-metrics-adapter/pkg/collector/httpmetrics" "github.com/zalando-incubator/kube-metrics-adapter/pkg/collector/httpmetrics"
"github.com/oliveagle/jsonpath"
"k8s.io/api/autoscaling/v2beta2" "k8s.io/api/autoscaling/v2beta2"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -36,14 +35,12 @@ func (p *HTTPCollectorPlugin) NewCollector(_ *v2beta2.HorizontalPodAutoscaler, c
if value, ok = config.Config[HTTPJsonPathAnnotationKey]; !ok { if value, ok = config.Config[HTTPJsonPathAnnotationKey]; !ok {
return nil, fmt.Errorf("config value %s not found", HTTPJsonPathAnnotationKey) return nil, fmt.Errorf("config value %s not found", HTTPJsonPathAnnotationKey)
} }
jsonPath, err := jsonpath.Compile(value) jsonPath := value
if err != nil {
return nil, fmt.Errorf("failed to parse json path: %v", err)
}
collector.jsonPath = jsonPath
if value, ok = config.Config[HTTPEndpointAnnotationKey]; !ok { if value, ok = config.Config[HTTPEndpointAnnotationKey]; !ok {
return nil, fmt.Errorf("config value %s not found", HTTPEndpointAnnotationKey) return nil, fmt.Errorf("config value %s not found", HTTPEndpointAnnotationKey)
} }
var err error
collector.endpoint, err = url.Parse(value) collector.endpoint, err = url.Parse(value)
if err != nil { if err != nil {
return nil, err return nil, err
@ -65,13 +62,16 @@ func (p *HTTPCollectorPlugin) NewCollector(_ *v2beta2.HorizontalPodAutoscaler, c
return nil, err return nil, err
} }
} }
collector.metricsGetter = httpmetrics.NewJSONPathMetricsGetter(httpmetrics.DefaultMetricsHTTPClient(), aggFunc, jsonPath) jsonPathGetter, err := httpmetrics.NewJSONPathMetricsGetter(httpmetrics.DefaultMetricsHTTPClient(), aggFunc, jsonPath)
if err != nil {
return nil, err
}
collector.metricsGetter = jsonPathGetter
return collector, nil return collector, nil
} }
type HTTPCollector struct { type HTTPCollector struct {
endpoint *url.URL endpoint *url.URL
jsonPath *jsonpath.Compiled
interval time.Duration interval time.Duration
metricType v2beta2.MetricSourceType metricType v2beta2.MetricSourceType
metricsGetter *httpmetrics.JSONPathMetricsGetter metricsGetter *httpmetrics.JSONPathMetricsGetter

View File

@ -1,7 +1,6 @@
package httpmetrics package httpmetrics
import ( import (
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net" "net"
@ -9,21 +8,26 @@ import (
"net/url" "net/url"
"time" "time"
"github.com/oliveagle/jsonpath" "github.com/spyzhov/ajson"
) )
// JSONPathMetricsGetter is a metrics getter which looks up pod metrics by // JSONPathMetricsGetter is a metrics getter which looks up pod metrics by
// querying the pods metrics endpoint and lookup the metric value as defined by // querying the pods metrics endpoint and lookup the metric value as defined by
// the json path query. // the json path query.
type JSONPathMetricsGetter struct { type JSONPathMetricsGetter struct {
jsonPath *jsonpath.Compiled jsonPath string
aggregator AggregatorFunc aggregator AggregatorFunc
client *http.Client client *http.Client
} }
// NewJSONPathMetricsGetter initializes a new JSONPathMetricsGetter. // NewJSONPathMetricsGetter initializes a new JSONPathMetricsGetter.
func NewJSONPathMetricsGetter(httpClient *http.Client, aggregatorFunc AggregatorFunc, compiledPath *jsonpath.Compiled) *JSONPathMetricsGetter { func NewJSONPathMetricsGetter(httpClient *http.Client, aggregatorFunc AggregatorFunc, jsonPath string) (*JSONPathMetricsGetter, error) {
return &JSONPathMetricsGetter{client: httpClient, aggregator: aggregatorFunc, jsonPath: compiledPath} // check that jsonPath parses
_, err := ajson.ParseJSONPath(jsonPath)
if err != nil {
return nil, err
}
return &JSONPathMetricsGetter{client: httpClient, aggregator: aggregatorFunc, jsonPath: jsonPath}, nil
} }
var DefaultRequestTimeout = 15 * time.Second var DefaultRequestTimeout = 15 * time.Second
@ -58,57 +62,45 @@ func (g *JSONPathMetricsGetter) GetMetric(metricsURL url.URL) (float64, error) {
} }
// parse data // parse data
var jsonData interface{} root, err := ajson.Unmarshal(data)
err = json.Unmarshal(data, &jsonData)
if err != nil { if err != nil {
return 0, err return 0, err
} }
res, err := g.jsonPath.Lookup(jsonData) nodes, err := root.JSONPath(g.jsonPath)
if err != nil { if err != nil {
return 0, err return 0, err
} }
switch res := res.(type) { if len(nodes) != 1 {
case int: return 0, fmt.Errorf("unexpected json: expected single numeric or array value")
return float64(res), nil }
case float32:
return float64(res), nil node := nodes[0]
case float64: if node.IsArray() {
return res, nil
case []interface{}:
if g.aggregator == nil { if g.aggregator == nil {
return 0, fmt.Errorf("no aggregator function has been specified") return 0, fmt.Errorf("no aggregator function has been specified")
} }
s, err := castSlice(res) values := make([]float64, 0, len(nodes))
items, _ := node.GetArray()
for _, item := range items {
value, err := item.GetNumeric()
if err != nil { if err != nil {
return 0, err return 0, fmt.Errorf("did not find numeric type: %w", err)
} }
return g.aggregator(s...), nil values = append(values, value)
default:
return 0, fmt.Errorf("unsupported type %T", res)
} }
return g.aggregator(values...), nil
} else if node.IsNumeric() {
res, _ := node.GetNumeric()
return res, nil
} }
// castSlice takes a slice of interface and returns a slice of float64 if all value, err := node.Value()
// values in slice were castable, else returns an error if err != nil {
func castSlice(in []interface{}) ([]float64, error) { return 0, fmt.Errorf("failed to check value of jsonPath result: %w", err)
var out []float64
for _, v := range in {
switch v := v.(type) {
case int:
out = append(out, float64(v))
case float32:
out = append(out, float64(v))
case float64:
out = append(out, v)
default:
return nil, fmt.Errorf("slice was returned by JSONPath, but value inside is unsupported: %T", v)
} }
} return 0, fmt.Errorf("unsupported type %T", value)
return out, nil
} }
func (g *JSONPathMetricsGetter) fetchMetrics(metricsURL url.URL) ([]byte, error) { func (g *JSONPathMetricsGetter) fetchMetrics(metricsURL url.URL) ([]byte, error) {

View File

@ -1,59 +1,21 @@
package httpmetrics package httpmetrics
import ( import (
"encoding/json" "errors"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"testing" "testing"
"github.com/oliveagle/jsonpath"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestCastSlice(t *testing.T) { func makeTestHTTPServer(t *testing.T, response []byte) *httptest.Server {
res1, err1 := castSlice([]interface{}{1, 2, 3})
require.NoError(t, err1)
require.Equal(t, []float64{1.0, 2.0, 3.0}, res1)
res2, err2 := castSlice([]interface{}{float32(1.0), float32(2.0), float32(3.0)})
require.NoError(t, err2)
require.Equal(t, []float64{1.0, 2.0, 3.0}, res2)
res3, err3 := castSlice([]interface{}{float64(1.0), float64(2.0), float64(3.0)})
require.NoError(t, err3)
require.Equal(t, []float64{1.0, 2.0, 3.0}, res3)
res4, err4 := castSlice([]interface{}{1, 2, "some string"})
require.Errorf(t, err4, "slice was returned by JSONPath, but value inside is unsupported: %T", "string")
require.Equal(t, []float64(nil), res4)
}
type testValueResponse struct {
Value int64 `json:"value"`
}
type testValueArrayResponse struct {
Value []int64 `json:"value"`
}
func makeTestHTTPServer(t *testing.T, values ...int64) *httptest.Server {
h := func(w http.ResponseWriter, r *http.Request) { h := func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, r.URL.Path, "/metrics") require.Equal(t, r.URL.Path, "/metrics")
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
var ( _, err := w.Write(response)
response []byte
err error
)
if len(values) == 1 {
response, err = json.Marshal(testValueResponse{Value: values[0]})
require.NoError(t, err)
} else {
response, err = json.Marshal(testValueArrayResponse{Value: values})
require.NoError(t, err)
}
_, err = w.Write(response)
require.NoError(t, err) require.NoError(t, err)
} }
return httptest.NewServer(http.HandlerFunc(h)) return httptest.NewServer(http.HandlerFunc(h))
@ -62,28 +24,61 @@ func makeTestHTTPServer(t *testing.T, values ...int64) *httptest.Server {
func TestJSONPathMetricsGetter(t *testing.T) { func TestJSONPathMetricsGetter(t *testing.T) {
for _, tc := range []struct { for _, tc := range []struct {
name string name string
input []int64 jsonResponse []byte
output float64 jsonPath string
result float64
aggregator AggregatorFunc aggregator AggregatorFunc
err error
}{ }{
{ {
name: "basic average", name: "basic single value",
input: []int64{3, 4, 5}, jsonResponse: []byte(`{"value":3}`),
output: 4, jsonPath: "$.value",
result: 3,
aggregator: Average, aggregator: Average,
}, },
{
name: "basic average",
jsonResponse: []byte(`{"value":[3,4,5]}`),
jsonPath: "$.value",
result: 4,
aggregator: Average,
},
{
name: "dotted key",
jsonResponse: []byte(`{"metric.value":5}`),
jsonPath: "$['metric.value']",
result: 5,
aggregator: Average,
},
{
name: "json path not resulting in array or number should lead to error",
jsonResponse: []byte(`{"metric.value":5}`),
jsonPath: "$['invalid.metric.values']",
err: errors.New("unexpected json: expected single numeric or array value"),
},
{
name: "invalid json should error",
jsonResponse: []byte(`{`),
jsonPath: "$['invalid.metric.values']",
err: errors.New("unexpected end of file"),
},
} { } {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
server := makeTestHTTPServer(t, tc.input...) server := makeTestHTTPServer(t, tc.jsonResponse)
defer server.Close() defer server.Close()
path, err := jsonpath.Compile("$.value") getter, err := NewJSONPathMetricsGetter(DefaultMetricsHTTPClient(), tc.aggregator, tc.jsonPath)
require.NoError(t, err) require.NoError(t, err)
getter := NewJSONPathMetricsGetter(DefaultMetricsHTTPClient(), tc.aggregator, path)
url, err := url.Parse(fmt.Sprintf("%s/metrics", server.URL)) url, err := url.Parse(fmt.Sprintf("%s/metrics", server.URL))
require.NoError(t, err) require.NoError(t, err)
metric, err := getter.GetMetric(*url) metric, err := getter.GetMetric(*url)
if tc.err != nil {
require.Error(t, err)
require.Equal(t, tc.err.Error(), err.Error())
return
}
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tc.output, metric) require.Equal(t, tc.result, metric)
}) })
} }
} }

View File

@ -6,7 +6,6 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/oliveagle/jsonpath"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
@ -33,18 +32,13 @@ func (g PodMetricsJSONPathGetter) GetMetric(pod *v1.Pod) (float64, error) {
func NewPodMetricsJSONPathGetter(config map[string]string) (*PodMetricsJSONPathGetter, error) { func NewPodMetricsJSONPathGetter(config map[string]string) (*PodMetricsJSONPathGetter, error) {
getter := PodMetricsJSONPathGetter{} getter := PodMetricsJSONPathGetter{}
var ( var (
jsonPath *jsonpath.Compiled jsonPath string
aggregator AggregatorFunc aggregator AggregatorFunc
err error err error
) )
if v, ok := config["json-key"]; ok { if v, ok := config["json-key"]; ok {
path, err := jsonpath.Compile(v) jsonPath = v
if err != nil {
return nil, fmt.Errorf("failed to parse json path definition: %v", err)
}
jsonPath = path
} }
if v, ok := config["scheme"]; ok { if v, ok := config["scheme"]; ok {
@ -99,7 +93,11 @@ func NewPodMetricsJSONPathGetter(config map[string]string) (*PodMetricsJSONPathG
connectTimeout = d connectTimeout = d
} }
getter.metricGetter = NewJSONPathMetricsGetter(CustomMetricsHTTPClient(requestTimeout, connectTimeout), aggregator, jsonPath) jsonPathGetter, err := NewJSONPathMetricsGetter(CustomMetricsHTTPClient(requestTimeout, connectTimeout), aggregator, jsonPath)
if err != nil {
return nil, err
}
getter.metricGetter = jsonPathGetter
return &getter, nil return &getter, nil
} }

View File

@ -5,7 +5,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/oliveagle/jsonpath"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -23,12 +22,11 @@ func TestNewPodJSONPathMetricsGetter(t *testing.T) {
"path": "/metrics", "path": "/metrics",
"port": "9090", "port": "9090",
} }
jpath1, _ := jsonpath.Compile(configNoAggregator["json-key"])
getterNoAggregator, err1 := NewPodMetricsJSONPathGetter(configNoAggregator) getterNoAggregator, err1 := NewPodMetricsJSONPathGetter(configNoAggregator)
require.NoError(t, err1) require.NoError(t, err1)
compareMetricsGetter(t, &PodMetricsJSONPathGetter{ compareMetricsGetter(t, &PodMetricsJSONPathGetter{
metricGetter: &JSONPathMetricsGetter{jsonPath: jpath1}, metricGetter: &JSONPathMetricsGetter{jsonPath: configNoAggregator["json-key"]},
scheme: "http", scheme: "http",
path: "/metrics", path: "/metrics",
port: 9090, port: 9090,
@ -41,12 +39,11 @@ func TestNewPodJSONPathMetricsGetter(t *testing.T) {
"port": "9090", "port": "9090",
"aggregator": "avg", "aggregator": "avg",
} }
jpath2, _ := jsonpath.Compile(configAggregator["json-key"])
getterAggregator, err2 := NewPodMetricsJSONPathGetter(configAggregator) getterAggregator, err2 := NewPodMetricsJSONPathGetter(configAggregator)
require.NoError(t, err2) require.NoError(t, err2)
compareMetricsGetter(t, &PodMetricsJSONPathGetter{ compareMetricsGetter(t, &PodMetricsJSONPathGetter{
metricGetter: &JSONPathMetricsGetter{jsonPath: jpath2, aggregator: Average}, metricGetter: &JSONPathMetricsGetter{jsonPath: configAggregator["json-key"], aggregator: Average},
scheme: "http", scheme: "http",
path: "/metrics", path: "/metrics",
port: 9090, port: 9090,
@ -79,12 +76,11 @@ func TestNewPodJSONPathMetricsGetter(t *testing.T) {
"port": "9090", "port": "9090",
"raw-query": "foo=bar&baz=bop", "raw-query": "foo=bar&baz=bop",
} }
jpath5, _ := jsonpath.Compile(configWithRawQuery["json-key"])
getterWithRawQuery, err5 := NewPodMetricsJSONPathGetter(configWithRawQuery) getterWithRawQuery, err5 := NewPodMetricsJSONPathGetter(configWithRawQuery)
require.NoError(t, err5) require.NoError(t, err5)
compareMetricsGetter(t, &PodMetricsJSONPathGetter{ compareMetricsGetter(t, &PodMetricsJSONPathGetter{
metricGetter: &JSONPathMetricsGetter{jsonPath: jpath5}, metricGetter: &JSONPathMetricsGetter{jsonPath: configWithRawQuery["json-key"]},
scheme: "http", scheme: "http",
path: "/metrics", path: "/metrics",
port: 9090, port: 9090,
@ -107,8 +103,6 @@ func TestBuildMetricsURL(t *testing.T) {
"port": port, "port": port,
"raw-query": rawQuery, "raw-query": rawQuery,
} }
_, err := jsonpath.Compile(configWithRawQuery["json-key"])
require.NoError(t, err)
getterWithRawQuery, err1 := NewPodMetricsJSONPathGetter(configWithRawQuery) getterWithRawQuery, err1 := NewPodMetricsJSONPathGetter(configWithRawQuery)
require.NoError(t, err1) require.NoError(t, err1)
@ -123,8 +117,6 @@ func TestBuildMetricsURL(t *testing.T) {
"path": path, "path": path,
"port": port, "port": port,
} }
_, err2 := jsonpath.Compile(configWithNoQuery["json-key"])
require.NoError(t, err2)
getterWithNoQuery, err3 := NewPodMetricsJSONPathGetter(configWithNoQuery) getterWithNoQuery, err3 := NewPodMetricsJSONPathGetter(configWithNoQuery)
require.NoError(t, err3) require.NoError(t, err3)
@ -173,7 +165,7 @@ func TestCustomTimeouts(t *testing.T) {
"port": port, "port": port,
"connect-timeout": "512ms", "connect-timeout": "512ms",
} }
customRequestGetter, err3 := NewPodMetricsJSONPathGetter(configWithConnectTimeout) _, err3 := NewPodMetricsJSONPathGetter(configWithConnectTimeout)
require.NoError(t, err3) require.NoError(t, err3)
configWithInvalidTimeout := map[string]string{ configWithInvalidTimeout := map[string]string{

View File

@ -1,6 +1,7 @@
package collector package collector
import ( import (
"context"
"fmt" "fmt"
"net/http" "net/http"
"time" "time"
@ -8,9 +9,9 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/zalando-incubator/kube-metrics-adapter/pkg/collector/httpmetrics" "github.com/zalando-incubator/kube-metrics-adapter/pkg/collector/httpmetrics"
autoscalingv2 "k8s.io/api/autoscaling/v2beta2" autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/metrics/pkg/apis/custom_metrics" "k8s.io/metrics/pkg/apis/custom_metrics"
@ -81,7 +82,7 @@ func (c *PodCollector) GetMetrics() ([]CollectedMetric, error) {
LabelSelector: labels.Set(c.podLabelSelector.MatchLabels).String(), LabelSelector: labels.Set(c.podLabelSelector.MatchLabels).String(),
} }
pods, err := c.client.CoreV1().Pods(c.namespace).List(opts) pods, err := c.client.CoreV1().Pods(c.namespace).List(context.TODO(), opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -135,13 +136,13 @@ func (c *PodCollector) getPodMetric(pod corev1.Pod, ch chan CollectedMetric, err
func getPodLabelSelector(client kubernetes.Interface, hpa *autoscalingv2.HorizontalPodAutoscaler) (*metav1.LabelSelector, error) { func getPodLabelSelector(client kubernetes.Interface, hpa *autoscalingv2.HorizontalPodAutoscaler) (*metav1.LabelSelector, error) {
switch hpa.Spec.ScaleTargetRef.Kind { switch hpa.Spec.ScaleTargetRef.Kind {
case "Deployment": case "Deployment":
deployment, err := client.AppsV1().Deployments(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{}) deployment, err := client.AppsV1().Deployments(hpa.Namespace).Get(context.TODO(), hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return deployment.Spec.Selector, nil return deployment.Spec.Selector, nil
case "StatefulSet": case "StatefulSet":
sts, err := client.AppsV1().StatefulSets(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{}) sts, err := client.AppsV1().StatefulSets(hpa.Namespace).Get(context.TODO(), hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,14 +1,15 @@
package collector package collector
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"sync"
"testing" "testing"
"time" "time"
"sync"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
@ -115,7 +116,7 @@ func makeTestPods(t *testing.T, testServer string, metricName string, port strin
PodIP: testServer, PodIP: testServer,
}, },
} }
_, err := client.CoreV1().Pods(testNamespace).Create(testPod) _, err := client.CoreV1().Pods(testNamespace).Create(context.TODO(), testPod, v1.CreateOptions{})
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -129,7 +130,7 @@ func makeTestDeployment(t *testing.T, client kubernetes.Interface) *appsv1.Deplo
}, },
}, },
} }
_, err := client.AppsV1().Deployments(testNamespace).Create(&deployment) _, err := client.AppsV1().Deployments(testNamespace).Create(context.TODO(), &deployment, v1.CreateOptions{})
require.NoError(t, err) require.NoError(t, err)
return &deployment return &deployment
@ -149,7 +150,7 @@ func makeTestHPA(t *testing.T, client kubernetes.Interface) *autoscalingv2.Horiz
}, },
}, },
} }
_, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers("test-namespace").Create(hpa) _, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers("test-namespace").Create(context.TODO(), hpa, v1.CreateOptions{})
require.NoError(t, err) require.NoError(t, err)
return hpa return hpa
} }

View File

@ -1,6 +1,7 @@
package collector package collector
import ( import (
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -87,16 +88,16 @@ func NewSkipperCollector(client kubernetes.Interface, plugin CollectorPlugin, hp
}, nil }, nil
} }
func getAnnotationWeight(backendWeights string, backend string) float64 { func getAnnotationWeight(backendWeights string, backend string) (float64, error) {
var weightsMap map[string]int var weightsMap map[string]float64
err := json.Unmarshal([]byte(backendWeights), &weightsMap) err := json.Unmarshal([]byte(backendWeights), &weightsMap)
if err != nil { if err != nil {
return 0 return 0, err
} }
if weight, ok := weightsMap[backend]; ok { if weight, ok := weightsMap[backend]; ok {
return float64(weight) / 100 return float64(weight) / 100, nil
} }
return 0 return 0, nil
} }
func getWeights(ingressAnnotations map[string]string, backendAnnotations []string, backend string) (float64, error) { func getWeights(ingressAnnotations map[string]string, backendAnnotations []string, backend string) (float64, error) {
@ -106,7 +107,11 @@ func getWeights(ingressAnnotations map[string]string, backendAnnotations []strin
for _, anno := range backendAnnotations { for _, anno := range backendAnnotations {
if weightsMap, ok := ingressAnnotations[anno]; ok { if weightsMap, ok := ingressAnnotations[anno]; ok {
annotationsPresent = true annotationsPresent = true
maxWeight = math.Max(maxWeight, getAnnotationWeight(weightsMap, backend)) weight, err := getAnnotationWeight(weightsMap, backend)
if err != nil {
return 0.0, err
}
maxWeight = math.Max(maxWeight, weight)
} }
} }
@ -125,7 +130,7 @@ func getWeights(ingressAnnotations map[string]string, backendAnnotations []strin
// getCollector returns a collector for getting the metrics. // getCollector returns a collector for getting the metrics.
func (c *SkipperCollector) getCollector() (Collector, error) { func (c *SkipperCollector) getCollector() (Collector, error) {
ingress, err := c.client.NetworkingV1beta1().Ingresses(c.objectReference.Namespace).Get(c.objectReference.Name, metav1.GetOptions{}) ingress, err := c.client.NetworkingV1beta1().Ingresses(c.objectReference.Namespace).Get(context.TODO(), c.objectReference.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -207,13 +212,13 @@ func targetRefReplicas(client kubernetes.Interface, hpa *autoscalingv2.Horizonta
var replicas int32 var replicas int32
switch hpa.Spec.ScaleTargetRef.Kind { switch hpa.Spec.ScaleTargetRef.Kind {
case "Deployment": case "Deployment":
deployment, err := client.AppsV1().Deployments(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{}) deployment, err := client.AppsV1().Deployments(hpa.Namespace).Get(context.TODO(), hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return 0, err return 0, err
} }
replicas = deployment.Status.Replicas replicas = deployment.Status.Replicas
case "StatefulSet": case "StatefulSet":
sts, err := client.AppsV1().StatefulSets(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{}) sts, err := client.AppsV1().StatefulSets(hpa.Namespace).Get(context.TODO(), hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@ -1,6 +1,7 @@
package collector package collector
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"testing" "testing"
@ -32,7 +33,7 @@ func TestTargetRefReplicasDeployments(t *testing.T) {
// Create an HPA with the deployment as ref // Create an HPA with the deployment as ref
hpa, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers(deployment.Namespace). hpa, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers(deployment.Namespace).
Create(newHPA(defaultNamespace, name, "Deployment")) Create(context.TODO(), newHPA(defaultNamespace, name, "Deployment"), metav1.CreateOptions{})
require.NoError(t, err) require.NoError(t, err)
replicas, err := targetRefReplicas(client, hpa) replicas, err := targetRefReplicas(client, hpa)
@ -49,7 +50,7 @@ func TestTargetRefReplicasStatefulSets(t *testing.T) {
// Create an HPA with the statefulSet as ref // Create an HPA with the statefulSet as ref
hpa, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers(statefulSet.Namespace). hpa, err := client.AutoscalingV2beta2().HorizontalPodAutoscalers(statefulSet.Namespace).
Create(newHPA(defaultNamespace, name, "StatefulSet")) Create(context.TODO(), newHPA(defaultNamespace, name, "StatefulSet"), metav1.CreateOptions{})
require.NoError(t, err) require.NoError(t, err)
replicas, err := targetRefReplicas(client, hpa) replicas, err := targetRefReplicas(client, hpa)
@ -73,7 +74,7 @@ func newHPA(namesapce string, refName string, refKind string) *autoscalingv2.Hor
} }
func newDeployment(client *fake.Clientset, namespace string, name string, replicas, readyReplicas int32) (*appsv1.Deployment, error) { func newDeployment(client *fake.Clientset, namespace string, name string, replicas, readyReplicas int32) (*appsv1.Deployment, error) {
return client.AppsV1().Deployments(namespace).Create(&appsv1.Deployment{ return client.AppsV1().Deployments(namespace).Create(context.TODO(), &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
@ -83,11 +84,11 @@ func newDeployment(client *fake.Clientset, namespace string, name string, replic
ReadyReplicas: replicas, ReadyReplicas: replicas,
Replicas: readyReplicas, Replicas: readyReplicas,
}, },
}) }, metav1.CreateOptions{})
} }
func newStatefulSet(client *fake.Clientset, namespace string, name string) (*appsv1.StatefulSet, error) { func newStatefulSet(client *fake.Clientset, namespace string, name string) (*appsv1.StatefulSet, error) {
return client.AppsV1().StatefulSets(namespace).Create(&appsv1.StatefulSet{ return client.AppsV1().StatefulSets(namespace).Create(context.TODO(), &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
@ -96,7 +97,7 @@ func newStatefulSet(client *fake.Clientset, namespace string, name string) (*app
ReadyReplicas: 1, ReadyReplicas: 1,
Replicas: 2, Replicas: 2,
}, },
}) }, metav1.CreateOptions{})
} }
func TestSkipperCollector(t *testing.T) { func TestSkipperCollector(t *testing.T) {
@ -111,7 +112,7 @@ func TestSkipperCollector(t *testing.T) {
expectError bool expectError bool
fakedAverage bool fakedAverage bool
namespace string namespace string
backendWeights map[string]map[string]int backendWeights map[string]map[string]float64
replicas int32 replicas int32
readyReplicas int32 readyReplicas int32
backendAnnotations []string backendAnnotations []string
@ -137,7 +138,7 @@ func TestSkipperCollector(t *testing.T) {
collectedMetric: 1000, collectedMetric: 1000,
namespace: "default", namespace: "default",
backend: "backend1", backend: "backend1",
backendWeights: map[string]map[string]int{testBackendWeightsAnnotation: {"backend2": 60, "backend1": 40}}, backendWeights: map[string]map[string]float64{testBackendWeightsAnnotation: {"backend2": 60.0, "backend1": 40}},
replicas: 1, replicas: 1,
readyReplicas: 1, readyReplicas: 1,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -151,7 +152,7 @@ func TestSkipperCollector(t *testing.T) {
collectedMetric: 1000, collectedMetric: 1000,
namespace: "default", namespace: "default",
backend: "backend1", backend: "backend1",
backendWeights: map[string]map[string]int{testBackendWeightsAnnotation: {"backend2": 60, "backend1": 40}}, backendWeights: map[string]map[string]float64{testBackendWeightsAnnotation: {"backend2": 60, "backend1": 40}},
replicas: 1, replicas: 1,
readyReplicas: 1, readyReplicas: 1,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -166,7 +167,7 @@ func TestSkipperCollector(t *testing.T) {
fakedAverage: true, fakedAverage: true,
namespace: "default", namespace: "default",
backend: "backend1", backend: "backend1",
backendWeights: map[string]map[string]int{testBackendWeightsAnnotation: {"backend2": 50, "backend1": 50}}, backendWeights: map[string]map[string]float64{testBackendWeightsAnnotation: {"backend2": 50, "backend1": 50}},
replicas: 5, replicas: 5,
readyReplicas: 5, readyReplicas: 5,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -180,7 +181,7 @@ func TestSkipperCollector(t *testing.T) {
collectedMetric: 1500, collectedMetric: 1500,
namespace: "default", namespace: "default",
backend: "backend1", backend: "backend1",
backendWeights: map[string]map[string]int{testBackendWeightsAnnotation: {"backend2": 50, "backend1": 50}}, backendWeights: map[string]map[string]float64{testBackendWeightsAnnotation: {"backend2": 50, "backend1": 50}},
replicas: 5, // this is not taken into account replicas: 5, // this is not taken into account
readyReplicas: 5, readyReplicas: 5,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -194,7 +195,7 @@ func TestSkipperCollector(t *testing.T) {
collectedMetric: 0, collectedMetric: 0,
namespace: "default", namespace: "default",
backend: "backend1", backend: "backend1",
backendWeights: map[string]map[string]int{testBackendWeightsAnnotation: {"backend2": 100, "backend1": 0}}, backendWeights: map[string]map[string]float64{testBackendWeightsAnnotation: {"backend2": 100, "backend1": 0}},
replicas: 5, replicas: 5,
readyReplicas: 5, readyReplicas: 5,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -209,7 +210,7 @@ func TestSkipperCollector(t *testing.T) {
fakedAverage: true, fakedAverage: true,
namespace: "default", namespace: "default",
backend: "backend1", backend: "backend1",
backendWeights: map[string]map[string]int{ backendWeights: map[string]map[string]float64{
testBackendWeightsAnnotation: {"backend2": 20, "backend1": 80}, testBackendWeightsAnnotation: {"backend2": 20, "backend1": 80},
testStacksetWeightsAnnotation: {"backend2": 0, "backend1": 100}, testStacksetWeightsAnnotation: {"backend2": 0, "backend1": 100},
}, },
@ -226,7 +227,7 @@ func TestSkipperCollector(t *testing.T) {
collectedMetric: 1500, collectedMetric: 1500,
namespace: "default", namespace: "default",
backend: "backend1", backend: "backend1",
backendWeights: map[string]map[string]int{ backendWeights: map[string]map[string]float64{
testBackendWeightsAnnotation: {"backend2": 20, "backend1": 80}, testBackendWeightsAnnotation: {"backend2": 20, "backend1": 80},
testStacksetWeightsAnnotation: {"backend2": 0, "backend1": 100}, testStacksetWeightsAnnotation: {"backend2": 0, "backend1": 100},
}, },
@ -243,7 +244,7 @@ func TestSkipperCollector(t *testing.T) {
collectedMetric: 0, collectedMetric: 0,
namespace: "default", namespace: "default",
backend: "backend3", backend: "backend3",
backendWeights: map[string]map[string]int{testBackendWeightsAnnotation: {"backend2": 100, "backend1": 0}}, backendWeights: map[string]map[string]float64{testBackendWeightsAnnotation: {"backend2": 100, "backend1": 0}},
replicas: 1, replicas: 1,
readyReplicas: 1, readyReplicas: 1,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -257,7 +258,7 @@ func TestSkipperCollector(t *testing.T) {
collectedMetric: 1500, collectedMetric: 1500,
namespace: "default", namespace: "default",
backend: "backend3", backend: "backend3",
backendWeights: map[string]map[string]int{}, backendWeights: map[string]map[string]float64{},
replicas: 1, replicas: 1,
readyReplicas: 1, readyReplicas: 1,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -271,7 +272,7 @@ func TestSkipperCollector(t *testing.T) {
expectError: true, expectError: true,
namespace: "default", namespace: "default",
backend: "", backend: "",
backendWeights: map[string]map[string]int{testBackendWeightsAnnotation: {"backend2": 100, "backend1": 0}}, backendWeights: map[string]map[string]float64{testBackendWeightsAnnotation: {"backend2": 100, "backend1": 0}},
replicas: 1, replicas: 1,
readyReplicas: 1, readyReplicas: 1,
backendAnnotations: []string{testBackendWeightsAnnotation}, backendAnnotations: []string{testBackendWeightsAnnotation},
@ -300,7 +301,7 @@ func TestSkipperCollector(t *testing.T) {
fakedAverage: true, fakedAverage: true,
namespace: "default", namespace: "default",
backend: "backend2", backend: "backend2",
backendWeights: map[string]map[string]int{ backendWeights: map[string]map[string]float64{
testBackendWeightsAnnotation: {"backend2": 20, "backend1": 80}, testBackendWeightsAnnotation: {"backend2": 20, "backend1": 80},
testStacksetWeightsAnnotation: {"backend1": 100}, testStacksetWeightsAnnotation: {"backend1": 100},
}, },
@ -313,12 +314,12 @@ func TestSkipperCollector(t *testing.T) {
metric: 1500, metric: 1500,
ingressName: "dummy-ingress", ingressName: "dummy-ingress",
hostnames: []string{"example.org"}, hostnames: []string{"example.org"},
expectedQuery: `scalar(sum(rate(skipper_serve_host_duration_seconds_count{host=~"example_org"}[1m])) * 0.2000)`, expectedQuery: `scalar(sum(rate(skipper_serve_host_duration_seconds_count{host=~"example_org"}[1m])) * 0.2050)`,
collectedMetric: 1500, collectedMetric: 1500,
namespace: "default", namespace: "default",
backend: "backend2", backend: "backend2",
backendWeights: map[string]map[string]int{ backendWeights: map[string]map[string]float64{
testBackendWeightsAnnotation: {"backend2": 20, "backend1": 80}, testBackendWeightsAnnotation: {"backend2": 20.5, "backend1": 79.5},
testStacksetWeightsAnnotation: {"backend1": 100}, testStacksetWeightsAnnotation: {"backend1": 100},
}, },
replicas: 5, replicas: 5,
@ -351,7 +352,7 @@ func TestSkipperCollector(t *testing.T) {
} }
} }
func makeIngress(client kubernetes.Interface, namespace, ingressName, backend string, hostnames []string, backendWeights map[string]map[string]int) error { func makeIngress(client kubernetes.Interface, namespace, ingressName, backend string, hostnames []string, backendWeights map[string]map[string]float64) error {
annotations := make(map[string]string) annotations := make(map[string]string)
for anno, weights := range backendWeights { for anno, weights := range backendWeights {
sWeights, err := json.Marshal(weights) sWeights, err := json.Marshal(weights)
@ -382,7 +383,7 @@ func makeIngress(client kubernetes.Interface, namespace, ingressName, backend st
Host: hostname, Host: hostname,
}) })
} }
_, err := client.NetworkingV1beta1().Ingresses(namespace).Create(ingress) _, err := client.NetworkingV1beta1().Ingresses(namespace).Create(context.TODO(), ingress, metav1.CreateOptions{})
return err return err
} }

View File

@ -119,7 +119,7 @@ func (p *HPAProvider) Run(ctx context.Context) {
func (p *HPAProvider) updateHPAs() error { func (p *HPAProvider) updateHPAs() error {
p.logger.Info("Looking for HPAs") p.logger.Info("Looking for HPAs")
hpas, err := p.client.AutoscalingV2beta2().HorizontalPodAutoscalers(metav1.NamespaceAll).List(metav1.ListOptions{}) hpas, err := p.client.AutoscalingV2beta2().HorizontalPodAutoscalers(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }

View File

@ -70,7 +70,7 @@ func TestUpdateHPAs(t *testing.T) {
fakeClient := fake.NewSimpleClientset() fakeClient := fake.NewSimpleClientset()
var err error var err error
hpa, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Create(hpa) hpa, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Create(context.TODO(), hpa, metav1.CreateOptions{})
require.NoError(t, err) require.NoError(t, err)
collectorFactory := collector.NewCollectorFactory() collectorFactory := collector.NewCollectorFactory()
@ -86,7 +86,7 @@ func TestUpdateHPAs(t *testing.T) {
// update HPA // update HPA
hpa.Annotations["metric-config.pods.requests-per-second.json-path/port"] = "8080" hpa.Annotations["metric-config.pods.requests-per-second.json-path/port"] = "8080"
_, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Update(hpa) _, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Update(context.TODO(), hpa, metav1.UpdateOptions{})
require.NoError(t, err) require.NoError(t, err)
err = provider.updateHPAs() err = provider.updateHPAs()
@ -134,7 +134,7 @@ func TestUpdateHPAsDisregardingIncompatibleHPA(t *testing.T) {
fakeClient := fake.NewSimpleClientset() fakeClient := fake.NewSimpleClientset()
var err error var err error
_, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Create(hpa) _, err = fakeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Create(context.TODO(), hpa, metav1.CreateOptions{})
require.NoError(t, err) require.NoError(t, err)
collectorFactory := collector.NewCollectorFactory() collectorFactory := collector.NewCollectorFactory()