...
1 package srv
2
3 import (
4 "bytes"
5 "fmt"
6 "net/http"
7 "regexp"
8
9 "github.com/julienschmidt/httprouter"
10 "github.com/linkerd/linkerd2/pkg/k8s"
11 profiles "github.com/linkerd/linkerd2/pkg/profiles"
12 vizPb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
13 "github.com/patrickmn/go-cache"
14 log "github.com/sirupsen/logrus"
15 )
16
17 var proxyPathRegexp = regexp.MustCompile("/api/v1/namespaces/.*/proxy/")
18
19 type (
20 renderTemplate func(http.ResponseWriter, string, string, interface{}) error
21
22 handler struct {
23 render renderTemplate
24 apiClient vizPb.ApiClient
25 k8sAPI *k8s.KubernetesAPI
26 uuid string
27 version string
28 controllerNamespace string
29 clusterDomain string
30 grafana string
31 grafanaExternalURL string
32 grafanaPrefix string
33 jaeger string
34 grafanaProxy *reverseProxy
35 jaegerProxy *reverseProxy
36 hc healthChecker
37 statCache *cache.Cache
38 }
39 )
40
41 func (h *handler) handleIndex(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
42
43 pathPfx := proxyPathRegexp.FindString(req.URL.Path)
44 if pathPfx == "" {
45 pathPfx = "/"
46 }
47
48 params := appParams{
49 UUID: h.uuid,
50 ReleaseVersion: h.version,
51 ControllerNamespace: h.controllerNamespace,
52 PathPrefix: pathPfx,
53 Grafana: h.grafana,
54 GrafanaExternalURL: h.grafanaExternalURL,
55 GrafanaPrefix: h.grafanaPrefix,
56 Jaeger: h.jaeger,
57 }
58
59 err := h.render(w, "app.tmpl.html", "base", params)
60 if err != nil {
61 log.Error(err)
62 }
63 }
64
65 func (h *handler) handleProfileDownload(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
66 service := req.FormValue("service")
67 namespace := req.FormValue("namespace")
68
69 if service == "" || namespace == "" {
70 err := fmt.Errorf("Service and namespace must be provided to create a new profile")
71 log.Error(err)
72 http.Error(w, err.Error(), http.StatusBadRequest)
73 return
74 }
75
76 profileYaml := &bytes.Buffer{}
77 err := profiles.RenderProfileTemplate(namespace, service, h.clusterDomain, profileYaml, "yaml")
78
79 if err != nil {
80 log.Error(err)
81 http.Error(w, err.Error(), http.StatusInternalServerError)
82 return
83 }
84
85 dispositionHeaderVal := fmt.Sprintf("attachment; filename=%s-profile.yml", service)
86
87 w.Header().Set("Content-Type", "text/yaml")
88 w.Header().Set("Content-Disposition", dispositionHeaderVal)
89
90 w.Write(profileYaml.Bytes())
91 }
92
93 func (h *handler) handleGrafana(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
94 h.grafanaProxy.ServeHTTP(w, req)
95 }
96
97 func (h *handler) handleJaeger(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
98 h.jaegerProxy.ServeHTTP(w, req)
99 }
100
View as plain text