Skip to content

Commit

Permalink
Make the ReactUI the default one (#4081)
Browse files Browse the repository at this point in the history
* make the reactUI the default one

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>

* prefix all static path to having back the classic UI

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>

* add missing react route

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>

* remove unused method

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>

* update bucket ui to use the react app by default

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>

* rollback the bucket to see if it fixed the e2e

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>

* fix bucket display

Signed-off-by: Augustin Husson <husson.augustin@gmail.com>

Co-authored-by: Prem Saraswat <prmsrswt@gmail.com>

Co-authored-by: Prem Saraswat <prmsrswt@gmail.com>
  • Loading branch information
Nexucis and onprem committed Apr 22, 2021
1 parent 6d4d1c5 commit 393a471
Show file tree
Hide file tree
Showing 18 changed files with 323 additions and 277 deletions.
260 changes: 130 additions & 130 deletions pkg/ui/bindata.go

Large diffs are not rendered by default.

40 changes: 24 additions & 16 deletions pkg/ui/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ func NewBucketUI(logger log.Logger, label, externalPrefix, prefixHeader, uiPrefi
"Component": comp.String(),
}

tmplFuncs := queryTmplFuncs()
// here the uiPrefix is empty because the uiPrefix is injected in the pathPrefix.
// Which seems to be the only way to the correct path in the file bucket.html
tmplFuncs["uiPrefix"] = func() string { return "" }

return &Bucket{
BaseUI: NewBaseUI(log.With(logger, "component", "bucketUI"), "bucket_menu.html", queryTmplFuncs(), tmplVariables, externalPrefix, prefixHeader, comp),
BaseUI: NewBaseUI(log.With(logger, "component", "bucketUI"), "bucket_menu.html", tmplFuncs, tmplVariables, externalPrefix, prefixHeader, comp),
Blocks: "[]",
Label: label,
externalPrefix: externalPrefix,
Expand All @@ -49,27 +54,30 @@ func NewBucketUI(logger log.Logger, label, externalPrefix, prefixHeader, uiPrefi

// Register registers http routes for bucket UI.
func (b *Bucket) Register(r *route.Router, registerNewUI bool, ins extpromhttp.InstrumentationMiddleware) {
instrf := func(name string, next func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
return ins.NewHandler(b.externalPrefix+name, http.HandlerFunc(next))
}
r.WithPrefix(b.uiPrefix).Get("/", instrf("root", b.root))
r.WithPrefix(b.uiPrefix).Get("/static/*filepath", instrf("static", b.serveStaticAsset))
classicPrefix := path.Join("/classic", b.uiPrefix)
r.WithPrefix(classicPrefix).Get("/", instrf("bucket", ins, b.bucket))
r.WithPrefix(classicPrefix).Get("/static/*filepath", instrf("static", ins, b.serveStaticAsset))

if registerNewUI {
// Make sure that "<path-prefix>/new" is redirected to "<path-prefix>/new/" and
// not just the naked "/new/", which would be the default behavior of the router
// with the "RedirectTrailingSlash" option (https://godoc.org/github.com/julienschmidt/httprouter#Router.RedirectTrailingSlash),
// and which breaks users with a --web.route-prefix that deviates from the path derived
// from the external URL.
r.Get("/new", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(b.logger, b.externalPrefix, b.prefixHeader, r), "new")+"/", http.StatusFound)
// Redirect the original React UI's path (under "/new") to its new path at the root.
r.Get("/new/*path", func(w http.ResponseWriter, r *http.Request) {
p := route.Param(r.Context(), "path")
http.Redirect(w, r, path.Join(GetWebPrefix(b.logger, b.externalPrefix, b.prefixHeader, r), strings.TrimPrefix(p, "/new"))+"?"+r.URL.RawQuery, http.StatusFound)
})
r.Get("/new/*filepath", instrf("react-static", b.serveReactUI))

r.Get("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(b.logger, b.externalPrefix, b.prefixHeader, r), b.uiPrefix), http.StatusFound)
})

registerReactApp(r, ins, b.BaseUI)
}
}

// Handle / of bucket UIs.
func (b *Bucket) root(w http.ResponseWriter, r *http.Request) {
b.executeTemplate(w, "bucket.html", GetWebPrefix(b.logger, path.Join(b.externalPrefix, strings.TrimPrefix(b.uiPrefix, "/")), b.prefixHeader, r), b)
func (b *Bucket) bucket(w http.ResponseWriter, r *http.Request) {
classicPrefix := path.Join("/classic", b.uiPrefix)
prefix := GetWebPrefix(b.logger, path.Join(b.externalPrefix, strings.TrimPrefix(classicPrefix, "/")), b.prefixHeader, r)
b.executeTemplate(w, "bucket.html", prefix, b)
}

func (b *Bucket) Set(blocks []metadata.Meta, err error) {
Expand Down
48 changes: 22 additions & 26 deletions pkg/ui/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/go-kit/kit/log"
"github.com/prometheus/common/model"
"github.com/prometheus/common/route"

"github.com/thanos-io/thanos/pkg/api"
"github.com/thanos-io/thanos/pkg/component"
extpromhttp "github.com/thanos-io/thanos/pkg/extprom/http"
Expand All @@ -39,8 +38,11 @@ func NewQueryUI(logger log.Logger, storeSet *query.StoreSet, externalPrefix, pre
}
runtimeInfo := api.GetRuntimeInfoFunc(logger)

tmplFuncs := queryTmplFuncs()
tmplFuncs["uiPrefix"] = func() string { return "/classic" }

return &Query{
BaseUI: NewBaseUI(logger, "query_menu.html", queryTmplFuncs(), tmplVariables, externalPrefix, prefixHeader, component.Query),
BaseUI: NewBaseUI(logger, "query_menu.html", tmplFuncs, tmplVariables, externalPrefix, prefixHeader, component.Query),
storeSet: storeSet,
externalPrefix: externalPrefix,
prefixHeader: prefixHeader,
Expand All @@ -65,38 +67,32 @@ func queryTmplFuncs() template.FuncMap {

// Register registers new GET routes for subpages and redirects from / to /graph.
func (q *Query) Register(r *route.Router, ins extpromhttp.InstrumentationMiddleware) {
instrf := func(name string, next func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
return ins.NewHandler(name, http.HandlerFunc(next))
}
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(q.logger, q.externalPrefix, q.prefixHeader, r), "/graph"), http.StatusFound)
})

r.Get("/classic/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(q.logger, q.externalPrefix, q.prefixHeader, r), "/classic/graph"), http.StatusFound)
})

r.Get("/", instrf("root", q.root))
r.Get("/graph", instrf("graph", q.graph))
r.Get("/stores", instrf("stores", q.stores))
r.Get("/status", instrf("status", q.status))

r.Get("/static/*filepath", instrf("static", q.serveStaticAsset))
// Make sure that "<path-prefix>/new" is redirected to "<path-prefix>/new/" and
// not just the naked "/new/", which would be the default behavior of the router
// with the "RedirectTrailingSlash" option (https://godoc.org/github.com/julienschmidt/httprouter#Router.RedirectTrailingSlash),
// and which breaks users with a --web.route-prefix that deviates from the path derived
// from the external URL.
r.Get("/new", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(q.logger, q.externalPrefix, q.prefixHeader, r), "new")+"/graph", http.StatusFound)
// Redirect the original React UI's path (under "/new") to its new path at the root.
r.Get("/new/*path", func(w http.ResponseWriter, r *http.Request) {
p := route.Param(r.Context(), "path")
http.Redirect(w, r, path.Join(GetWebPrefix(q.logger, q.externalPrefix, q.prefixHeader, r), strings.TrimPrefix(p, "/new"))+"?"+r.URL.RawQuery, http.StatusFound)
})
r.Get("/new/*filepath", instrf("react-static", q.serveReactUI))

