vault/ui/app/models/cluster.js
Vault Automation 0079d343d8
[UI] VAULT-41960 resilience and recovery sidebar (#12056) (#12170)
* VAULT-41960 resiliance and recovery sidebar

* Add breadcrumbs and fix failing tests

* Update link to be external

* Update mode title

* Fix tests

* More tests

* Passing tests!

* Fix sidebar highlight issue

* Update remaining breadcrumbs and fix tests

* Fix recovery tests

* Add resilience and recovery tests

* Sidebar clients rearrangement

* Dasherize and address feedback

* Add copyright headers

* Move to snapshots component for integration test

* Create recovery route file in cluster

* Update ts file and create resilience route

* Remove unused comment

* Add display-nav-item helper

* remove extra nav instantiation

* Add copywrite header

* Address feedback!

* Add more tests!

* Remaining helper tests

* last resilience recovery test

Co-authored-by: Kianna <30884335+kiannaquach@users.noreply.github.com>
2026-02-04 12:06:25 -08:00

115 lines
3.0 KiB
JavaScript

/**
* Copyright IBM Corp. 2016, 2025
* SPDX-License-Identifier: BUSL-1.1
*/
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
import { service } from '@ember/service';
import { get } from '@ember/object';
export default class ClusterModel extends Model {
@service version;
@hasMany('nodes', { async: false, inverse: null }) nodes;
@attr('string') name;
@attr('string') status;
@attr('boolean') standby;
@attr('string') type;
@attr('object') license;
// manually set on response in cluster adapter
@attr('boolean') hasChrootNamespace;
@attr('boolean') replicationRedacted;
/* Licensing concerns */
get licenseExpiry() {
return this.license?.expiry_time;
}
get licenseState() {
return this.license?.state;
}
get needsInit() {
return this.nodes.every((node) => {
return node.initialized === false;
});
}
get unsealed() {
return !!this.nodes.find((node) => {
return node.sealed === false;
});
}
get sealed() {
return !this.unsealed;
}
get leaderNode() {
const nodes = this.nodes;
if (nodes.length === 1) {
return nodes[0];
} else {
return nodes.find((node) => node.isLeader === true);
}
}
get sealThreshold() {
return this.leaderNode?.sealThreshold;
}
get sealProgress() {
return this.leaderNode?.progress;
}
get sealType() {
return this.leaderNode?.type;
}
get storageType() {
return this.leaderNode?.storageType;
}
get hcpLinkStatus() {
return this.leaderNode?.hcpLinkStatus;
}
get hasProgress() {
return this.sealProgress >= 1;
}
get usingRaft() {
return this.storageType === 'raft';
}
//replication mode - will only ever be 'unsupported'
//otherwise the particular mode will have the relevant mode attr through replication-attributes
// eg dr.mode or performance.mode
@attr('string')
mode;
get allReplicationDisabled() {
return this.dr?.replicationDisabled && this.performance?.replicationDisabled;
}
get anyReplicationEnabled() {
return this.dr?.replicationEnabled || this.performance?.replicationEnabled;
}
@belongsTo('replication-attributes', { async: false, inverse: null }) dr;
@belongsTo('replication-attributes', { async: false, inverse: null }) performance;
// this service exposes what mode the UI is currently viewing
// replicationAttrs will then return the relevant `replication-attributes` model
@service('replication-mode') rm;
get drMode() {
return this.dr.mode;
}
get replicationMode() {
return this.rm.mode;
}
get replicationModeForDisplay() {
return this.replicationMode === 'dr' ? 'Disaster recovery' : 'Performance';
}
get replicationIsInitializing() {
// 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;
}
get replicationAttrs() {
const replicationMode = this.replicationMode;
return replicationMode ? get(this, replicationMode) : null;
}
}