mirror of https://github.com/status-im/consul.git
ui: Metrics - Provide a fetch-like http client that automatically adds the current ACL token (#9094)
* Remove local httpGet and shim one in from options * Add custom httpGet to pass through to provider * Make a fetch wrapper that adds your token * Pass the fetch like fetchWithToken wrapper through to the provider * Fix up httpGet to encode query params again and use fetch-like
This commit is contained in:
parent
1a5d4cfe43
commit
0f6c0a5c13
|
@ -152,6 +152,17 @@ export default Service.extend({
|
||||||
params.headers[CONTENT_TYPE] = 'application/json; charset=utf-8';
|
params.headers[CONTENT_TYPE] = 'application/json; charset=utf-8';
|
||||||
return params;
|
return params;
|
||||||
},
|
},
|
||||||
|
fetchWithToken: function(path, params) {
|
||||||
|
return this.settings.findBySlug('token').then(token => {
|
||||||
|
return fetch(`${path}`, {
|
||||||
|
...params,
|
||||||
|
headers: {
|
||||||
|
'X-Consul-Token': typeof token.SecretID === 'undefined' ? '' : token.SecretID,
|
||||||
|
...params.headers,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
request: function(cb) {
|
request: function(cb) {
|
||||||
const client = this;
|
const client = this;
|
||||||
return cb(function(strs, ...values) {
|
return cb(function(strs, ...values) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ const meta = {
|
||||||
|
|
||||||
export default RepositoryService.extend({
|
export default RepositoryService.extend({
|
||||||
cfg: service('ui-config'),
|
cfg: service('ui-config'),
|
||||||
|
client: service('client/http'),
|
||||||
error: null,
|
error: null,
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
|
@ -20,6 +21,9 @@ export default RepositoryService.extend({
|
||||||
// JSON options the user provided.
|
// JSON options the user provided.
|
||||||
const opts = uiCfg.metrics_provider_options || {};
|
const opts = uiCfg.metrics_provider_options || {};
|
||||||
opts.metrics_proxy_enabled = uiCfg.metrics_proxy_enabled;
|
opts.metrics_proxy_enabled = uiCfg.metrics_proxy_enabled;
|
||||||
|
// Inject a convenience function for dialing through the metrics proxy.
|
||||||
|
opts.fetch = (path, params) =>
|
||||||
|
this.client.fetchWithToken(`/v1/internal/ui/metrics-proxy${path}`, params);
|
||||||
// Inject the base app URL
|
// Inject the base app URL
|
||||||
const provider = uiCfg.metrics_provider || 'prometheus';
|
const provider = uiCfg.metrics_provider || 'prometheus';
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,14 @@
|
||||||
* options.providerOptions contains any operator configured parameters
|
* options.providerOptions contains any operator configured parameters
|
||||||
* specified in the Consul agent config that is serving the UI.
|
* specified in the Consul agent config that is serving the UI.
|
||||||
*
|
*
|
||||||
* Consul will provider a boolean options.metrics_proxy_enabled to indicate
|
* Consul will provide:
|
||||||
* whether the agent has a metrics proxy configured.
|
*
|
||||||
|
* 1. A boolean options.metrics_proxy_enabled to indicate whether the agent
|
||||||
|
* has a metrics proxy configured.
|
||||||
|
* 2. A fetch-like options.fetch which is a thin fetch wrapper that prefixes
|
||||||
|
* any url with the url of Consul's proxy endpoint and adds your current
|
||||||
|
* Consul ACL token to the request headers. Otherwise it functions like the
|
||||||
|
* browsers native fetch
|
||||||
*
|
*
|
||||||
* The provider should throw an Exception if the options are not valid for
|
* The provider should throw an Exception if the options are not valid for
|
||||||
* example because it requires a metrics proxy and one is not configured.
|
* example because it requires a metrics proxy and one is not configured.
|
||||||
|
@ -24,6 +30,34 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// simple httpGet function that also encodes query parameters
|
||||||
|
// before passing the constructed url through to native fetch
|
||||||
|
// any errors should throw an error with a statusCode property
|
||||||
|
httpGet: function(url, queryParams, headers) {
|
||||||
|
if (queryParams) {
|
||||||
|
var separator = url.indexOf('?') !== -1 ? '&' : '?';
|
||||||
|
var qs = Object.keys(queryParams).
|
||||||
|
map(function(key) {
|
||||||
|
return encodeURIComponent(key) + "=" + encodeURIComponent(queryParams[key]);
|
||||||
|
}).
|
||||||
|
join("&");
|
||||||
|
url = url + separator + qs;
|
||||||
|
}
|
||||||
|
// fetch the url along with any headers
|
||||||
|
return this.options.fetch(url, {headers: headers || {}}).then(
|
||||||
|
function(response) {
|
||||||
|
if(response.ok) {
|
||||||
|
return response.json();
|
||||||
|
} else {
|
||||||
|
// throw a statusCode error if any errors are received
|
||||||
|
var e = new Error('HTTP Error: ' + response.statusText);
|
||||||
|
e.statusCode = response.status;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* serviceRecentSummarySeries should return time series for a recent time
|
* serviceRecentSummarySeries should return time series for a recent time
|
||||||
* period summarizing the usage of the named service in the indicated
|
* period summarizing the usage of the named service in the indicated
|
||||||
|
@ -656,42 +690,6 @@
|
||||||
return this.httpGet("/api/v1/query_range", params)
|
return this.httpGet("/api/v1/query_range", params)
|
||||||
},
|
},
|
||||||
|
|
||||||
httpGet: function(path, params) {
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
var self = this
|
|
||||||
return new Promise(function(resolve, reject){
|
|
||||||
xhr.onreadystatechange = function(){
|
|
||||||
if (xhr.readyState !== 4) return;
|
|
||||||
|
|
||||||
if (xhr.status == 200) {
|
|
||||||
// Attempt to parse response as JSON and return the object
|
|
||||||
var o = JSON.parse(xhr.responseText)
|
|
||||||
resolve(o)
|
|
||||||
}
|
|
||||||
const e = new Error(xhr.statusText);
|
|
||||||
e.statusCode = xhr.status;
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = self.baseURL()+path;
|
|
||||||
if (params) {
|
|
||||||
var qs = Object.keys(params).
|
|
||||||
map(function(key){
|
|
||||||
return encodeURIComponent(key)+"="+encodeURIComponent(params[key])
|
|
||||||
}).
|
|
||||||
join("&")
|
|
||||||
url = url+"?"+qs
|
|
||||||
}
|
|
||||||
xhr.open("GET", url, true);
|
|
||||||
xhr.send();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
baseURL: function() {
|
|
||||||
// TODO support configuring a direct Prometheus via
|
|
||||||
// metrics_provider_options_json.
|
|
||||||
return "/v1/internal/ui/metrics-proxy"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
|
|
Loading…
Reference in New Issue