-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4353 from hashicorp/f-ui-node-drain
UI: Node drain and eligibility
- Loading branch information
Showing
15 changed files
with
414 additions
and
20 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,8 @@ | ||
import Helper from '@ember/component/helper'; | ||
import formatDuration from '../utils/format-duration'; | ||
|
||
function formatDurationHelper([duration], { units }) { | ||
return formatDuration(duration, units); | ||
} | ||
|
||
export default Helper.helper(formatDurationHelper); |
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,12 @@ | ||
import { lt, equal } from '@ember/object/computed'; | ||
import attr from 'ember-data/attr'; | ||
import Fragment from 'ember-data-model-fragments/fragment'; | ||
|
||
export default Fragment.extend({ | ||
deadline: attr('number'), | ||
forceDeadline: attr('date'), | ||
ignoreSystemJobs: attr('boolean'), | ||
|
||
isForced: lt('deadline', 0), | ||
hasNoDeadline: equal('deadline', 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 |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { computed } from '@ember/object'; | ||
import { equal } from '@ember/object/computed'; | ||
import Model from 'ember-data/model'; | ||
import attr from 'ember-data/attr'; | ||
import { hasMany } from 'ember-data/relationships'; | ||
|
@@ -11,6 +12,7 @@ export default Model.extend({ | |
name: attr('string'), | ||
datacenter: attr('string'), | ||
isDraining: attr('boolean'), | ||
schedulingEligibility: attr('string'), | ||
status: attr('string'), | ||
statusDescription: attr('string'), | ||
shortId: shortUUIDProperty('id'), | ||
|
@@ -23,6 +25,9 @@ export default Model.extend({ | |
meta: fragment('node-attributes'), | ||
resources: fragment('resources'), | ||
reserved: fragment('resources'), | ||
drainStrategy: fragment('drain-strategy'), | ||
|
||
isEligible: equal('schedulingEligibility', 'eligible'), | ||
|
||
address: computed('httpAddr', function() { | ||
return ipParts(this.get('httpAddr')).address; | ||
|
@@ -52,4 +57,10 @@ export default Model.extend({ | |
unhealthyDriverNames: computed('[email protected]', function() { | ||
return this.get('unhealthyDrivers').mapBy('name'); | ||
}), | ||
|
||
// A status attribute that includes states not included in node status. | ||
// Useful for coloring and sorting nodes | ||
compositeStatus: computed('status', 'isEligible', function() { | ||
return this.get('isEligible') ? this.get('status') : 'ineligible'; | ||
}), | ||
}); |
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,13 @@ | ||
import ApplicationSerializer from './application'; | ||
|
||
export default ApplicationSerializer.extend({ | ||
normalize(typeHash, hash) { | ||
// TODO API: finishedAt is always marshaled as a date even when unset. | ||
// To simplify things, unset it here when it's the empty date value. | ||
if (hash.ForceDeadline === '0001-01-01T00:00:00Z') { | ||
hash.ForceDeadline = null; | ||
} | ||
|
||
return this._super(typeHash, hash); | ||
}, | ||
}); |
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 |
---|---|---|
|
@@ -26,4 +26,8 @@ $size: 0.75em; | |
darken($grey-lighter, 25%) 6px | ||
); | ||
} | ||
|
||
&.ineligible { | ||
background: $warning; | ||
} | ||
} |
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
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,64 @@ | ||
import moment from 'moment'; | ||
|
||
const allUnits = [ | ||
{ name: 'years', suffix: 'year', inMoment: true, pluralizable: true }, | ||
{ name: 'months', suffix: 'month', inMoment: true, pluralizable: true }, | ||
{ name: 'days', suffix: 'day', inMoment: true, pluralizable: true }, | ||
{ name: 'hours', suffix: 'h', inMoment: true, pluralizable: false }, | ||
{ name: 'minutes', suffix: 'm', inMoment: true, pluralizable: false }, | ||
{ name: 'seconds', suffix: 's', inMoment: true, pluralizable: false }, | ||
{ name: 'milliseconds', suffix: 'ms', inMoment: true, pluralizable: false }, | ||
{ name: 'microseconds', suffix: 'µs', inMoment: false, pluralizable: false }, | ||
{ name: 'nanoseconds', suffix: 'ns', inMoment: false, pluralizable: false }, | ||
]; | ||
|
||
export default function formatDuration(duration = 0, units = 'ns') { | ||
const durationParts = {}; | ||
|
||
// Moment only handles up to millisecond precision. | ||
// Microseconds and nanoseconds need to be handled first, | ||
// then Moment can take over for all larger units. | ||
if (units === 'ns') { | ||
durationParts.nanoseconds = duration % 1000; | ||
durationParts.microseconds = Math.floor((duration % 1000000) / 1000); | ||
duration = Math.floor(duration / 1000000); | ||
} else if (units === 'mms') { | ||
durationParts.microseconds = duration % 1000; | ||
duration = Math.floor(duration / 1000); | ||
} | ||
|
||
let momentUnits = units; | ||
if (units === 'ns' || units === 'mms') { | ||
momentUnits = 'ms'; | ||
} | ||
const momentDuration = moment.duration(duration, momentUnits); | ||
|
||
// Get the count of each time unit that Moment handles | ||
allUnits | ||
.filterBy('inMoment') | ||
.mapBy('name') | ||
.forEach(unit => { | ||
durationParts[unit] = momentDuration[unit](); | ||
}); | ||
|
||
// Format each time time bucket as a string | ||
// e.g., { years: 5, seconds: 30 } -> [ '5 years', '30s' ] | ||
const displayParts = allUnits.reduce((parts, unitType) => { | ||
if (durationParts[unitType.name]) { | ||
const count = durationParts[unitType.name]; | ||
const suffix = | ||
count === 1 || !unitType.pluralizable ? unitType.suffix : unitType.suffix.pluralize(); | ||
parts.push(`${count}${unitType.pluralizable ? ' ' : ''}${suffix}`); | ||
} | ||
return parts; | ||
}, []); | ||
|
||
if (displayParts.length) { | ||
return displayParts.join(' '); | ||
} | ||
|
||
// When the duration is 0, show 0 in terms of `units` | ||
const unitTypeForUnits = allUnits.findBy('suffix', units); | ||
const suffix = unitTypeForUnits.pluralizable ? units.pluralize() : units; | ||
return `0${unitTypeForUnits.pluralizable ? ' ' : ''}${suffix}`; | ||
} |
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.