Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,21 @@ type Server struct {
}

type Prometheus struct {
URL string `yaml:"url" json:"url"`
DevURL string `yaml:"devUrl,omitempty" json:"devUrl,omitempty"`
Timeout Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
TokenPath string `yaml:"tokenPath,omitempty" json:"tokenPath,omitempty"`
SkipTLS bool `yaml:"skipTls,omitempty" json:"skipTls,omitempty"`
CAPath string `yaml:"caPath,omitempty" json:"caPath,omitempty"`
ForwardUserToken bool `yaml:"forwardUserToken,omitempty" json:"forwardUserToken,omitempty"`
Metrics []MetricInfo `yaml:"metrics,omitempty" json:"metrics,omitempty"`
URL string `yaml:"url" json:"url"`
DevURL string `yaml:"devUrl,omitempty" json:"devUrl,omitempty"`
Timeout Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
TokenPath string `yaml:"tokenPath,omitempty" json:"tokenPath,omitempty"`
SkipTLS bool `yaml:"skipTls,omitempty" json:"skipTls,omitempty"`
CAPath string `yaml:"caPath,omitempty" json:"caPath,omitempty"`
ForwardUserToken bool `yaml:"forwardUserToken,omitempty" json:"forwardUserToken,omitempty"`
Metrics []MetricInfo `yaml:"metrics,omitempty" json:"metrics,omitempty"`
AlertManager AlertManagerConfig `yaml:"alertManager" json:"alertManager"`
}

type AlertManagerConfig struct {
URL string `yaml:"url" json:"url"`
SkipTLS bool `yaml:"skipTls,omitempty" json:"skipTls,omitempty"`
CAPath string `yaml:"caPath,omitempty" json:"caPath,omitempty"`
}

type FlowDirection string
Expand Down Expand Up @@ -276,7 +283,7 @@ func (c *Config) Validate() error {
}

if c.IsPromEnabled() {
log.Infof("Prometheus is enabled:\n - admin: %s\n - dev: %s\n", c.Prometheus.URL, c.Prometheus.DevURL)
log.Infof("Prometheus is enabled [admin: %s, dev: %s, alert-manager: %s]", c.Prometheus.URL, c.Prometheus.DevURL, c.Prometheus.AlertManager.URL)
// parse config urls
_, err := url.Parse(c.Prometheus.URL)
if err != nil {
Expand Down
57 changes: 57 additions & 0 deletions pkg/handler/promproxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package handler

import (
"io"
"net/http"
"net/url"
"time"

"github.com/netobserv/network-observability-console-plugin/pkg/prometheus"
)

func (h *Handlers) PromProxyRules() func(w http.ResponseWriter, r *http.Request) {
u, _ := url.JoinPath(h.Cfg.Prometheus.URL, "/api/v1/rules")
cfg := &h.Cfg.Prometheus
return simpleProxy(u, cfg.Timeout.Duration, cfg.SkipTLS, cfg.CAPath, cfg.ForwardUserToken, cfg.TokenPath)
}

func (h *Handlers) PromProxySilences() func(w http.ResponseWriter, r *http.Request) {
u, _ := url.JoinPath(h.Cfg.Prometheus.AlertManager.URL, "/api/v2/silences")
cfg := &h.Cfg.Prometheus
return simpleProxy(u, cfg.Timeout.Duration, cfg.SkipTLS, cfg.CAPath, cfg.ForwardUserToken, cfg.TokenPath)
}

func simpleProxy(toURL string, timeout time.Duration, skipTLS bool, caPath string, forwardUserToken bool, tokenPath string) func(w http.ResponseWriter, r *http.Request) {
hlog.Infof("Proxying to: %s", toURL)
backendURL, _ := url.Parse(toURL)
return func(w http.ResponseWriter, r *http.Request) {
roundTripper, err := prometheus.CreateRoundTripper(timeout, skipTLS, caPath, forwardUserToken, tokenPath, r.Header)
if err != nil {
hlog.Errorf("Proxying to %s; CreateRoundTripper error: %v", toURL, err)
writeError(w, http.StatusInternalServerError, err.Error())
return
}
backendURL.RawQuery = r.URL.RawQuery
rq := http.Request{
Method: r.Method,
URL: backendURL,
Body: r.Body,
ContentLength: r.ContentLength,
}
resp, err := roundTripper.RoundTrip(&rq)
if err != nil {
hlog.Errorf("Proxying to %s; RoundTrip error: %v", toURL, err)
writeError(w, http.StatusInternalServerError, err.Error())
return
}
w.WriteHeader(resp.StatusCode)
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
hlog.Errorf("Error reading response from proxy on %s: %v", toURL, err)
}
if _, err := w.Write(body); err != nil {
hlog.Errorf("Error proxying response from %s: %v", toURL, err)
}
}
}
13 changes: 9 additions & 4 deletions pkg/prometheus/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ func NewDevClient(cfg *config.Prometheus, requestHeader http.Header, namespace s
}

func newClient(timeout time.Duration, skipTLS bool, caPath string, forwardUserToken bool, tokenPath string, url string, requestHeader http.Header) (api.Client, error) {
roundTripper, err := CreateRoundTripper(timeout, skipTLS, caPath, forwardUserToken, tokenPath, requestHeader)
if err != nil {
return nil, err
}
return api.NewClient(api.Config{Address: url, RoundTripper: roundTripper})
}

func CreateRoundTripper(timeout time.Duration, skipTLS bool, caPath string, forwardUserToken bool, tokenPath string, requestHeader http.Header) (http.RoundTripper, error) {
maybeTLS := httpclient.NewTransport(timeout, skipTLS, caPath, "", "")

var roundTripper http.RoundTripper
Expand All @@ -57,10 +65,7 @@ func newClient(timeout time.Duration, skipTLS bool, caPath string, forwardUserTo
roundTripper = maybeTLS
}

return api.NewClient(api.Config{
Address: url,
RoundTripper: roundTripper,
})
return roundTripper, nil
}

func executeQueryRange(ctx context.Context, cl api.Client, q *Query) (pmod.Value, int, error) {
Expand Down
11 changes: 10 additions & 1 deletion pkg/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,20 @@ func setupRoutes(ctx context.Context, cfg *config.Config, authChecker auth.Check
// K8S endpoints
api.HandleFunc("/k8s/resources/udnIds", h.GetUDNIdss(ctx))

// Path prefixed with "console-" are routed via react-router (standalone console)
r.PathPrefix("/console-").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./web/dist/index.html")
})

// Frontend files
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./web/dist/")))
}

if cfg.Loki.UseMocks {
if cfg.Prometheus.AlertManager.URL != "" {
// When AlertManager URL is configured, we don't use the Console proxy; doing our own proxy instead (likely, we're in standalone mode)
api.HandleFunc("/prometheus/api/v1/rules", h.PromProxyRules())
api.HandleFunc("/alertmanager/api/v2/silences", h.PromProxySilences())
} else if cfg.Loki.UseMocks {
// Add route for alerts (otherwise, the route is provided by the Console itself)
api.HandleFunc("/prometheus/api/v1/rules", alertingmock.GetRules())
}
Expand Down
Loading