Description: Do not embed web resources in the binary.
 Upstream is interested in keeping the resources embedded, this patch is to
 comply with Debian policy.
Forwarded: not-needed
Author: Martina Ferrari <tina@debian.org>
Last-Update: 2022-09-19

---
 cli/check_config.go        |    2 +-
 cli/template_render.go     |    2 +-
 cmd/alertmanager/main.go   |    6 ++++--
 notify/email/email_test.go |    2 +-
 notify/test/test.go        |    2 +-
 template/template.go       |   30 ++++++++++++------------------
 template/template_test.go  |    2 +-
 ui/app/src/Views.elm       |    4 ++--
 ui/web.go                  |   26 ++++++++++----------------
 9 files changed, 33 insertions(+), 43 deletions(-)

--- a/ui/web.go
+++ b/ui/web.go
@@ -18,48 +18,42 @@ import (
 	"net/http"
 	_ "net/http/pprof" // Comment this line to disable pprof endpoint.
 	"path"
+	"os"
 
-	"github.com/go-kit/log"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 	"github.com/prometheus/common/route"
-
-	"github.com/prometheus/alertmanager/asset"
 )
 
 // Register registers handlers to serve files for the web interface.
-func Register(r *route.Router, reloadCh chan<- chan error, logger log.Logger) {
+func Register(r *route.Router, reloadCh chan<- chan error, uiPath string) {
+	if _, err := os.Stat(path.Join(uiPath, "index.html")); os.IsNotExist(err) {
+		// UI not installed, use stub site.
+		uiPath = "/usr/share/prometheus/alertmanager/no-ui"
+	}
 	r.Get("/metrics", promhttp.Handler().ServeHTTP)
 
 	r.Get("/", func(w http.ResponseWriter, req *http.Request) {
 		disableCaching(w)
 
-		req.URL.Path = "/static/"
-		fs := http.FileServer(asset.Assets)
-		fs.ServeHTTP(w, req)
+		http.ServeFile(w, req, path.Join(uiPath, "index.html"))
 	})
 
 	r.Get("/script.js", func(w http.ResponseWriter, req *http.Request) {
 		disableCaching(w)
 
-		req.URL.Path = "/static/script.js"
-		fs := http.FileServer(asset.Assets)
-		fs.ServeHTTP(w, req)
+		http.ServeFile(w, req, path.Join(uiPath, "script.js"))
 	})
 
 	r.Get("/favicon.ico", func(w http.ResponseWriter, req *http.Request) {
 		disableCaching(w)
 
-		req.URL.Path = "/static/favicon.ico"
-		fs := http.FileServer(asset.Assets)
-		fs.ServeHTTP(w, req)
+		http.ServeFile(w, req, path.Join(uiPath, "favicon.ico"))
 	})
 
 	r.Get("/lib/*path", func(w http.ResponseWriter, req *http.Request) {
 		disableCaching(w)
 
-		req.URL.Path = path.Join("/static/lib", route.Param(req.Context(), "path"))
-		fs := http.FileServer(asset.Assets)
-		fs.ServeHTTP(w, req)
+		http.ServeFile(w, req, path.Join(uiPath, "/lib", route.Param(req.Context(), "path")))
 	})
 
 	r.Post("/-/reload", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
--- a/template/template.go
+++ b/template/template.go
@@ -18,7 +18,6 @@ import (
 	tmplhtml "html/template"
 	"io/ioutil"
 	"net/url"
-	"path"
 	"path/filepath"
 	"regexp"
 	"sort"
@@ -28,7 +27,6 @@ import (
 
 	"github.com/prometheus/common/model"
 
-	"github.com/prometheus/alertmanager/asset"
 	"github.com/prometheus/alertmanager/types"
 )
 
@@ -42,7 +40,7 @@ type Template struct {
 
 // FromGlobs calls ParseGlob on all path globs provided and returns the
 // resulting Template.
-func FromGlobs(paths ...string) (*Template, error) {
+func FromGlobs(defaultTemplate string, paths ...string) (*Template, error) {
 	t := &Template{
 		text: tmpltext.New("").Option("missingkey=zero"),
 		html: tmplhtml.New("").Option("missingkey=zero"),
@@ -51,15 +49,8 @@ func FromGlobs(paths ...string) (*Templa
 	t.text = t.text.Funcs(tmpltext.FuncMap(DefaultFuncs))
 	t.html = t.html.Funcs(tmplhtml.FuncMap(DefaultFuncs))
 
-	defaultTemplates := []string{"default.tmpl", "email.tmpl"}
-
-	for _, file := range defaultTemplates {
-		f, err := asset.Assets.Open(path.Join("/templates", file))
-		if err != nil {
-			return nil, err
-		}
-		defer f.Close()
-		b, err := ioutil.ReadAll(f)
+	if defaultTemplate != "" {
+		b, err := ioutil.ReadFile(defaultTemplate)
 		if err != nil {
 			return nil, err
 		}
@@ -69,7 +60,6 @@ func FromGlobs(paths ...string) (*Templa
 		if t.html, err = t.html.Parse(string(b)); err != nil {
 			return nil, err
 		}
-
 	}
 
 	for _, tp := range paths {
--- a/cmd/alertmanager/main.go
+++ b/cmd/alertmanager/main.go
@@ -201,6 +201,8 @@ func run() int {
 		listenAddress  = kingpin.Flag("web.listen-address", "Address to listen on for the web interface and API.").Default(":9093").String()
 		getConcurrency = kingpin.Flag("web.get-concurrency", "Maximum number of GET requests processed concurrently. If negative or zero, the limit is GOMAXPROC or 8, whichever is larger.").Default("0").Int()
 		httpTimeout    = kingpin.Flag("web.timeout", "Timeout for HTTP requests. If negative or zero, no timeout is set.").Default("0").Duration()
+		uiPath = kingpin.Flag("web.ui-path", "Path to static UI directory.").Default("/usr/share/prometheus/alertmanager/ui/").String()
+		defaultTemplate = kingpin.Flag("template.default", "Path to default notification template.").Default("/usr/share/prometheus/alertmanager/default.tmpl").String()
 
 		clusterBindAddr = kingpin.Flag("cluster.listen-address", "Listen address for cluster. Set to empty string to disable HA mode.").
 				Default(defaultClusterAddr).String()
@@ -409,7 +411,7 @@ func run() int {
 		configLogger,
 	)
 	configCoordinator.Subscribe(func(conf *config.Config) error {
-		tmpl, err = template.FromGlobs(conf.Templates...)
+		tmpl, err = template.FromGlobs(*defaultTemplate, conf.Templates...)
 		if err != nil {
 			return errors.Wrap(err, "failed to parse templates")
 		}
@@ -524,7 +526,7 @@ func run() int {
 
 	webReload := make(chan chan error)
 
-	ui.Register(router, webReload, logger)
+	ui.Register(router, webReload, *uiPath)
 
 	mux := api.Register(router, *routePrefix)
 
--- a/cli/check_config.go
+++ b/cli/check_config.go
@@ -83,7 +83,7 @@ func CheckConfig(args []string) error {
 			fmt.Printf(" - %d receivers\n", len(cfg.Receivers))
 			fmt.Printf(" - %d templates\n", len(cfg.Templates))
 			if len(cfg.Templates) > 0 {
-				_, err = template.FromGlobs(cfg.Templates...)
+				_, err = template.FromGlobs("", cfg.Templates...)
 				if err != nil {
 					fmt.Printf("  FAILED: %s\n", err)
 					failed++
--- a/template/template_test.go
+++ b/template/template_test.go
@@ -277,7 +277,7 @@ func TestData(t *testing.T) {
 }
 
 func TestTemplateExpansion(t *testing.T) {
-	tmpl, err := FromGlobs()
+	tmpl, err := FromGlobs("../template/default.tmpl")
 	require.NoError(t, err)
 
 	for _, tc := range []struct {
--- a/notify/email/email_test.go
+++ b/notify/email/email_test.go
@@ -183,7 +183,7 @@ func notifyEmailWithContext(ctx context.
 		return nil, false, err
 	}
 
-	tmpl, err := template.FromGlobs()
+	tmpl, err := template.FromGlobs("../../template/default.tmpl")
 	if err != nil {
 		return nil, false, err
 	}
--- a/notify/test/test.go
+++ b/notify/test/test.go
@@ -128,7 +128,7 @@ func DefaultRetryCodes() []int {
 
 // CreateTmpl returns a ready-to-use template.
 func CreateTmpl(t *testing.T) *template.Template {
-	tmpl, err := template.FromGlobs()
+	tmpl, err := template.FromGlobs("../../template/default.tmpl")
 	require.NoError(t, err)
 	tmpl.ExternalURL, _ = url.Parse("http://am")
 	return tmpl
--- a/ui/app/src/Views.elm
+++ b/ui/app/src/Views.elm
@@ -54,8 +54,8 @@ failureView model err =
 renderCSS : String -> Html Msg
 renderCSS assetsUrl =
     div []
-        [ cssNode (assetsUrl ++ "lib/bootstrap-4.0.0-alpha.6-dist/css/bootstrap.min.css") BootstrapCSSLoaded
-        , cssNode (assetsUrl ++ "lib/font-awesome-4.7.0/css/font-awesome.min.css") FontAwesomeCSSLoaded
+        [ cssNode (assetsUrl ++ "lib/bootstrap/css/bootstrap.min.css") BootstrapCSSLoaded
+        , cssNode (assetsUrl ++ "lib/font-awesome/css/font-awesome.min.css") FontAwesomeCSSLoaded
         , cssNode (assetsUrl ++ "lib/elm-datepicker/css/elm-datepicker.css") ElmDatepickerCSSLoaded
         ]
 
--- a/cli/template_render.go
+++ b/cli/template_render.go
@@ -106,7 +106,7 @@ func configureTemplateRenderCmd(cc *king
 }
 
 func (c *templateRenderCmd) render(ctx context.Context, _ *kingpin.ParseContext) error {
-	tmpl, err := template.FromGlobs(c.templateFilesGlobs...)
+	tmpl, err := template.FromGlobs("", c.templateFilesGlobs...)
 	if err != nil {
 		return err
 	}