r.Get("/classic/graph", instrf("graph", ins, q.graph))
r.Get("/classic/stores", instrf("stores", ins, q.stores))
r.Get("/classic/status", instrf("status", ins, q.status))
r.Get("/classic/static/*filepath", instrf("static", ins, q.serveStaticAsset))

registerReactApp(r, ins, q.BaseUI)

// TODO(bplotka): Consider adding more Thanos related data e.g:
// - What store nodes we see currently.
// - What sidecars we see currently.
}

// Root redirects "/" requests to "/graph", taking into account the path prefix value.
func (q *Query) root(w http.ResponseWriter, r *http.Request) {
prefix := GetWebPrefix(q.logger, q.externalPrefix, q.prefixHeader, r)

http.Redirect(w, r, path.Join("/", prefix, "/graph"), http.StatusFound)
}

func (q *Query) graph(w http.ResponseWriter, r *http.Request) {
prefix := GetWebPrefix(q.logger, q.externalPrefix, q.prefixHeader, r)

Expand Down
4 changes: 2 additions & 2 deletions pkg/ui/react-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const App: FC<PathPrefixProps & ThanosComponentProps> = ({ pathPrefix, thanosCom
/>
<Container fluid style={{ paddingTop: 70 }}>
<QueryParamProvider reachHistory={globalHistory}>
<Router basepath={`${pathPrefix}/new`}>
<Redirect from="/" to={`${pathPrefix}/new${defaultRouteConfig[thanosComponent]}`} />
<Router basepath={`${pathPrefix}`}>
<Redirect from="/" to={`${pathPrefix}${defaultRouteConfig[thanosComponent]}`} />

<PanelList path="/graph" pathPrefix={pathPrefix} />
<Alerts path="/alerts" pathPrefix={pathPrefix} />
Expand Down
22 changes: 11 additions & 11 deletions pkg/ui/react-app/src/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const Navigation: FC<PathPrefixProps & NavbarProps> = ({ pathPrefix, consolesLin
return (
<Navbar className="mb-3" dark color="dark" expand="md" fixed="top">
<NavbarToggler onClick={toggle} />
<Link className="pt-0 navbar-brand" to={`${pathPrefix}/new/graph`}>
<Link className="pt-0 navbar-brand" to={`${pathPrefix}/graph`}>
Prometheus
</Link>
<Collapse isOpen={isOpen} navbar style={{ justifyContent: 'space-between' }}>
Expand All @@ -35,12 +35,12 @@ const Navigation: FC<PathPrefixProps & NavbarProps> = ({ pathPrefix, consolesLin
</NavItem>
)}
<NavItem>
<NavLink tag={Link} to={`${pathPrefix}/new/alerts`}>
<NavLink tag={Link} to={`${pathPrefix}/alerts`}>
Alerts
</NavLink>
</NavItem>
<NavItem>
<NavLink tag={Link} to={`${pathPrefix}/new/graph`}>
<NavLink tag={Link} to={`${pathPrefix}/graph`}>
Graph
</NavLink>
</NavItem>
Expand All @@ -49,25 +49,25 @@ const Navigation: FC<PathPrefixProps & NavbarProps> = ({ pathPrefix, consolesLin
Status
</DropdownToggle>
<DropdownMenu>
<DropdownItem tag={Link} to={`${pathPrefix}/new/status`}>
<DropdownItem tag={Link} to={`${pathPrefix}/status`}>
Runtime & Build Information
</DropdownItem>
<DropdownItem tag={Link} to={`${pathPrefix}/new/tsdb-status`}>
<DropdownItem tag={Link} to={`${pathPrefix}/tsdb-status`}>
TSDB Status
</DropdownItem>
<DropdownItem tag={Link} to={`${pathPrefix}/new/flags`}>
<DropdownItem tag={Link} to={`${pathPrefix}/flags`}>
Command-Line Flags
</DropdownItem>
<DropdownItem tag={Link} to={`${pathPrefix}/new/config`}>
<DropdownItem tag={Link} to={`${pathPrefix}/config`}>
Configuration
</DropdownItem>
<DropdownItem tag={Link} to={`${pathPrefix}/new/rules`}>
<DropdownItem tag={Link} to={`${pathPrefix}/rules`}>
Rules
</DropdownItem>
<DropdownItem tag={Link} to={`${pathPrefix}/new/targets`}>
<DropdownItem tag={Link} to={`${pathPrefix}/targets`}>
Targets
</DropdownItem>
<DropdownItem tag={Link} to={`${pathPrefix}/new/service-discovery`}>
<DropdownItem tag={Link} to={`${pathPrefix}/service-discovery`}>
Service Discovery
</DropdownItem>
</DropdownMenu>
Expand All @@ -76,7 +76,7 @@ const Navigation: FC<PathPrefixProps & NavbarProps> = ({ pathPrefix, consolesLin
<NavLink href="https://prometheus.io/docs/prometheus/latest/getting_started/">Help</NavLink>
</NavItem>
<NavItem>
<NavLink href={`${pathPrefix}/graph${window.location.search}`}>Classic UI</NavLink>
<NavLink href={`${pathPrefix}/classic/graph${window.location.search}`}>Classic UI</NavLink>
</NavItem>
</Nav>
</Collapse>
Expand Down
50 changes: 25 additions & 25 deletions pkg/ui/react-app/src/thanos/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,69 +26,69 @@ interface NavDropDown {

const navConfig: { [component: string]: (NavConfig | NavDropDown)[] } = {
query: [
{ name: 'Graph', uri: '/new/graph' },
{ name: 'Stores', uri: '/new/stores' },
{ name: 'Graph', uri: '/graph' },
{ name: 'Stores', uri: '/stores' },
{
name: 'Status',
children: [
{ name: 'Runtime & Build Information', uri: '/new/status' },
{ name: 'Command-Line Flags', uri: '/new/flags' },
{ name: 'Runtime & Build Information', uri: '/status' },
{ name: 'Command-Line Flags', uri: '/flags' },
// TODO(onprem): Uncomment after `--target` flag on Querier becomes
// non-hidden or we move to `--endpoint`.
// { name: 'Targets', uri: '/new/targets' },
// { name: 'Targets', uri: '/targets' },
],
},
],
rule: [
{ name: 'Alerts', uri: '/new/alerts' },
{ name: 'Rules', uri: '/new/rules' },
{ name: 'Alerts', uri: '/alerts' },
{ name: 'Rules', uri: '/rules' },
{
name: 'Status',
children: [
{ name: 'Runtime & Build Information', uri: '/new/status' },
{ name: 'Command-Line Flags', uri: '/new/flags' },
{ name: 'Runtime & Build Information', uri: '/status' },
{ name: 'Command-Line Flags', uri: '/flags' },
],
},
],
bucket: [
{ name: 'Blocks', uri: '/new/blocks' },
{ name: 'Blocks', uri: '/blocks' },
{
name: 'Status',
children: [
{ name: 'Runtime & Build Information', uri: '/new/status' },
{ name: 'Command-Line Flags', uri: '/new/flags' },
{ name: 'Runtime & Build Information', uri: '/status' },
{ name: 'Command-Line Flags', uri: '/flags' },
],
},
],
compact: [
{ name: 'Global Blocks', uri: '/new/blocks' },
{ name: 'Loaded Blocks', uri: '/new/loaded' },
{ name: 'Global Blocks', uri: '/blocks' },
{ name: 'Loaded Blocks', uri: '/loaded' },
{
name: 'Status',
children: [
{ name: 'Runtime & Build Information', uri: '/new/status' },
{ name: 'Command-Line Flags', uri: '/new/flags' },
{ name: 'Runtime & Build Information', uri: '/status' },
{ name: 'Command-Line Flags', uri: '/flags' },
],
},
],
store: [
{ name: 'Loaded Blocks', uri: '/new/loaded' },
{ name: 'Loaded Blocks', uri: '/loaded' },
{
name: 'Status',
children: [
{ name: 'Runtime & Build Information', uri: '/new/status' },
{ name: 'Command-Line Flags', uri: '/new/flags' },
{ name: 'Runtime & Build Information', uri: '/status' },
{ name: 'Command-Line Flags', uri: '/flags' },
],
},
],
};

const defaultClassicUIRoute: { [component: string]: string } = {
query: '/graph',
rule: '/alerts',
bucket: '/',
compact: '/loaded',
store: '/loaded',
query: '/classic/graph',
rule: '/classic/alerts',
bucket: '/classic',
compact: '/classic/loaded',
store: '/classic/loaded',
};

interface NavigationProps {
Expand All @@ -102,7 +102,7 @@ const Navigation: FC<PathPrefixProps & NavigationProps> = ({ pathPrefix, thanosC
return (
<Navbar className="mb-3" dark color="dark" expand="md" fixed="top">
<NavbarToggler onClick={toggle} />
<Link className="navbar-brand" to={`${pathPrefix}/new${defaultRoute}`}>
<Link className="navbar-brand" to={`${pathPrefix}${defaultRoute}`}>
Thanos - {thanosComponent[0].toUpperCase()}
{thanosComponent.substr(1, thanosComponent.length)}
</Link>
Expand Down
46 changes: 22 additions & 24 deletions pkg/ui/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/http"
"path"
"regexp"
"strings"
"time"

"github.com/go-kit/kit/log"
Expand Down Expand Up @@ -37,8 +38,11 @@ func NewRuleUI(logger log.Logger, reg prometheus.Registerer, ruleManager *thanos
"queryURL": queryURL,
}

tmplFuncs := ruleTmplFuncs(queryURL)
tmplFuncs["uiPrefix"] = func() string { return "/classic" }

return &Rule{
BaseUI: NewBaseUI(logger, "rule_menu.html", ruleTmplFuncs(queryURL), tmplVariables, externalPrefix, prefixHeader, component.Rule),
BaseUI: NewBaseUI(logger, "rule_menu.html", tmplFuncs, tmplVariables, externalPrefix, prefixHeader, component.Rule),
externalPrefix: externalPrefix,
prefixHeader: prefixHeader,
ruleManager: ruleManager,
Expand Down Expand Up @@ -153,32 +157,26 @@ func (ru *Rule) rules(w http.ResponseWriter, r *http.Request) {
ru.executeTemplate(w, "rules.html", prefix, ru.ruleManager)
}

// Root redirects / requests to /graph, taking into account the path prefix value.
func (ru *Rule) root(w http.ResponseWriter, r *http.Request) {
prefix := GetWebPrefix(ru.logger, ru.externalPrefix, ru.prefixHeader, r)

http.Redirect(w, r, path.Join(prefix, "/alerts"), http.StatusFound)
}

func (ru *Rule) Register(r *route.Router, ins extpromhttp.InstrumentationMiddleware) {
instrf := func(name string, next func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
return ins.NewHandler(name, http.HandlerFunc(next))
}
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(ru.logger, ru.externalPrefix, ru.prefixHeader, r), "/alerts"), http.StatusFound)
})

r.Get("/classic/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(ru.logger, ru.externalPrefix, ru.prefixHeader, r), "/classic/alerts"), http.StatusFound)
})

r.Get("/", instrf("root", ru.root))
r.Get("/alerts", instrf("alerts", ru.alerts))
r.Get("/rules", instrf("rules", ru.rules))

r.Get("/static/*filepath", instrf("static", ru.serveStaticAsset))
// Make sure that "<path-prefix>/new" is redirected to "<path-prefix>/new/" and
// not just the naked "/new/", which would be the default behavior of the router
// with the "RedirectTrailingSlash" option (https://godoc.org/github.com/julienschmidt/httprouter#Router.RedirectTrailingSlash),
// and which breaks users with a --web.route-prefix that deviates from the path derived
// from the external URL.
r.Get("/new", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, path.Join(GetWebPrefix(ru.logger, ru.externalPrefix, ru.prefixHeader, r), "new")+"/", http.StatusFound)
// Redirect the original React UI's path (under "/new") to its new path at the root.
r.Get("/new/*path", func(w http.ResponseWriter, r *http.Request) {
p := route.Param(r.Context(), "path")
http.Redirect(w, r, path.Join(GetWebPrefix(ru.logger, ru.externalPrefix, ru.prefixHeader, r), strings.TrimPrefix(p, "/new"))+"?"+r.URL.RawQuery, http.StatusFound)
})
r.Get("/new/*filepath", instrf("react-static", ru.serveReactUI))

r.Get("/classic/alerts", instrf("alerts", ins, ru.alerts))
r.Get("/classic/rules", instrf("rules", ins, ru.rules))

r.Get("/classic/static/*filepath", instrf("static", ins, ru.serveStaticAsset))
registerReactApp(r, ins, ru.BaseUI)
}

// AlertStatus bundles alerting rules and the mapping of alert states to row classes.
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/static/js/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -1301,7 +1301,7 @@ function init() {
});

$.ajax({
url: PATH_PREFIX + "/static/js/graph_template.handlebar?v=" + BUILD_VERSION,
url: PATH_PREFIX + "/classic/static/js/graph_template.handlebar?v=" + BUILD_VERSION,
success: function(data) {

graphTemplate = data;
Expand Down

0 comments on commit 393a471

Please sign in to comment.