-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ui: Add version diff comparison to KV v2 (#23200)
* add diff route * add version diff toolbar link * finish functionality of version diff comparison * add tests * update empty state message * update selectors * wip tests * finish test * add empty state test * switch dropdowns * add changelog * add comment
- Loading branch information
1 parent
758de87
commit 8375149
Showing
11 changed files
with
342 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:improvement | ||
ui: Move access to KV V2 version diff view to toolbar in Version History | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
ui/lib/kv/addon/components/page/secret/metadata/version-diff.hbs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<KvPageHeader @breadcrumbs={{@breadcrumbs}} @pageTitle="Version Diff"> | ||
<:toolbarFilters> | ||
<span class="has-text-grey has-text-weight-semibold is-size-8">FROM:</span> | ||
<KvVersionDropdown | ||
@displayVersion={{this.leftVersion}} | ||
@metadata={{@metadata}} | ||
@onSelect={{fn this.handleSelect "leftVersion"}} | ||
/> | ||
<span class="has-text-grey has-text-weight-semibold is-size-8">TO:</span> | ||
<KvVersionDropdown | ||
@displayVersion={{this.rightVersion}} | ||
@metadata={{@metadata}} | ||
@onSelect={{fn this.handleSelect "rightVersion"}} | ||
/> | ||
{{#if this.statesMatch}} | ||
<div class="has-left-padding-s"> | ||
<Icon @name="check-circle-fill" class="has-text-success" /> | ||
<span>States match</span> | ||
</div> | ||
{{/if}} | ||
</:toolbarFilters> | ||
</KvPageHeader> | ||
|
||
{{#if this.deactivatedState}} | ||
<EmptyState | ||
@title="Version {{this.rightVersion}} has been {{this.deactivatedState}}" | ||
@message="The current version of this secret has been {{this.deactivatedState}}. Select another version to compare." | ||
/> | ||
{{else}} | ||
<div class="form-section visual-diff text-grey-lightest background-color-black has-top-margin-s"> | ||
<pre data-test-visual-diff>{{sanitized-html this.visualDiff}}</pre> | ||
</div> | ||
{{/if}} |
82 changes: 82 additions & 0 deletions
82
ui/lib/kv/addon/components/page/secret/metadata/version-diff.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/** | ||
* Copyright (c) HashiCorp, Inc. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
|
||
import Component from '@glimmer/component'; | ||
import { action } from '@ember/object'; | ||
import { inject as service } from '@ember/service'; | ||
import { tracked } from '@glimmer/tracking'; | ||
import { kvDataPath } from 'vault/utils/kv-path'; | ||
|
||
/** | ||
* @module KvSecretMetadataVersionDiff renders the version diff comparison | ||
* <Page::Secret::Metadata::VersionDiff | ||
* @metadata={{this.model.metadata}} | ||
* @path={{this.model.path}} | ||
* @backend={{this.model.backend}} | ||
* @breadcrumbs={{this.breadcrumbs}} | ||
* /> | ||
* | ||
* @param {model} metadata - Ember data model: 'kv/metadata' | ||
* @param {string} path - path to request secret data for selected version | ||
* @param {string} backend - kv secret mount to make network request | ||
* @param {array} breadcrumbs - Array to generate breadcrumbs, passed to the page header component | ||
*/ | ||
|
||
/* eslint-disable no-undef */ | ||
export default class KvSecretMetadataVersionDiff extends Component { | ||
@service store; | ||
@tracked leftVersion; | ||
@tracked rightVersion; | ||
@tracked visualDiff; | ||
@tracked statesMatch = false; | ||
|
||
constructor() { | ||
super(...arguments); | ||
|
||
// initialize with most recently (before current), active version on left | ||
const olderVersions = this.args.metadata.sortedVersions.slice(1); | ||
const recentlyActive = olderVersions.find((v) => !v.destroyed && !v.isSecretDeleted); | ||
this.leftVersion = Number(recentlyActive?.version); | ||
this.rightVersion = this.args.metadata.currentVersion; | ||
|
||
// this diff is from older to newer (current) secret data | ||
this.createVisualDiff(); | ||
} | ||
|
||
// this can only be true on initialization if the current version is inactive | ||
// selecting a deleted/destroyed version is otherwise disabled | ||
get deactivatedState() { | ||
const { currentVersion, currentSecret } = this.args.metadata; | ||
return this.rightVersion === currentVersion && currentSecret.isDeactivated ? currentSecret.state : ''; | ||
} | ||
|
||
@action | ||
handleSelect(side, version, actions) { | ||
this[side] = Number(version); | ||
actions.close(); | ||
this.createVisualDiff(); | ||
} | ||
|
||
async createVisualDiff() { | ||
const leftSecretData = await this.fetchSecretData(this.leftVersion); | ||
const rightSecretData = await this.fetchSecretData(this.rightVersion); | ||
const diffpatcher = jsondiffpatch.create({}); | ||
const delta = diffpatcher.diff(leftSecretData, rightSecretData); | ||
|
||
this.statesMatch = !delta; | ||
this.visualDiff = delta | ||
? jsondiffpatch.formatters.html.format(delta, leftSecretData) | ||
: JSON.stringify(rightSecretData, undefined, 2); | ||
} | ||
|
||
async fetchSecretData(version) { | ||
const { backend, path } = this.args; | ||
// check the store first, avoiding an extra network request if possible. | ||
const storeData = await this.store.peekRecord('kv/data', kvDataPath(backend, path, version)); | ||
const data = storeData ? storeData : await this.store.queryRecord('kv/data', { backend, path, version }); | ||
|
||
return data?.secretData; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* Copyright (c) HashiCorp, Inc. | ||
* SPDX-License-Identifier: MPL-2.0 | ||
*/ | ||
|
||
import Route from '@ember/routing/route'; | ||
import { breadcrumbsForSecret } from 'kv/utils/kv-breadcrumbs'; | ||
|
||
export default class KvSecretMetadataDiffRoute extends Route { | ||
// model passed from parent secret route, if we need to access or intercept | ||
// it can retrieved via `this.modelFor('secret'), which includes the metadata model. | ||
setupController(controller, resolvedModel) { | ||
super.setupController(controller, resolvedModel); | ||
const breadcrumbsArray = [ | ||
{ label: 'secrets', route: 'secrets', linkExternal: true }, | ||
{ label: resolvedModel.backend, route: 'list' }, | ||
...breadcrumbsForSecret(resolvedModel.path), | ||
{ label: 'version history', route: 'secret.metadata.versions' }, | ||
{ label: 'diff' }, | ||
]; | ||
controller.set('breadcrumbs', breadcrumbsArray); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<Page::Secret::Metadata::VersionDiff | ||
@metadata={{this.model.metadata}} | ||
@path={{this.model.path}} | ||
@backend={{this.model.backend}} | ||
@breadcrumbs={{this.breadcrumbs}} | ||
/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.