Skip to content
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

UI/license banners #11759

Merged
merged 12 commits into from
Jun 3, 2021
27 changes: 27 additions & 0 deletions ui/app/components/license-banners.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @module LicenseBanners
* LicenseBanners components are used to display Vault-specific license expiry messages
*
* @example
* ```js
* <LicenseBanners @expiry={expiryDate} />
* ```
* @param {string} expiry - RFC3339 date timestamp
*/

import Component from '@glimmer/component';
import isAfter from 'date-fns/isAfter';
import differenceInDays from 'date-fns/differenceInDays';

export default class LicenseBanners extends Component {
get licenseExpired() {
if (!this.args.expiry) return false;
return isAfter(new Date(), new Date(this.args.expiry));
}

get licenseExpiringInDays() {
// Anything more than 30 does not render a warning
if (!this.args.expiry) return 99;
return differenceInDays(new Date(this.args.expiry), new Date());
}
}
5 changes: 5 additions & 0 deletions ui/app/models/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export default Model.extend({
status: attr('string'),
standby: attr('boolean'),
type: attr('string'),
license: attr('object'),

/* Licensing concerns */
licenseExpiry: alias('license.expiry'),
licenseState: alias('license.state'),

needsInit: computed('nodes', '[email protected]', function() {
// needs init if no nodes are initialized
Expand Down
6 changes: 6 additions & 0 deletions ui/app/styles/components/license-banners.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.license-banner-wrapper {
width: 100%;
max-width: 1344px;
margin: $spacing-l auto 0;
padding: 0 1.5rem;
}
1 change: 1 addition & 0 deletions ui/app/styles/core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
@import './components/input-hint';
@import './components/kmip-role-edit';
@import './components/known-secondaries-card.scss';
@import './components/license-banners';
@import './components/linked-block';
@import './components/list-item-row';
@import './components/list-pagination';
Expand Down
3 changes: 3 additions & 0 deletions ui/app/styles/core/helpers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@
.has-top-margin-s {
margin-top: $spacing-s;
}
.has-top-margin-l {
margin-top: $spacing-l;
}
.has-top-margin-xl {
margin-top: $spacing-xl;
}
Expand Down
4 changes: 4 additions & 0 deletions ui/app/styles/core/message.scss
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,7 @@
.has-text-highlight {
color: $yellow-500;
}

.message.message-marginless {
margin: 0;
}
23 changes: 23 additions & 0 deletions ui/app/templates/components/license-banners.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{{#if this.licenseExpired}}
<div class="license-banner-wrapper" data-test-license-banner data-test-license-banner-expired>
<AlertBanner
@type="danger"
@title="License expired"
@message="Your Vault license expired on {{date-format @expiry "MMM d, yyyy"}}. Add a new license to your configuration and restart Vault."
@marginless={{true}}
>
<a href="https://learn.hashicorp.com/tutorials/nomad/hashicorp-enterprise-license" target="_blank" rel="noreferrer noopener">Read documentation</a>
</AlertBanner>
</div>
{{else if (lte this.licenseExpiringInDays 30)}}
<div class="license-banner-wrapper" data-test-license-banner data-test-license-banner-warning>
<AlertBanner
@type="warning"
@title="Vault license expiring"
@message="Your Vault license will expire in {{this.licenseExpiringInDays}} days at {{date-format @expiry "hh:mm:ss a"}} on {{date-format @expiry "MMM d, yyyy"}}. Add a new license to your configuration."
@marginless={{true}}
>
<a href="https://learn.hashicorp.com/tutorials/nomad/hashicorp-enterprise-license" target="_blank" rel="noreferrer noopener">Read documentation</a>
</AlertBanner>
</div>
{{/if}}
1 change: 1 addition & 0 deletions ui/app/templates/vault/cluster.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
</Nav.items>
</NavHeader>
{{/if}}
<LicenseBanners @expiry={{activeCluster.licenseExpiry}} />
<div class="global-flash">
{{#each flashMessages.queue as |flash|}}
{{#flash-message data-test-flash-message=true flash=flash as |customComponent flash close|}}
Expand Down
6 changes: 4 additions & 2 deletions ui/lib/core/addon/components/alert-banner.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ export default Component.extend({
secondIconType: null,
progressBar: null,
yieldWithoutColumn: false,
marginless: false,
classNameBindings: ['containerClass'],

containerClass: computed('type', function() {
return 'message ' + messageTypes([this.type]).class;
containerClass: computed('type', 'marginless', function() {
const base = this.marginless ? 'message message-marginless ' : 'message ';
return base + messageTypes([this.type]).class;
}),

alertType: computed('type', function() {
Expand Down
20 changes: 20 additions & 0 deletions ui/mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,25 @@ export default function() {
};
});

this.get('/sys/health', function() {
return {
initialized: true,
sealed: false,
standby: false,
license: {
expiry: '2021-05-12T23:20:50.52Z',
state: 'stored',
},
performance_standby: false,
replication_performance_mode: 'disabled',
replication_dr_mode: 'disabled',
server_time_utc: 1622562585,
version: '1.9.0+ent',
cluster_name: 'vault-cluster-e779cd7c',
cluster_id: '5f20f5ab-acea-0481-787e-71ec2ff5a60b',
last_wal: 121,
};
});

this.passthrough();
}
39 changes: 39 additions & 0 deletions ui/tests/integration/components/license-banners-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import subDays from 'date-fns/subDays';
import addDays from 'date-fns/addDays';
import formatRFC3339 from 'date-fns/formatRFC3339';

module('Integration | Component | license-banners', function(hooks) {
setupRenderingTest(hooks);

test('it does not render if no expiry', async function(assert) {
await render(hbs`<LicenseBanners />`);
assert.dom('[data-test-license-banner]').doesNotExist('License banner does not render');
});

test('it renders an error if expiry is before now', async function(assert) {
const yesterday = subDays(new Date(), 1);
this.set('expiry', formatRFC3339(yesterday));
await render(hbs`<LicenseBanners @expiry={{expiry}} />`);
assert.dom('[data-test-license-banner-expired]').exists('Expired license banner renders');
assert.dom('.message-title').hasText('License expired', 'Shows correct title on alert');
});

test('it renders a warning if expiry is within 30 days', async function(assert) {
const nextMonth = addDays(new Date(), 30);
this.set('expiry', formatRFC3339(nextMonth));
await render(hbs`<LicenseBanners @expiry={{expiry}} />`);
assert.dom('[data-test-license-banner-warning]').exists('Warning license banner renders');
assert.dom('.message-title').hasText('Vault license expiring', 'Shows correct title on alert');
});

test('it does not render a banner if expiry is outside 30 days', async function(assert) {
const outside30 = addDays(new Date(), 32);
this.set('expiry', formatRFC3339(outside30));
await render(hbs`<LicenseBanners @expiry={{expiry}} />`);
assert.dom('[data-test-license-banner]').doesNotExist('License banner does not render');
});
});