-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
223 additions
and
2 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: show site-wide banners for license warnings if applicable | ||
``` |
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,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()); | ||
} | ||
} |
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 |
---|---|---|
|
@@ -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 | ||
|
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 @@ | ||
.license-banner-wrapper { | ||
width: 100%; | ||
max-width: 1344px; | ||
margin: $spacing-l auto 0; | ||
padding: 0 1.5rem; | ||
} |
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 |
---|---|---|
|
@@ -132,3 +132,7 @@ | |
.has-text-highlight { | ||
color: $yellow-500; | ||
} | ||
|
||
.message.message-marginless { | ||
margin: 0; | ||
} |
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 @@ | ||
{{#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}} |
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
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,87 @@ | ||
import { module, test } from 'qunit'; | ||
import { visit } from '@ember/test-helpers'; | ||
import { setupApplicationTest } from 'ember-qunit'; | ||
import Pretender from 'pretender'; | ||
import formatRFC3339 from 'date-fns/formatRFC3339'; | ||
import { addDays, subDays } from 'date-fns'; | ||
|
||
const generateHealthResponse = state => { | ||
let expiry; | ||
switch (state) { | ||
case 'expired': | ||
expiry = subDays(new Date(), 2); | ||
break; | ||
case 'expiring': | ||
expiry = addDays(new Date(), 10); | ||
break; | ||
default: | ||
expiry = addDays(new Date(), 33); | ||
break; | ||
} | ||
return { | ||
initialized: true, | ||
sealed: false, | ||
standby: false, | ||
license: { | ||
expiry: formatRFC3339(expiry), | ||
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, | ||
}; | ||
}; | ||
|
||
module('Acceptance | Enterprise | License banner warnings', function(hooks) { | ||
setupApplicationTest(hooks); | ||
|
||
test('it shows no license banner if license expires in > 30 days', async function(assert) { | ||
const healthResp = generateHealthResponse(); | ||
this.server = new Pretender(function() { | ||
this.get('/v1/sys/health', response => { | ||
return [response, { 'Content-Type': 'application/json' }, JSON.stringify(healthResp)]; | ||
}); | ||
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough); | ||
// this.get('/v1/sys/health', this.passthrough); | ||
this.get('/v1/sys/seal-status', this.passthrough); | ||
this.get('/v1/sys/license/features', this.passthrough); | ||
}); | ||
await visit('/vault/auth'); | ||
assert.dom('[data-test-license-banner]').doesNotExist('license banner does not show'); | ||
this.server.shutdown(); | ||
}); | ||
test('it shows license banner warning if license expires within 30 days', async function(assert) { | ||
const healthResp = generateHealthResponse('expiring'); | ||
this.server = new Pretender(function() { | ||
this.get('/v1/sys/health', response => { | ||
return [response, { 'Content-Type': 'application/json' }, JSON.stringify(healthResp)]; | ||
}); | ||
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough); | ||
this.get('/v1/sys/seal-status', this.passthrough); | ||
this.get('/v1/sys/license/features', this.passthrough); | ||
}); | ||
await visit('/vault/auth'); | ||
assert.dom('[data-test-license-banner-warning]').exists('license warning shows'); | ||
this.server.shutdown(); | ||
}); | ||
|
||
test('it shows license banner alert if license has already expired', async function(assert) { | ||
const healthResp = generateHealthResponse('expired'); | ||
this.server = new Pretender(function() { | ||
this.get('/v1/sys/health', response => { | ||
return [response, { 'Content-Type': 'application/json' }, JSON.stringify(healthResp)]; | ||
}); | ||
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough); | ||
this.get('/v1/sys/seal-status', this.passthrough); | ||
this.get('/v1/sys/license/features', this.passthrough); | ||
}); | ||
await visit('/vault/auth'); | ||
assert.dom('[data-test-license-banner-expired]').exists('expired license message shows'); | ||
this.server.shutdown(); | ||
}); | ||
}); |
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,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'); | ||
}); | ||
}); |