Skip to content

Commit

Permalink
Sidebranch: address transition issues on replication engine and actio…
Browse files Browse the repository at this point in the history
…ns (#9010)

* small formatting changes

* change findRecord to peekRecord so it keeps track of the changing data.

* add styling such that when page is loading it does not spread across the whole page

* help with reload and styling on replication route

* initial setup for new flow that handles adding a perf secondary, and also some on a dr secondary

* clean up

* add loader on rep page for situations when data is still loading, and add loading mode in header, seperate from the modeForUrl used in other places to help transistion

* fix transitionTo when coming from different replication.mode vs replication.index route

* set default of mode for radio checkboxes after removing from DEFAULTS var

* reset and cont using onEnable because TransitionTo is not working inside of component

* remove console

* the reason we were getting transition errors :(

* remove modeObjecT

* fix error by removing peek record from application and moving it lower down in a property replicationAttrs

* Readd back space

* this one really does fix the issue

* add back peek record and add conditional to isLoadingData

* figure out cluster id from service instead of hardcoded

* fix capabilities-self error by adding a 1 sceond delay for when transition from replication.index to replication.mode.index on enable performance secondary

* remove attempt to circumvent the peekRecord in application

* add to replication page tests and clarify replicationMode to formattedReplicationMode, it's super confusing when seeing replicationMode being duplicated throughout the computed components.  this clarifies its computed only for formatting

* fix repetive conditional

* capture the state when either dr.mode or performance.mode are undefined, which happens during a transition.  If this is the case add a loader on the replicationindex page.

* address some pr comments

* small change

* add bootstrapping mode to test
  • Loading branch information
Monkeychip committed May 21, 2020
1 parent dd81d58 commit 83c8944
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 128 deletions.
5 changes: 5 additions & 0 deletions ui/app/models/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ export default DS.Model.extend({
// replicationAttrs will then return the relevant `replication-attributes` fragment
rm: service('replication-mode'),
replicationMode: alias('rm.mode'),
replicationIsInitializing: computed('dr.mode', 'performance.mode', function() {
// a mode of null only happens when a cluster is being initialized
// otherwise the mode will be 'disabled', 'primary', 'secondary'
return !this.dr.mode || !this.performance.mode;
}),
replicationAttrs: computed('dr.mode', 'performance.mode', 'replicationMode', function() {
const replicationMode = this.get('replicationMode');
return replicationMode ? get(this, replicationMode) : null;
Expand Down
8 changes: 8 additions & 0 deletions ui/app/models/replication-attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ export default Fragment.extend({
? 'bootstrapping'
: (this.get('isSecondary') && 'secondary') || (this.get('isPrimary') && 'primary');
}),
modeForHeader: computed('mode', function() {
const mode = this.mode;
if (!mode) {
// mode will be false or undefined if it calls the status endpoint while still setting up the cluster
return 'loading';
}
return mode;
}),
secondaryId: attr('string'),
primaryClusterAddr: attr('string'),
knownPrimaryClusterAddrs: attr('array'),
Expand Down
26 changes: 19 additions & 7 deletions ui/lib/core/addon/components/replication-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export default Component.extend({
layout,
store: service(),
reindexingDetails: null,

didReceiveAttrs() {
this._super(arguments);
this.getReplicationModeStatus.perform();
Expand All @@ -26,20 +25,33 @@ export default Component.extend({
.adapterFor('replication-mode')
.fetchStatus(replicationMode);
} catch (e) {
console.log(e);
// do not handle error
}
this.set('reindexingDetails', resp);
}),
replicationMode: computed('model.{replicationMode}', function() {
formattedReplicationMode: computed('model.{replicationMode}', function() {
// dr or performance 🤯
let mode = this.model.replicationMode;
const mode = this.model.replicationMode;
return MODE[mode];
}),
clusterMode: computed('model.{replicationAttrs}', function() {
// primary or secondary
const { model } = this;
return model.replicationAttrs.mode;
}),
isLoadingData: computed('clusterMode', 'model.{replicationAttrs}', function() {
const { clusterMode } = this;
const { model } = this;
const clusterId = model.replicationAttrs.clusterId;
const replicationDisabled = model.replicationAttrs.replicationDisabled;

if (clusterMode === 'bootstrapping' || (!clusterId && !replicationDisabled)) {
// if clusterMode is bootstrapping
// if no clusterId, the data hasn't loaded yet, wait for another status endpoint to be called
return true;
}
return false;
}),
isSecondary: computed('clusterMode', function() {
const { clusterMode } = this;
return clusterMode === 'secondary';
Expand All @@ -55,10 +67,10 @@ export default Component.extend({
}
return false;
}),
message: computed('model.{anyReplicationEnabled}', 'replicationMode', function() {
message: computed('model.{anyReplicationEnabled}', 'formattedReplicationMode', function() {
if (this.model.anyReplicationEnabled) {
return `This ${this.replicationMode} secondary has not been enabled. You can do so from the ${this.replicationMode} Primary.`;
return `This ${this.formattedReplicationMode} secondary has not been enabled. You can do so from the ${this.formattedReplicationMode} Primary.`;
}
return `This cluster has not been enabled as a ${this.replicationMode} Secondary. You can do so by enabling replication and adding a secondary from the ${this.replicationMode} Primary.`;
return `This cluster has not been enabled as a ${this.formattedReplicationMode} Secondary. You can do so by enabling replication and adding a secondary from the ${this.formattedReplicationMode} Primary.`;
}),
});
12 changes: 3 additions & 9 deletions ui/lib/core/addon/mixins/replication-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,10 @@ export default Mixin.create({
if (action === 'disable') {
yield this.onDisable();
}
if (mode === 'secondary' && replicationMode === 'dr') {
// return mode so you can properly handle the transition
return mode;
}
if (action === 'enable') {
try {
yield this.onEnable(replicationMode); // should not be called for dr secondary
} catch (e) {
// TODO handle error
}
/// onEnable is a method available only to route vault.cluster.replication.index
// if action 'enable' is called from vault.cluster.replication.mode.index this method is not called
yield this.onEnable(replicationMode, mode);
}
}).drop(),

Expand Down
2 changes: 1 addition & 1 deletion ui/lib/core/addon/templates/components/layout-loading.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="is-flex-v-centered is-flex-1 loader-inner-page" >
<div class="is-flex-v-centered is-flex-1 loader-inner-page" data-test-layout-loading>
<div class="columns is-centered">
<div class="column is-narrow has-text-centered has-text-grey-dark has-current-color-fill">
<div class="level is-mobile">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
</div>
<div class="level-right">
{{#if replicationDisabled}}
{{#link-to "vault.cluster.replication.mode.index" cluster.name mode class="button is-primary"}}
{{#link-to "mode.index" cluster.name mode class="button is-primary"}}
Enable
{{/link-to}}
{{else}}
Expand Down
42 changes: 23 additions & 19 deletions ui/lib/core/addon/templates/components/replication-page.hbs
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
<div class="replication-page" data-test-replication-page>
{{yield
(hash
header=(component 'replication-header'
data=model
title=replicationMode
isSecondary=isSecondary
secondaryId=replicationDetails.secondaryId
{{#if isLoadingData }}
<LayoutLoading />
{{else}}
{{yield
(hash
header=(component 'replication-header'
data=model
title=formattedReplicationMode
isSecondary=isSecondary
secondaryId=replicationDetails.secondaryId
)
dashboard=(component
'replication-dashboard'
data=model
isSecondary=isSecondary
replicationDetails=replicationDetails
clusterMode=clusterMode
reindexingDetails=reindexingDetails
)
isDisabled=isDisabled
message=message
)
dashboard=(component
'replication-dashboard'
data=model
isSecondary=isSecondary
replicationDetails=replicationDetails
clusterMode=clusterMode
reindexingDetails=reindexingDetails
)
isDisabled=isDisabled
message=message
)
}}
}}
{{/if}}
</div>
17 changes: 3 additions & 14 deletions ui/lib/replication/addon/components/replication-summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import ReplicationActions from 'core/mixins/replication-actions';
import { task } from 'ember-concurrency';

const DEFAULTS = {
mode: 'primary',
token: null,
id: null,
loading: false,
Expand All @@ -16,10 +15,11 @@ const DEFAULTS = {
primary_cluster_addr: null,
ca_file: null,
ca_path: null,
replicationMode: 'dr',
};

export default Component.extend(ReplicationActions, DEFAULTS, {
replicationMode: 'dr',
mode: 'primary',
wizard: service(),
version: service(),
didReceiveAttrs() {
Expand Down Expand Up @@ -66,24 +66,13 @@ export default Component.extend(ReplicationActions, DEFAULTS, {
this.setProperties(DEFAULTS);
},

transitionTo: computed('mode', 'replicationMode', function() {
// Take transitionTo outside of a yield because it unmounts the cluster and yield cannot return anything
return () => this.router.transitionTo('vault.cluster');
}),

submit: task(function*() {
let mode;
try {
mode = yield this.submitHandler.perform(...arguments);
yield this.submitHandler.perform(...arguments);
} catch (e) {
// TODO handle error
}
// if Secondary, handle transition here, if not, handle transition in mixin Enable
if (mode === 'secondary') {
this.transitionTo();
}
}),

actions: {
onSubmit(/*action, mode, data, event*/) {
this.get('submit').perform(...arguments);
Expand Down
17 changes: 15 additions & 2 deletions ui/lib/replication/addon/controllers/replication-mode.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import Controller from '@ember/controller';
import { task, timeout } from 'ember-concurrency';

export default Controller.extend({
rm: service('replication-mode'),
replicationMode: alias('rm.mode'),
waitForNewClusterToInit: task(function*(replicationMode) {
// waiting for the newly enabled cluster to init
// this ensures we don't hit a capabilities-self error, called in the model of the mode/index route
yield timeout(1000);
return this.transitionToRoute('mode', replicationMode);
}),
actions: {
onEnable(mode) {
return this.transitionToRoute('mode', mode);
onEnable(replicationMode, mode) {
if (replicationMode == 'dr' && mode === 'secondary') {
return this.transitionToRoute('vault.cluster');
} else if (replicationMode === 'dr') {
return this.transitionToRoute('mode', replicationMode);
} else {
this.waitForNewClusterToInit.perform(replicationMode);
}
},
onDisable() {
return this.transitionToRoute('index');
Expand Down
4 changes: 3 additions & 1 deletion ui/lib/replication/addon/routes/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ClusterRoute from 'vault/mixins/cluster-route';
export default Route.extend(ClusterRoute, {
version: service(),
store: service(),
auth: service(),

beforeModel() {
return this.get('version')
Expand All @@ -17,7 +18,8 @@ export default Route.extend(ClusterRoute, {
},

model() {
return this.store.findRecord('cluster', 'vault');
const activeClusterId = this.get('auth.activeCluster');
return this.store.peekRecord('cluster', activeClusterId);
},

afterModel(model) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@
<p>{{cluster.replicationModeStatus.cluster_id}}</p>
<div class="replication">
<ReplicationPage @model={{cluster}} as |Page|>
<Page.dashboard
<Page.dashboard
@data={{cluster}}
@componentToRender={{if (eq replicationAttrs.mode 'secondary') 'replication-secondary-card' 'replication-primary-card' }}
as |Dashboard|>
Expand All @@ -352,7 +352,7 @@
<Dashboard.card
@title='Last WAL entry'
@description='Index of last Write Ahead Logs entry written on local storage.'
@metric={{replicationAttrs.lastWAL}} />
@metric={{format-number replicationAttrs.lastWAL}} />
<Dashboard.secondaryCard
@cluster={{cluster}}
@replicationAttrs={{replicationAttrs}} />
Expand Down
46 changes: 27 additions & 19 deletions ui/lib/replication/addon/templates/index.hbs
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
{{#if (eq model.mode 'unsupported')}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3 has-text-grey">
Replication unsupported
</h1>
</p.levelLeft>
</PageHeader>
<EmptyState
@title="The current cluster configuration does not support replication"
/>
{{else}}
<ReplicationSummary
@cluster={{model}}
@showModeSummary={{true}}
@onEnable={{action "onEnable"}}
@onDisable={{action "onDisable"}}
/>
{{/if}}
<section class="section">
<div class="container is-widescreen">
{{#if model.replicationIsInitializing }}
<LayoutLoading />
{{else}}
{{#if (eq model.mode 'unsupported')}}
<PageHeader as |p|>
<p.levelLeft>
<h1 class="title is-3 has-text-grey">
Replication unsupported
</h1>
</p.levelLeft>
</PageHeader>
<EmptyState
@title="The current cluster configuration does not support replication"
/>
{{else}}
<ReplicationSummary
@cluster={{model}}
@showModeSummary={{true}}
@onEnable={{action "onEnable"}}
@onDisable={{action "onDisable"}}
/>
{{/if}}
{{/if}}
</div>
</section>

0 comments on commit 83c8944

Please sign in to comment.