Skip to content

Commit

Permalink
ui: Make sure we pass the nspace through to the API for nodes (#9488)
Browse files Browse the repository at this point in the history
Nodes themselves are not namespaced, so we'd originally assumed we did not need to pass through the ns query parameter when listing or viewing nodes.

As it turns out the API endpoints we use to list and view nodes (and related things) return things that are namespaced, therefore any API requests for nodes do require a the ns query parameter to be passed through to the request.

This PR adds the necessary ns query param to all things Node, apart from the querying for the leader which only returns node related information.
  • Loading branch information
johncowen authored Jan 5, 2021
1 parent 0d4b710 commit af335e7
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 25 deletions.
3 changes: 3 additions & 0 deletions .changelog/9488.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
ui: ensure namespace is used for node API requests
```
22 changes: 18 additions & 4 deletions ui-v2/app/adapters/node.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import Adapter from './application';
// TODO: Update to use this.formatDatacenter()

// Node and Namespaces are a little strange in that Nodes don't belong in a
// namespace whereas things that belong to a Node do (Health Checks and
// Service Instances). So even though Nodes themselves don't require a
// namespace filter, you sill needs to pass the namespace through to API
// requests in order to get the correct information for the things that belong
// to the node.

export default Adapter.extend({
requestForQuery: function(request, { dc, index, id, uri }) {
requestForQuery: function(request, { dc, ns, index, id, uri }) {
return request`
GET /v1/internal/ui/nodes?${{ dc }}
X-Request-ID: ${uri}
${{ index }}
${{
...this.formatNspace(ns),
index,
}}
`;
},
requestForQueryRecord: function(request, { dc, index, id, uri }) {
requestForQueryRecord: function(request, { dc, ns, index, id, uri }) {
if (typeof id === 'undefined') {
throw new Error('You must specify an id');
}
return request`
GET /v1/internal/ui/node/${id}?${{ dc }}
X-Request-ID: ${uri}
${{ index }}
${{
...this.formatNspace(ns),
index,
}}
`;
},
requestForQueryLeader: function(request, { dc }) {
Expand Down
2 changes: 1 addition & 1 deletion ui-v2/app/routes/dc/nodes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default Route.extend({
},
model: function(params) {
const dc = this.modelFor('dc').dc.Name;
const nspace = '*';
const nspace = this.modelFor('nspace').nspace.substr(1);
return hash({
items: this.data.source(uri => uri`/${nspace}/${dc}/nodes`),
leader: this.repo.findByLeader(dc),
Expand Down
4 changes: 2 additions & 2 deletions ui-v2/tests/acceptance/page-navigation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Feature: page-navigation
Where:
-------------------------------------------------------------------------------------
| Link | URL | Endpoint |
| nodes | /dc-1/nodes | /v1/internal/ui/nodes?dc=dc-1 |
| nodes | /dc-1/nodes | /v1/internal/ui/nodes?dc=dc-1&ns=@namespace |
| kvs | /dc-1/kv | /v1/kv/?keys&dc=dc-1&separator=%2F&ns=@namespace |
| acls | /dc-1/acls/tokens | /v1/acl/tokens?dc=dc-1&ns=@namespace |
| intentions | /dc-1/intentions | /v1/connect/intentions?dc=dc-1 |
Expand Down Expand Up @@ -58,7 +58,7 @@ Feature: page-navigation
---
- /v1/catalog/datacenters
- /v1/namespaces
- /v1/internal/ui/node/node-0?dc=dc-1
- /v1/internal/ui/node/node-0?dc=dc-1&ns=@namespace
- /v1/coordinate/nodes?dc=dc-1
- /v1/session/node/node-0?dc=dc-1&ns=@namespace
---
Expand Down
50 changes: 32 additions & 18 deletions ui-v2/tests/integration/adapters/node-test.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { env } from '../../../env';
const shouldHaveNspace = function(nspace) {
return typeof nspace !== 'undefined' && env('CONSUL_NSPACES_ENABLED');
};
module('Integration | Adapter | node', function(hooks) {
setupTest(hooks);
const dc = 'dc-1';
const id = 'node-name';
test('requestForQuery returns the correct url', function(assert) {
const adapter = this.owner.lookup('adapter:node');
const client = this.owner.lookup('service:client/http');
const expected = `GET /v1/internal/ui/nodes?dc=${dc}`;
const actual = adapter.requestForQuery(client.requestParams.bind(client), {
dc: dc,
const undefinedNspace = 'default';
[undefinedNspace, 'team-1', undefined].forEach(nspace => {
test(`requestForQuery returns the correct url when nspace is ${nspace}`, function(assert) {
const adapter = this.owner.lookup('adapter:node');
const client = this.owner.lookup('service:client/http');
const expected = `GET /v1/internal/ui/nodes?dc=${dc}${
shouldHaveNspace(nspace) ? `&ns=${nspace}` : ``
}`;
const actual = adapter.requestForQuery(client.requestParams.bind(client), {
dc: dc,
ns: nspace,
});
assert.equal(`${actual.method} ${actual.url}`, expected);
});
assert.equal(`${actual.method} ${actual.url}`, expected);
});
test('requestForQueryRecord returns the correct url', function(assert) {
const adapter = this.owner.lookup('adapter:node');
const client = this.owner.lookup('service:client/http');
const expected = `GET /v1/internal/ui/node/${id}?dc=${dc}`;
const actual = adapter.requestForQueryRecord(client.requestParams.bind(client), {
dc: dc,
id: id,
test(`requestForQueryRecord returns the correct url when the nspace is ${nspace}`, function(assert) {
const adapter = this.owner.lookup('adapter:node');
const client = this.owner.lookup('service:client/http');
const expected = `GET /v1/internal/ui/node/${id}?dc=${dc}${
shouldHaveNspace(nspace) ? `&ns=${nspace}` : ``
}`;
const actual = adapter.requestForQueryRecord(client.requestParams.bind(client), {
dc: dc,
id: id,
ns: nspace,
});
assert.equal(`${actual.method} ${actual.url}`, expected);
});
assert.equal(`${actual.method} ${actual.url}`, expected);
});
// the following don't require nspacing
test("requestForQueryRecord throws if you don't specify an id", function(assert) {
const adapter = this.owner.lookup('adapter:node');
const client = this.owner.lookup('service:client/http');
Expand All @@ -36,9 +50,9 @@ module('Integration | Adapter | node', function(hooks) {
const adapter = this.owner.lookup('adapter:node');
const client = this.owner.lookup('service:client/http');
const expected = `GET /v1/status/leader?dc=${dc}`;
const actual = adapter.requestForQueryLeader(client.url, {
const actual = adapter.requestForQueryLeader(client.requestParams.bind(client), {
dc: dc,
});
assert.equal(actual, expected);
assert.equal(`${actual.method} ${actual.url}`, expected);
});
});

0 comments on commit af335e7

Please sign in to comment.