-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sidebranch: address transition issues on replication engine and actions #9010
Changes from 19 commits
e06d8e5
a9e20c6
9b9837d
3de1634
35f910c
c07e81a
4b6e19a
60d9fec
b4fce6d
fc38bba
99be007
96cd6e1
1c53f95
6cecbbf
ee3ea14
1c7a824
ab4365a
4c126bb
921118c
8ce3d2c
ef8d19e
0b10c7b
988f54a
280b8b5
a3636c5
03eed54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,16 +88,10 @@ export default Mixin.create({ | |
if (action === 'disable') { | ||
yield this.onDisable(); | ||
} | ||
if (mode === 'secondary' && replicationMode === 'dr') { | ||
Monkeychip marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when you say 'this method is not called', do you mean that we never hit this conditional and execute line 94 if we're on the vault.cluster.replication.mode.index? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We hit the conditional, but because it can't find the method 'onEnable' it just stops. There is some refactoring here that could help, but onEnable is used by a lot of the actions I wasn't dealing with so I just added a comment as it's a gotchya when trying to problem solve. |
||
yield this.onEnable(replicationMode, mode); | ||
} | ||
}).drop(), | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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"}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because we are using peekRecord, this was causing a console error. I can't exactly explain why the peekRecord now adds a vault.cluster.replication to the link to helper here, but it does. Here was the error, you can see the link-to is trying to hit vault.cluster.replication.vault.cluster.replication.mode.index There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👏 |
||
{{#link-to "mode.index" cluster.name mode class="button is-primary"}} | ||
Enable | ||
{{/link-to}} | ||
{{else}} | ||
|
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=replicationMode | ||
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> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
|
@@ -16,10 +15,13 @@ const DEFAULTS = { | |
primary_cluster_addr: null, | ||
ca_file: null, | ||
ca_path: null, | ||
replicationMode: 'dr', | ||
}; | ||
|
||
export default Component.extend(ReplicationActions, DEFAULTS, { | ||
replicationMode: 'dr', | ||
mode: 'primary', | ||
auth: service(), | ||
store: service(), | ||
wizard: service(), | ||
version: service(), | ||
didReceiveAttrs() { | ||
|
@@ -32,9 +34,13 @@ export default Component.extend(ReplicationActions, DEFAULTS, { | |
showModeSummary: false, | ||
initialReplicationMode: null, | ||
cluster: null, | ||
|
||
replicationAttrs: alias('cluster.replicationAttrs'), | ||
|
||
activeCluster: computed('auth.activeCluster', function() { | ||
return this.get('store').peekRecord('cluster', this.get('auth.activeCluster')); | ||
}), | ||
// activeCluster uses peekRecord which watches for changes in cluster data record | ||
replicationAttrs: computed('activeCluster', function() { | ||
return this.activeCluster.replicationAttrs; | ||
}), | ||
tokenIncludesAPIAddr: computed('token', function() { | ||
const config = decodeConfigFromJWT(get(this, 'token')); | ||
return config && config.addr ? true : false; | ||
|
@@ -66,24 +72,13 @@ export default Component.extend(ReplicationActions, DEFAULTS, { | |
this.setProperties(DEFAULTS); | ||
}, | ||
|
||
transitionTo: computed('mode', 'replicationMode', function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had originally created this to handle DR secondary transition issues, but this is being reverted to how it is in master, and the transition conditions are handled in the controller/replication-mode.js |
||
// 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); | ||
|
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love arbitrary timeouts, but I trust you that this was necessary. For diligence: is there a way to kick this off after the other thing has finished from the index route? Looks like it does the transition fine when the mode is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It has everything to do with hitting the model on the route it's transitioning to. For DR it's not transitioning to the same route, only in this specific case (Enabling a Performance Secondary) does it follow this flow: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i was thinking about this too -- an arbitrary timeout feels like it could have the potential to be flaky. i know you have tried many ideas, but have you considered moving the fetch for
i'm not super confident it this, but technically we are trying to compute the capabilities after the model hook returns the vault cluster with replication enabled, so it might fit. 🤷♀️ https://guides.emberjs.com/release/routing/controllers/#toc_where-and-when-to-use-controllers i'm not sure, but some guidance from others would be helpful here too -- @meirish, @DingoEatingFuzz, or @johncowen, do any of you have advice for us on how to ensure a network request in the model doesn't happen until the model is already "ready"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not having looked massively at this code yet, my question would be: What's the 'signal' so you know when this is 'ready'? It sounds like there isn't one?
So a follow up question would be, whilst potentially horrible, is there something you could poll so you know when this is 'ready'? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm yeah that's tricky - I'd expect replication status or cluster status to tell you if it's bootstrapping (or some other status as it's changing). Alternatively does every request return a 40x error? If so you could poll until you don't get 40x's (not great, but more of signal like John mentioned). Or even poll the capabilities-self endpoint and catch the errors until it doesn't return one. |
||
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'); | ||
} | ||
if (replicationMode === 'dr') { | ||
return this.transitionToRoute('mode', replicationMode); | ||
} | ||
this.waitForNewClusterToInit.perform(replicationMode); | ||
Monkeychip marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
onDisable() { | ||
return this.transitionToRoute('index'); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,23 @@ | ||
{{#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"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just added section and div to file so it wouldn't span the whole width while waiting to load. |
||
<div class="container is-widescreen"> | ||
{{#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}} | ||
</div> | ||
</section> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This separates out a specific property for the mode displayed in the Header. We needed one that wasn't also moonlighting for a property from the URL (e.g. modeForUrl).
