mirror of https://github.com/linkerd/linkerd2.git
Tap Web UI: add autocomplete for some authorities (#1409)
Problem: Currently the web UI's resource autocomplete also lists authorities. However you can't tap authorities in this way, you have to use --authority in addition to whatever resource you're trying to tap. The web UI is confusing as it presents authorities in that list. Those authorities should instead be moved to the Authority box in the advanced filter form. Solution: * Don't present authorities as options in the Resource dropdowns * Add authority autocomplete to authority form input Follow up to @kl in #1391 there is an error when we try to tap an authority
This commit is contained in:
parent
4845b4ec04
commit
5d01779dc0
|
@ -41,6 +41,7 @@ class Tap extends React.Component {
|
|||
tapResultsById: {},
|
||||
tapResultFilterOptions: this.getInitialTapFilterOptions(),
|
||||
resourcesByNs: {},
|
||||
authoritiesByNs: {},
|
||||
query: {
|
||||
resource: "",
|
||||
namespace: "",
|
||||
|
@ -57,6 +58,7 @@ class Tap extends React.Component {
|
|||
resource: [],
|
||||
toNamespace: [],
|
||||
toResource: [],
|
||||
authority: []
|
||||
},
|
||||
maxLinesToDisplay: 40,
|
||||
awaitingWebSocketConnection: false,
|
||||
|
@ -131,18 +133,34 @@ class Tap extends React.Component {
|
|||
|
||||
getResourcesByNs(rsp) {
|
||||
let statTables = _.get(rsp, [0, "ok", "statTables"]);
|
||||
return _.reduce(statTables, (mem, table) => {
|
||||
let authoritiesByNs = {};
|
||||
let resourcesByNs = _.reduce(statTables, (mem, table) => {
|
||||
_.map(table.podGroup.rows, row => {
|
||||
if (!mem[row.resource.namespace]) {
|
||||
mem[row.resource.namespace] = [];
|
||||
authoritiesByNs[row.resource.namespace] = [];
|
||||
}
|
||||
|
||||
if (row.resource.type.toLowerCase() !== "service") {
|
||||
switch (row.resource.type.toLowerCase()) {
|
||||
case "service":
|
||||
break;
|
||||
case "authority":
|
||||
authoritiesByNs[row.resource.namespace].push(row.resource.name);
|
||||
break;
|
||||
default:
|
||||
mem[row.resource.namespace].push(`${row.resource.type}/${row.resource.name}`);
|
||||
}
|
||||
});
|
||||
return mem;
|
||||
}, {});
|
||||
return {
|
||||
authoritiesByNs,
|
||||
resourcesByNs
|
||||
};
|
||||
}
|
||||
|
||||
getResourceList(resourcesByNs, ns) {
|
||||
return resourcesByNs[ns] || _.uniq(_.flatten(_.values(resourcesByNs)));
|
||||
}
|
||||
|
||||
parseTapResult = data => {
|
||||
|
@ -307,7 +325,7 @@ class Tap extends React.Component {
|
|||
this.ws.close(1000);
|
||||
}
|
||||
|
||||
handleFormChange = (name, scopeResource) => {
|
||||
handleFormChange = (name, scopeResource, shouldScopeAuthority) => {
|
||||
let state = {
|
||||
query: this.state.query,
|
||||
autocomplete: this.state.autocomplete
|
||||
|
@ -319,6 +337,9 @@ class Tap extends React.Component {
|
|||
// scope the available typeahead resources to the selected namespace
|
||||
state.autocomplete[scopeResource] = this.state.resourcesByNs[formVal];
|
||||
}
|
||||
if (shouldScopeAuthority) {
|
||||
state.autocomplete.authority = this.state.authoritiesByNs[formVal];
|
||||
}
|
||||
|
||||
this.setState(state);
|
||||
};
|
||||
|
@ -354,20 +375,21 @@ class Tap extends React.Component {
|
|||
this.api.setCurrentRequests([this.api.fetchMetrics(url)]);
|
||||
this.serverPromise = Promise.all(this.api.getCurrentPromises())
|
||||
.then(rsp => {
|
||||
let resourcesByNs = this.getResourcesByNs(rsp);
|
||||
let { resourcesByNs, authoritiesByNs } = this.getResourcesByNs(rsp);
|
||||
let namespaces = _.sortBy(_.keys(resourcesByNs));
|
||||
let resourceNames = resourcesByNs[this.state.query.namespace] ||
|
||||
_.uniq(_.flatten(_.values(resourcesByNs)));
|
||||
let toResourceNames = resourcesByNs[this.state.query.toNamespace] ||
|
||||
_.uniq(_.flatten(_.values(resourcesByNs)));
|
||||
let resourceNames = this.getResourceList(resourcesByNs, this.state.query.namespace);
|
||||
let toResourceNames = this.getResourceList(resourcesByNs, this.state.query.toNamespace);
|
||||
let authorities = this.getResourceList(authoritiesByNs, this.state.query.namespace);
|
||||
|
||||
this.setState({
|
||||
resourcesByNs,
|
||||
authoritiesByNs,
|
||||
autocomplete: {
|
||||
namespace: namespaces,
|
||||
resource: resourceNames,
|
||||
toNamespace: namespaces,
|
||||
toResource: toResourceNames
|
||||
toResource: toResourceNames,
|
||||
authority: authorities
|
||||
},
|
||||
pendingRequests: false
|
||||
});
|
||||
|
@ -397,7 +419,7 @@ class Tap extends React.Component {
|
|||
allowClear
|
||||
placeholder="Namespace"
|
||||
optionFilterProp="children"
|
||||
onChange={this.handleFormChange("namespace", "resource")}>
|
||||
onChange={this.handleFormChange("namespace", "resource", true)}>
|
||||
{
|
||||
_.map(this.state.autocomplete.namespace, (n, i) => (
|
||||
<Select.Option key={`ns-dr-${i}`} value={n}>{n}</Select.Option>
|
||||
|
@ -480,7 +502,12 @@ class Tap extends React.Component {
|
|||
<Col span={2 * colSpan}>
|
||||
<Form.Item
|
||||
extra="Display requests with this :authority">
|
||||
<Input placeholder="Authority" onChange={this.handleFormEvent("authority")} />
|
||||
|
||||
<AutoComplete
|
||||
dataSource={this.autoCompleteData("authority")}
|
||||
onSelect={this.handleFormChange("authority")}
|
||||
onSearch={this.handleFormChange("authority")}
|
||||
placeholder="Authority" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
|
|
Loading…
Reference in New Issue