ui: Enable recovery from an unreachable datacenter (500 error) (#7404)

For URL maintenance reasons we store the last visited DC in
localStorage incase you come back to a page (for example settings) that
doesn't have a dc in the URL.

A problem arises here if the last DC you tried to visit is unreachable.

The first fix here clears out the last visited DC from localStorage if
the API has errored out.

Secondly, our `href-mut` helper which mutates the current current and
replaces 'parts' in the URL rather than the whole thing functioned by
detecting the current route/URL you are on an 'mutating' that. A problem
arose here as even though you might be on the `/ui/dc-1/services` URL the
actual route is the 'error' route which does not have a URL that can be
changed properly.

The second fix here uses route.currentRoute.name over route.currentRouteName.

The latter is equal to error when an error occurs whereas the former gives you the name of the route before the error happened, which is actually what we want/the intent here.

ie. when `router.currentRouteName === 'error'` then
`router.currentRoute.name === Name Of Route Before It Errored` it seems
This commit is contained in:
John Cowen 2020-03-09 09:10:47 +00:00 committed by GitHub
parent c2b5edf805
commit 40e632a955
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 4 deletions

View file

@ -22,7 +22,7 @@ export default Helper.extend({
atts = atts.concat(getRouteParams(parent, params)); atts = atts.concat(getRouteParams(parent, params));
current = parent; current = parent;
} }
let route = this.router.currentRouteName; let route = this.router.currentRoute.name;
// TODO: this is specific to consul/nspaces // TODO: this is specific to consul/nspaces
// 'ideally' we could try and do this elsewhere // 'ideally' we could try and do this elsewhere
// not super important though. // not super important though.

View file

@ -51,6 +51,8 @@ export default Route.extend(WithBlockingActions, {
error = e.errors[0]; error = e.errors[0];
error.message = error.title || error.detail || 'Error'; error.message = error.title || error.detail || 'Error';
} }
// Try and get the currently attempted dc, whereever that may be
const model = this.modelFor('dc') || this.modelFor('nspace.dc');
// TODO: Unfortunately ember will not maintain the correct URL // TODO: Unfortunately ember will not maintain the correct URL
// for you i.e. when this happens the URL in your browser location bar // for you i.e. when this happens the URL in your browser location bar
// will be the URL where you clicked on the link to come here // will be the URL where you clicked on the link to come here
@ -62,7 +64,6 @@ export default Route.extend(WithBlockingActions, {
// 403 page // 403 page
// To note: Consul only gives you back a 403 if a non-existent token has been sent in the header // To note: Consul only gives you back a 403 if a non-existent token has been sent in the header
// if a token has not been sent at all, it just gives you a 200 with an empty dataset // if a token has not been sent at all, it just gives you a 200 with an empty dataset
const model = this.modelFor('dc');
if (error.status === '403') { if (error.status === '403') {
return this.feedback.execute(() => { return this.feedback.execute(() => {
return this.settings.delete('token').then(() => { return this.settings.delete('token').then(() => {
@ -85,7 +86,8 @@ export default Route.extend(WithBlockingActions, {
: { Name: 'Error' }, : { Name: 'Error' },
dcs: model && model.dcs ? model.dcs : [], dcs: model && model.dcs ? model.dcs : [],
}) })
.then(model => { .then(model => Promise.all([model, this.repo.clearActive()]))
.then(([model]) => {
removeLoading($root); removeLoading($root);
model.nspaces = [model.nspace]; model.nspaces = [model.nspace];
// we can't use setupController as we received an error // we can't use setupController as we received an error

View file

@ -43,4 +43,7 @@ export default RepositoryService.extend({
} }
); );
}, },
clearActive: function() {
return this.settings.delete('dc');
},
}); });

View file

@ -15,7 +15,7 @@
You may have visited a URL that is loading an unknown resource, so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs.<br /> You may have visited a URL that is loading an unknown resource, so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs.<br />
Try looking in our <a href="{{env 'CONSUL_DOCS_URL'}}" target="_blank">documentation</a> Try looking in our <a href="{{env 'CONSUL_DOCS_URL'}}" target="_blank">documentation</a>
</p> </p>
<a rel="home" href={{href-to 'index'}}>Go back to root</a> <a data-test-home rel="home" href={{href-to 'index'}}>Go back to root</a>
{{/block-slot}} {{/block-slot}}
{{/app-view}} {{/app-view}}
{{/hashicorp-consul}} {{/hashicorp-consul}}

View file

@ -0,0 +1,26 @@
@setupApplicationTest
Feature: dc / error: Recovering from a dc 500 error
Background:
Given 2 datacenter models from yaml
---
- dc-1
- dc-500
---
And 3 service models
And the url "/v1/internal/ui/services" responds with a 500 status
When I visit the services page for yaml
---
dc: dc-500
---
Then the url should be /dc-500/services
And the title should be "Consul"
Then I see the text "500 (The backend responded with an error)" in "[data-test-error]"
Scenario: Clicking the back to root button
Given the url "/v1/internal/ui/services" responds with a 200 status
When I click home
Then I see 3 service models
Scenario: Choosing a different dc from the dc menu
Given the url "/v1/internal/ui/services" responds with a 200 status
When I click dc on the navigation
And I click dcs.0.name
Then I see 3 service models

View file

@ -0,0 +1,10 @@
import steps from '../steps';
// step definitions that are shared between features should be moved to the
// tests/acceptance/steps/steps.js file
export default function(assert) {
return steps(assert).then('I should find a file', function() {
assert.ok(true, this.step);
});
}

View file

@ -11,5 +11,6 @@ export default function(visitable, clickable, attribute, collection, page, filte
}), }),
navigation: page.navigation, navigation: page.navigation,
filter: filter, filter: filter,
home: clickable('[data-test-home]'),
}; };
} }