diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index eb73108c7234e473fafe1bc2de36940347f03670..36b6a14bf943b0d853fe487a599375c80af296ae 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -123,7 +123,7 @@ func TestDroppedMetrics(t *testing.T) { if err != nil { log.Fatal(err) } - for _, k := range md.Data { + for _, k := range md { // check if the metric' help text contains Deprecated if strings.Contains(k.Help, "Deprecated") { // query prometheus for the Deprecated metric @@ -138,3 +138,27 @@ func TestDroppedMetrics(t *testing.T) { } } + +func TestTargetsScheme(t *testing.T) { + // query targets for all endpoints + tgs, err := promClient.targets() + if err != nil { + log.Fatal(err) + } + + // exclude jobs from checking for http endpoints + // TODO(paulfantom): This should be reduced as we secure connections for those components + exclude := map[string]bool{ + "alertmanager-main": true, + "prometheus-k8s": true, + "kube-dns": true, + "grafana": true, + } + + for _, k := range tgs.Active { + job := k.Labels["job"] + if k.DiscoveredLabels["__scheme__"] == "http" && !exclude[string(job)] { + log.Fatalf("target exposing metrics over HTTP instead of HTTPS: %+v", k) + } + } +} diff --git a/tests/e2e/prometheus_client.go b/tests/e2e/prometheus_client.go index 89e25c0a3faa7af1a6638b22976c441473ef8c51..a932c0b580cf1d99d8231eab5f55b3dfdcd07c0d 100644 --- a/tests/e2e/prometheus_client.go +++ b/tests/e2e/prometheus_client.go @@ -22,6 +22,7 @@ import ( "k8s.io/client-go/kubernetes" "github.com/Jeffail/gabs" + promv1 "github.com/prometheus/client_golang/api/prometheus/v1" ) type prometheusClient struct { @@ -32,6 +33,42 @@ func newPrometheusClient(kubeClient kubernetes.Interface) *prometheusClient { return &prometheusClient{kubeClient} } +// Response hold API response in a form similar to apiResponse struct from prometheus/client_golang +// https://github.com/prometheus/client_golang/blob/master/api/prometheus/v1/api.go +type Response struct { + Status string `json:"status"` + Data json.RawMessage `json:"data"` +} + +// apiRequest makes a request against specified Prometheus API endpoint +func (c *prometheusClient) apiRequest(endpoint string, selector string, query string) (Response, error) { + req := c.kubeClient.CoreV1().RESTClient().Get(). + Namespace("monitoring"). + Resource("pods"). + SubResource("proxy"). + Name("prometheus-k8s-0:9090"). + Suffix(endpoint).Param(selector, query) + + var data Response + b, err := req.DoRaw() + if err != nil { + return data, err + } + + r := bytes.NewReader(b) + decoder := json.NewDecoder(r) + err = decoder.Decode(&data) + if err != nil { + return data, err + } + + if data.Status != "success" { + return data, fmt.Errorf("status of returned response was not successful; status: %s", data.Status) + } + + return data, err +} + // Query makes a request against the Prometheus /api/v1/query endpoint. func (c *prometheusClient) query(query string) (int, error) { req := c.kubeClient.CoreV1().RESTClient().Get(). @@ -55,40 +92,36 @@ func (c *prometheusClient) query(query string) (int, error) { return n, err } -type Metadata struct { - Status string `json:"status,omitempty"` - Data []Data `json:"data,omitempty"` -} - -type Data struct { - Metric string `json:"metric,omitempty"` - Help string `json:"help,omitempty"` -} - // metadata makes a request against the Prometheus /api/v1/targets/metadata endpoint. // It returns all the metrics and its metadata. -func (c *prometheusClient) metadata(query string) (Metadata, error) { - req := c.kubeClient.CoreV1().RESTClient().Get(). - Namespace("monitoring"). - Resource("pods"). - SubResource("proxy"). - Name("prometheus-k8s-0:9090"). - Suffix("/api/v1/targets/metadata").Param("match_target", query) +func (c *prometheusClient) metadata(query string) ([]promv1.MetricMetadata, error) { + var metadata []promv1.MetricMetadata + rsp, err := c.apiRequest("/api/v1/targets/metadata", "match_target", query) - var data Metadata - b, err := req.DoRaw() + r := bytes.NewReader(rsp.Data) + decoder := json.NewDecoder(r) + err = decoder.Decode(&metadata) if err != nil { - return data, err + return metadata, err } + return metadata, err +} - r := bytes.NewReader(b) - decoder := json.NewDecoder(r) - err = decoder.Decode(&data) +// targets makes a request against the Prometheus /api/v1/targets endpoint. +// It returns all targets registered in prometheus. +func (c *prometheusClient) targets() (promv1.TargetsResult, error) { + var targets promv1.TargetsResult + rsp, err := c.apiRequest("/api/v1/targets", "state", "any") if err != nil { - return data, err + return targets, err } - if data.Status != "success" { - return data, fmt.Errorf("status of returned response was not successful; status: %s", data.Status) + + r := bytes.NewReader(rsp.Data) + decoder := json.NewDecoder(r) + err = decoder.Decode(&targets) + if err != nil { + return targets, err } - return data, err + + return targets, err }