forked from yusheng-guo/kube-metrics-adapter
This fixes an issue with the type switch that was never able to fall (#88)
into cases of []<number>, being <number> a number type such as int, float32, float64. This is because Go can't type cast slices of interface{} out right because it's impossible to know the true types of the slice members beforehand. Signed-off-by: Tomás Pinho <me@tomaspinho.com>
This commit is contained in:
@@ -89,17 +89,38 @@ func (g *JSONPathMetricsGetter) GetMetric(pod *corev1.Pod) (float64, error) {
|
||||
return float64(res), nil
|
||||
case float64:
|
||||
return res, nil
|
||||
case []int:
|
||||
return reduce(intsToFloat64s(res), g.aggregator)
|
||||
case []float32:
|
||||
return reduce(float32sToFloat64s(res), g.aggregator)
|
||||
case []float64:
|
||||
return reduce(res, g.aggregator)
|
||||
case []interface{}:
|
||||
s, err := castSlice(res)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return reduce(s, g.aggregator)
|
||||
default:
|
||||
return 0, fmt.Errorf("unsupported type %T", res)
|
||||
}
|
||||
}
|
||||
|
||||
// castSlice takes a slice of interface and returns a slice of float64 if all
|
||||
// values in slice were castable, else returns an error
|
||||
func castSlice(in []interface{}) ([]float64, error) {
|
||||
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 out, nil
|
||||
}
|
||||
|
||||
// getPodMetrics returns the content of the pods metrics endpoint.
|
||||
func getPodMetrics(pod *corev1.Pod, scheme, path string, port int) ([]byte, error) {
|
||||
if pod.Status.PodIP == "" {
|
||||
@@ -144,24 +165,6 @@ func getPodMetrics(pod *corev1.Pod, scheme, path string, port int) ([]byte, erro
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// intsToFloat64s will convert a slice of int to a slice of float64
|
||||
func intsToFloat64s(in []int) (out []float64) {
|
||||
out = []float64{}
|
||||
for _, v := range in {
|
||||
out = append(out, float64(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// float32sToFloat64s will convert a slice of float32 to a slice of float64
|
||||
func float32sToFloat64s(in []float32) (out []float64) {
|
||||
out = []float64{}
|
||||
for _, v := range in {
|
||||
out = append(out, float64(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// reduce will reduce a slice of numbers given a aggregator function's name. If it's empty or not recognized, an error is returned.
|
||||
func reduce(values []float64, aggregator string) (float64, error) {
|
||||
switch aggregator {
|
||||
|
@@ -65,24 +65,22 @@ func TestNewJSONPathMetricsGetter(t *testing.T) {
|
||||
require.Error(t, err4)
|
||||
}
|
||||
|
||||
func TestIntsToFloat64s(t *testing.T) {
|
||||
noInts := []int{}
|
||||
noFloat64s := intsToFloat64s(noInts)
|
||||
require.Equal(t, []float64{}, noFloat64s)
|
||||
func TestCastSlice(t *testing.T) {
|
||||
res1, err1 := castSlice([]interface{}{1, 2, 3})
|
||||
require.NoError(t, err1)
|
||||
require.Equal(t, []float64{1.0, 2.0, 3.0}, res1)
|
||||
|
||||
someInts := []int{1, 2, 3}
|
||||
someFloat64s := intsToFloat64s(someInts)
|
||||
require.Equal(t, []float64{1.0, 2.0, 3.0}, someFloat64s)
|
||||
}
|
||||
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)
|
||||
|
||||
func TestFloat32sToFloat64s(t *testing.T) {
|
||||
noFloat32s := []float32{}
|
||||
noFloat64s := float32sToFloat64s(noFloat32s)
|
||||
require.Equal(t, []float64{}, noFloat64s)
|
||||
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)
|
||||
|
||||
someFloat32s := []float32{1.0, 2.0, 3.0}
|
||||
someFloat64s := float32sToFloat64s(someFloat32s)
|
||||
require.Equal(t, []float64{1.0, 2.0, 3.0}, someFloat64s)
|
||||
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)
|
||||
}
|
||||
|
||||
func TestReduce(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user