Merge pull request #2672 from influxdata/feature/env
ENV variable TELEGRAF_SYSTEM_INTERVALpull/10616/head
commit
af4e525aaf
|
@ -647,3 +647,9 @@ type BuildStore interface {
|
||||||
Get(context.Context) (BuildInfo, error)
|
Get(context.Context) (BuildInfo, error)
|
||||||
Update(context.Context, BuildInfo) error
|
Update(context.Context, BuildInfo) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Environement is the set of front-end exposed environment variables
|
||||||
|
// that were set on the server
|
||||||
|
type Environment struct {
|
||||||
|
TelegrafSystemInterval time.Duration `json:"telegrafSystemInterval"`
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/influxdata/chronograf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type envResponse struct {
|
||||||
|
Links selfLinks `json:"links"`
|
||||||
|
TelegrafSystemInterval string `json:"telegrafSystemInterval"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEnvResponse(env chronograf.Environment) *envResponse {
|
||||||
|
return &envResponse{
|
||||||
|
Links: selfLinks{
|
||||||
|
Self: "/chronograf/v1/env",
|
||||||
|
},
|
||||||
|
TelegrafSystemInterval: env.TelegrafSystemInterval.String(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Environment retrieves the global application configuration
|
||||||
|
func (s *Service) Environment(w http.ResponseWriter, r *http.Request) {
|
||||||
|
res := newEnvResponse(s.Env)
|
||||||
|
encodeJSON(w, http.StatusOK, res, s.Logger)
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdata/chronograf"
|
||||||
|
"github.com/influxdata/chronograf/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnvironment(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
Environment chronograf.Environment
|
||||||
|
}
|
||||||
|
type wants struct {
|
||||||
|
statusCode int
|
||||||
|
contentType string
|
||||||
|
body string
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
wants wants
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Get environment",
|
||||||
|
fields: fields{
|
||||||
|
Environment: chronograf.Environment{
|
||||||
|
TelegrafSystemInterval: 1 * time.Minute,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wants: wants{
|
||||||
|
statusCode: 200,
|
||||||
|
contentType: "application/json",
|
||||||
|
body: `{"links":{"self":"/chronograf/v1/env"},"telegrafSystemInterval":"1m0s"}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
s := &Service{
|
||||||
|
Env: tt.fields.Environment,
|
||||||
|
Logger: log.New(log.DebugLevel),
|
||||||
|
}
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r := httptest.NewRequest("GET", "http://any.url", nil)
|
||||||
|
|
||||||
|
s.Environment(w, r)
|
||||||
|
|
||||||
|
resp := w.Result()
|
||||||
|
content := resp.Header.Get("Content-Type")
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode != tt.wants.statusCode {
|
||||||
|
t.Errorf("%q. Config() = %v, want %v", tt.name, resp.StatusCode, tt.wants.statusCode)
|
||||||
|
}
|
||||||
|
if tt.wants.contentType != "" && content != tt.wants.contentType {
|
||||||
|
t.Errorf("%q. Config() = %v, want %v", tt.name, content, tt.wants.contentType)
|
||||||
|
}
|
||||||
|
if eq, _ := jsonEqual(string(body), tt.wants.body); tt.wants.body != "" && !eq {
|
||||||
|
t.Errorf("%q. Config() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wants.body)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -242,6 +242,8 @@ func NewMux(opts MuxOpts, service Service) http.Handler {
|
||||||
router.GET("/chronograf/v1/config/:section", EnsureSuperAdmin(service.ConfigSection))
|
router.GET("/chronograf/v1/config/:section", EnsureSuperAdmin(service.ConfigSection))
|
||||||
router.PUT("/chronograf/v1/config/:section", EnsureSuperAdmin(service.ReplaceConfigSection))
|
router.PUT("/chronograf/v1/config/:section", EnsureSuperAdmin(service.ReplaceConfigSection))
|
||||||
|
|
||||||
|
router.GET("/chronograf/v1/env", EnsureViewer(service.Environment))
|
||||||
|
|
||||||
allRoutes := &AllRoutes{
|
allRoutes := &AllRoutes{
|
||||||
Logger: opts.Logger,
|
Logger: opts.Logger,
|
||||||
StatusFeed: opts.StatusFeedURL,
|
StatusFeed: opts.StatusFeedURL,
|
||||||
|
|
|
@ -35,6 +35,7 @@ type getRoutesResponse struct {
|
||||||
Mappings string `json:"mappings"` // Location of the application mappings endpoint
|
Mappings string `json:"mappings"` // Location of the application mappings endpoint
|
||||||
Sources string `json:"sources"` // Location of the sources endpoint
|
Sources string `json:"sources"` // Location of the sources endpoint
|
||||||
Me string `json:"me"` // Location of the me endpoint
|
Me string `json:"me"` // Location of the me endpoint
|
||||||
|
Environment string `json:"environment"` // Location of the environement endpoint
|
||||||
Dashboards string `json:"dashboards"` // Location of the dashboards endpoint
|
Dashboards string `json:"dashboards"` // Location of the dashboards endpoint
|
||||||
Config getConfigLinksResponse `json:"config"` // Location of the config endpoint and its various sections
|
Config getConfigLinksResponse `json:"config"` // Location of the config endpoint and its various sections
|
||||||
Auth []AuthRoute `json:"auth"` // Location of all auth routes.
|
Auth []AuthRoute `json:"auth"` // Location of all auth routes.
|
||||||
|
@ -67,6 +68,7 @@ func (a *AllRoutes) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
Users: "/chronograf/v1/users",
|
Users: "/chronograf/v1/users",
|
||||||
Organizations: "/chronograf/v1/organizations",
|
Organizations: "/chronograf/v1/organizations",
|
||||||
Me: "/chronograf/v1/me",
|
Me: "/chronograf/v1/me",
|
||||||
|
Environment: "/chronograf/v1/env",
|
||||||
Mappings: "/chronograf/v1/mappings",
|
Mappings: "/chronograf/v1/mappings",
|
||||||
Dashboards: "/chronograf/v1/dashboards",
|
Dashboards: "/chronograf/v1/dashboards",
|
||||||
Config: getConfigLinksResponse{
|
Config: getConfigLinksResponse{
|
||||||
|
|
|
@ -29,7 +29,7 @@ func TestAllRoutes(t *testing.T) {
|
||||||
if err := json.Unmarshal(body, &routes); err != nil {
|
if err := json.Unmarshal(body, &routes); err != nil {
|
||||||
t.Error("TestAllRoutes not able to unmarshal JSON response")
|
t.Error("TestAllRoutes not able to unmarshal JSON response")
|
||||||
}
|
}
|
||||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[],"external":{"statusFeed":""}}
|
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[],"external":{"statusFeed":""}}
|
||||||
`
|
`
|
||||||
if want != string(body) {
|
if want != string(body) {
|
||||||
t.Errorf("TestAllRoutes\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
t.Errorf("TestAllRoutes\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
||||||
|
@ -67,7 +67,7 @@ func TestAllRoutesWithAuth(t *testing.T) {
|
||||||
if err := json.Unmarshal(body, &routes); err != nil {
|
if err := json.Unmarshal(body, &routes); err != nil {
|
||||||
t.Error("TestAllRoutesWithAuth not able to unmarshal JSON response")
|
t.Error("TestAllRoutesWithAuth not able to unmarshal JSON response")
|
||||||
}
|
}
|
||||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[{"name":"github","label":"GitHub","login":"/oauth/github/login","logout":"/oauth/github/logout","callback":"/oauth/github/callback"}],"logout":"/oauth/logout","external":{"statusFeed":""}}
|
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[{"name":"github","label":"GitHub","login":"/oauth/github/login","logout":"/oauth/github/logout","callback":"/oauth/github/callback"}],"logout":"/oauth/logout","external":{"statusFeed":""}}
|
||||||
`
|
`
|
||||||
if want != string(body) {
|
if want != string(body) {
|
||||||
t.Errorf("TestAllRoutesWithAuth\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
t.Errorf("TestAllRoutesWithAuth\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
||||||
|
@ -100,7 +100,7 @@ func TestAllRoutesWithExternalLinks(t *testing.T) {
|
||||||
if err := json.Unmarshal(body, &routes); err != nil {
|
if err := json.Unmarshal(body, &routes); err != nil {
|
||||||
t.Error("TestAllRoutesWithExternalLinks not able to unmarshal JSON response")
|
t.Error("TestAllRoutesWithExternalLinks not able to unmarshal JSON response")
|
||||||
}
|
}
|
||||||
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[],"external":{"statusFeed":"http://pineapple.life/feed.json","custom":[{"name":"cubeapple","url":"https://cube.apple"}]}}
|
want := `{"layouts":"/chronograf/v1/layouts","users":"/chronograf/v1/users","organizations":"/chronograf/v1/organizations","mappings":"/chronograf/v1/mappings","sources":"/chronograf/v1/sources","me":"/chronograf/v1/me","environment":"/chronograf/v1/env","dashboards":"/chronograf/v1/dashboards","config":{"self":"/chronograf/v1/config","auth":"/chronograf/v1/config/auth"},"auth":[],"external":{"statusFeed":"http://pineapple.life/feed.json","custom":[{"name":"cubeapple","url":"https://cube.apple"}]}}
|
||||||
`
|
`
|
||||||
if want != string(body) {
|
if want != string(body) {
|
||||||
t.Errorf("TestAllRoutesWithExternalLinks\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
t.Errorf("TestAllRoutesWithExternalLinks\nwanted\n*%s*\ngot\n*%s*", want, string(body))
|
||||||
|
|
|
@ -86,8 +86,9 @@ type Server struct {
|
||||||
Auth0ClientSecret string `long:"auth0-client-secret" description:"Auth0 Client Secret for OAuth2 support" env:"AUTH0_CLIENT_SECRET"`
|
Auth0ClientSecret string `long:"auth0-client-secret" description:"Auth0 Client Secret for OAuth2 support" env:"AUTH0_CLIENT_SECRET"`
|
||||||
Auth0Organizations []string `long:"auth0-organizations" description:"Auth0 organizations permitted to access Chronograf (comma separated)" env:"AUTH0_ORGS" env-delim:","`
|
Auth0Organizations []string `long:"auth0-organizations" description:"Auth0 organizations permitted to access Chronograf (comma separated)" env:"AUTH0_ORGS" env-delim:","`
|
||||||
|
|
||||||
StatusFeedURL string `long:"status-feed-url" description:"URL of a JSON Feed to display as a News Feed on the client Status page." default:"https://www.influxdata.com/feed/json" env:"STATUS_FEED_URL"`
|
StatusFeedURL string `long:"status-feed-url" description:"URL of a JSON Feed to display as a News Feed on the client Status page." default:"https://www.influxdata.com/feed/json" env:"STATUS_FEED_URL"`
|
||||||
CustomLinks map[string]string `long:"custom-link" description:"Custom link to be added to the client User menu. Multiple links can be added by using multiple of the same flag with different 'name:url' values, or as an environment variable with comma-separated 'name:url' values. E.g. via flags: '--custom-link=InfluxData:https://www.influxdata.com --custom-link=Chronograf:https://github.com/influxdata/chronograf'. E.g. via environment variable: 'export CUSTOM_LINKS=InfluxData:https://www.influxdata.com,Chronograf:https://github.com/influxdata/chronograf'" env:"CUSTOM_LINKS" env-delim:","`
|
CustomLinks map[string]string `long:"custom-link" description:"Custom link to be added to the client User menu. Multiple links can be added by using multiple of the same flag with different 'name:url' values, or as an environment variable with comma-separated 'name:url' values. E.g. via flags: '--custom-link=InfluxData:https://www.influxdata.com --custom-link=Chronograf:https://github.com/influxdata/chronograf'. E.g. via environment variable: 'export CUSTOM_LINKS=InfluxData:https://www.influxdata.com,Chronograf:https://github.com/influxdata/chronograf'" env:"CUSTOM_LINKS" env-delim:","`
|
||||||
|
TelegrafSystemInterval time.Duration `long:"telegraf-system-interval" default:"1m" description:"Duration used in the GROUP BY time interval for the hosts list" env:"TELEGRAF_SYSTEM_INTERVAL"`
|
||||||
|
|
||||||
ReportingDisabled bool `short:"r" long:"reporting-disabled" description:"Disable reporting of usage stats (os,arch,version,cluster_id,uptime) once every 24hr" env:"REPORTING_DISABLED"`
|
ReportingDisabled bool `short:"r" long:"reporting-disabled" description:"Disable reporting of usage stats (os,arch,version,cluster_id,uptime) once every 24hr" env:"REPORTING_DISABLED"`
|
||||||
LogLevel string `short:"l" long:"log-level" value-name:"choice" choice:"debug" choice:"info" choice:"error" default:"info" description:"Set the logging level" env:"LOG_LEVEL"`
|
LogLevel string `short:"l" long:"log-level" value-name:"choice" choice:"debug" choice:"info" choice:"error" default:"info" description:"Set the logging level" env:"LOG_LEVEL"`
|
||||||
|
@ -325,6 +326,9 @@ func (s *Server) Serve(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
service := openService(ctx, s.BuildInfo, s.BoltPath, s.newBuilders(logger), logger, s.useAuth())
|
service := openService(ctx, s.BuildInfo, s.BoltPath, s.newBuilders(logger), logger, s.useAuth())
|
||||||
|
service.Env = chronograf.Environment{
|
||||||
|
TelegrafSystemInterval: s.TelegrafSystemInterval,
|
||||||
|
}
|
||||||
if err := service.HandleNewSources(ctx, s.NewSources); err != nil {
|
if err := service.HandleNewSources(ctx, s.NewSources); err != nil {
|
||||||
logger.
|
logger.
|
||||||
WithField("component", "server").
|
WithField("component", "server").
|
||||||
|
|
|
@ -15,6 +15,7 @@ type Service struct {
|
||||||
TimeSeriesClient TimeSeriesClient
|
TimeSeriesClient TimeSeriesClient
|
||||||
Logger chronograf.Logger
|
Logger chronograf.Logger
|
||||||
UseAuth bool
|
UseAuth bool
|
||||||
|
Env chronograf.Environment
|
||||||
Databases chronograf.Databases
|
Databases chronograf.Databases
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,19 @@ import {proxy} from 'utils/queryUrlGenerator'
|
||||||
import AJAX from 'utils/ajax'
|
import AJAX from 'utils/ajax'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
export function getCpuAndLoadForHosts(proxyLink, telegrafDB) {
|
export const getCpuAndLoadForHosts = (
|
||||||
|
proxyLink,
|
||||||
|
telegrafDB,
|
||||||
|
telegrafSystemInterval
|
||||||
|
) => {
|
||||||
return proxy({
|
return proxy({
|
||||||
source: proxyLink,
|
source: proxyLink,
|
||||||
query: `SELECT mean("usage_user") FROM cpu WHERE "cpu" = 'cpu-total' AND time > now() - 10m GROUP BY host;
|
query: `SELECT mean("usage_user") FROM cpu WHERE "cpu" = 'cpu-total' AND time > now() - 10m GROUP BY host;
|
||||||
SELECT mean("load1") FROM "system" WHERE time > now() - 10m GROUP BY host;
|
SELECT mean("load1") FROM "system" WHERE time > now() - 10m GROUP BY host;
|
||||||
SELECT non_negative_derivative(mean(uptime)) AS deltaUptime FROM "system" WHERE time > now() - 10m GROUP BY host, time(1m) fill(0);
|
SELECT non_negative_derivative(mean(uptime)) AS deltaUptime FROM "system" WHERE time > now() - ${telegrafSystemInterval} * 10 GROUP BY host, time(${telegrafSystemInterval}) fill(0);
|
||||||
SELECT mean("Percent_Processor_Time") FROM win_cpu WHERE time > now() - 10m GROUP BY host;
|
SELECT mean("Percent_Processor_Time") FROM win_cpu WHERE time > now() - 10m GROUP BY host;
|
||||||
SELECT mean("Processor_Queue_Length") FROM win_system WHERE time > now() - 10s GROUP BY host;
|
SELECT mean("Processor_Queue_Length") FROM win_system WHERE time > now() - 10s GROUP BY host;
|
||||||
SELECT non_negative_derivative(mean("System_Up_Time")) AS winDeltaUptime FROM win_system WHERE time > now() - 10m GROUP BY host, time(1m) fill(0);
|
SELECT non_negative_derivative(mean("System_Up_Time")) AS winDeltaUptime FROM win_system WHERE time > now() - ${telegrafSystemInterval} * 10 GROUP BY host, time(${telegrafSystemInterval}) fill(0);
|
||||||
SHOW TAG VALUES WITH KEY = "host";`,
|
SHOW TAG VALUES WITH KEY = "host";`,
|
||||||
db: telegrafDB,
|
db: telegrafDB,
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
|
@ -116,7 +120,7 @@ export const getLayouts = () =>
|
||||||
resource: 'layouts',
|
resource: 'layouts',
|
||||||
})
|
})
|
||||||
|
|
||||||
export function getAppsForHosts(proxyLink, hosts, appLayouts, telegrafDB) {
|
export const getAppsForHosts = (proxyLink, hosts, appLayouts, telegrafDB) => {
|
||||||
const measurements = appLayouts.map(m => `^${m.measurement}$`).join('|')
|
const measurements = appLayouts.map(m => `^${m.measurement}$`).join('|')
|
||||||
const measurementsToApps = _.zipObject(
|
const measurementsToApps = _.zipObject(
|
||||||
appLayouts.map(m => m.measurement),
|
appLayouts.map(m => m.measurement),
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import React, {PropTypes, Component} from 'react'
|
import React, {PropTypes, Component} from 'react'
|
||||||
|
import {connect} from 'react-redux'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
import HostsTable from 'src/hosts/components/HostsTable'
|
import HostsTable from 'src/hosts/components/HostsTable'
|
||||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||||
|
|
||||||
import {getCpuAndLoadForHosts, getLayouts, getAppsForHosts} from '../apis'
|
import {getCpuAndLoadForHosts, getLayouts, getAppsForHosts} from '../apis'
|
||||||
|
import {getEnv} from 'src/shared/apis/env'
|
||||||
|
|
||||||
class HostsPage extends Component {
|
class HostsPage extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -17,48 +19,72 @@ class HostsPage extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
async componentDidMount() {
|
||||||
const {source, addFlashMessage} = this.props
|
const {source, links, addFlashMessage} = this.props
|
||||||
Promise.all([
|
|
||||||
getCpuAndLoadForHosts(source.links.proxy, source.telegraf),
|
const {telegrafSystemInterval} = await getEnv(links.environment)
|
||||||
getLayouts(),
|
|
||||||
new Promise(resolve => {
|
const hostsError = 'Unable to get apps for hosts'
|
||||||
this.setState({hostsLoading: true})
|
let hosts, layouts
|
||||||
resolve()
|
|
||||||
}),
|
try {
|
||||||
])
|
const [h, {data}] = await Promise.all([
|
||||||
.then(([hosts, {data: {layouts}}]) => {
|
getCpuAndLoadForHosts(
|
||||||
this.setState({
|
source.links.proxy,
|
||||||
hosts,
|
source.telegraf,
|
||||||
hostsLoading: false,
|
telegrafSystemInterval
|
||||||
})
|
),
|
||||||
getAppsForHosts(source.links.proxy, hosts, layouts, source.telegraf)
|
getLayouts(),
|
||||||
.then(newHosts => {
|
new Promise(resolve => {
|
||||||
this.setState({
|
this.setState({hostsLoading: true})
|
||||||
hosts: newHosts,
|
resolve()
|
||||||
hostsError: '',
|
}),
|
||||||
hostsLoading: false,
|
])
|
||||||
})
|
|
||||||
})
|
hosts = h
|
||||||
.catch(error => {
|
layouts = data.layouts
|
||||||
console.error(error)
|
|
||||||
const reason = 'Unable to get apps for hosts'
|
this.setState({
|
||||||
addFlashMessage({type: 'error', text: reason})
|
hosts,
|
||||||
this.setState({
|
hostsLoading: false,
|
||||||
hostsError: reason,
|
|
||||||
hostsLoading: false,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.catch(reason => {
|
} catch (error) {
|
||||||
this.setState({
|
this.setState({
|
||||||
hostsError: reason.toString(),
|
hostsError: error.toString(),
|
||||||
hostsLoading: false,
|
hostsLoading: false,
|
||||||
})
|
|
||||||
// TODO: this isn't reachable at the moment, because getCpuAndLoadForHosts doesn't fail when it should.
|
|
||||||
// (like with a bogus proxy link). We should provide better messaging to the user in this catch after that's fixed.
|
|
||||||
console.error(reason) // eslint-disable-line no-console
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hosts || !layouts) {
|
||||||
|
addFlashMessage({type: 'error', text: hostsError})
|
||||||
|
return this.setState({
|
||||||
|
hostsError,
|
||||||
|
hostsLoading: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const newHosts = await getAppsForHosts(
|
||||||
|
source.links.proxy,
|
||||||
|
hosts,
|
||||||
|
layouts,
|
||||||
|
source.telegraf
|
||||||
|
)
|
||||||
|
this.setState({
|
||||||
|
hosts: newHosts,
|
||||||
|
hostsError: '',
|
||||||
|
hostsLoading: false,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
addFlashMessage({type: 'error', text: hostsError})
|
||||||
|
this.setState({
|
||||||
|
hostsError,
|
||||||
|
hostsLoading: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -97,6 +123,12 @@ class HostsPage extends Component {
|
||||||
|
|
||||||
const {func, shape, string} = PropTypes
|
const {func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
const mapStateToProps = ({links}) => {
|
||||||
|
return {
|
||||||
|
links,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HostsPage.propTypes = {
|
HostsPage.propTypes = {
|
||||||
source: shape({
|
source: shape({
|
||||||
id: string.isRequired,
|
id: string.isRequired,
|
||||||
|
@ -107,7 +139,10 @@ HostsPage.propTypes = {
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
telegraf: string.isRequired,
|
telegraf: string.isRequired,
|
||||||
}),
|
}),
|
||||||
|
links: shape({
|
||||||
|
environment: string.isRequired,
|
||||||
|
}),
|
||||||
addFlashMessage: func,
|
addFlashMessage: func,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HostsPage
|
export default connect(mapStateToProps, null)(HostsPage)
|
||||||
|
|
|
@ -61,13 +61,15 @@ export const getMeAsync = ({shouldResetMe = false} = {}) => async dispatch => {
|
||||||
const {
|
const {
|
||||||
data: me,
|
data: me,
|
||||||
auth,
|
auth,
|
||||||
logoutLink,
|
|
||||||
external,
|
|
||||||
users,
|
users,
|
||||||
organizations,
|
|
||||||
meLink,
|
meLink,
|
||||||
config,
|
config,
|
||||||
|
external,
|
||||||
|
logoutLink,
|
||||||
|
organizations,
|
||||||
|
environment,
|
||||||
} = await getMeAJAX()
|
} = await getMeAJAX()
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
meGetCompleted({
|
meGetCompleted({
|
||||||
me,
|
me,
|
||||||
|
@ -75,8 +77,16 @@ export const getMeAsync = ({shouldResetMe = false} = {}) => async dispatch => {
|
||||||
logoutLink,
|
logoutLink,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
linksReceived({external, users, organizations, me: meLink, config})
|
linksReceived({
|
||||||
|
external,
|
||||||
|
users,
|
||||||
|
organizations,
|
||||||
|
me: meLink,
|
||||||
|
config,
|
||||||
|
environment,
|
||||||
|
})
|
||||||
) // TODO: put this before meGetCompleted... though for some reason it doesn't fire the first time then
|
) // TODO: put this before meGetCompleted... though for some reason it doesn't fire the first time then
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(meGetFailed())
|
dispatch(meGetFailed())
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import AJAX from 'src/utils/ajax'
|
||||||
|
|
||||||
|
const DEFAULT_ENVS = {
|
||||||
|
telegrafSystemInterval: '1m',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getEnv = async url => {
|
||||||
|
try {
|
||||||
|
const {data} = await AJAX({
|
||||||
|
method: 'GET',
|
||||||
|
url,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error retreieving envs: ', error)
|
||||||
|
return DEFAULT_ENVS
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,9 @@ const generateResponseWithLinks = (response, newLinks) => {
|
||||||
organizations,
|
organizations,
|
||||||
me: meLink,
|
me: meLink,
|
||||||
config,
|
config,
|
||||||
|
environment,
|
||||||
} = newLinks
|
} = newLinks
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...response,
|
...response,
|
||||||
auth: {links: auth},
|
auth: {links: auth},
|
||||||
|
@ -28,6 +30,7 @@ const generateResponseWithLinks = (response, newLinks) => {
|
||||||
organizations,
|
organizations,
|
||||||
meLink,
|
meLink,
|
||||||
config,
|
config,
|
||||||
|
environment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue