2023-04-10 15:36:59 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) HashiCorp, Inc.
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*/
|
|
|
|
|
2020-10-29 12:46:42 +00:00
|
|
|
import d3Format from 'd3-format';
|
|
|
|
|
2021-03-29 23:16:48 +00:00
|
|
|
import { formatBytes, formatHertz } from 'nomad-ui/utils/units';
|
2020-10-29 12:46:42 +00:00
|
|
|
|
|
|
|
const formatPercent = d3Format.format('+.0%');
|
|
|
|
const sumAggregate = (total, val) => total + val;
|
|
|
|
|
|
|
|
export default class ResourcesDiffs {
|
|
|
|
constructor(model, multiplier, recommendations, excludedRecommendations) {
|
|
|
|
this.model = model;
|
|
|
|
this.multiplier = multiplier;
|
|
|
|
this.recommendations = recommendations;
|
2021-12-28 14:45:20 +00:00
|
|
|
this.excludedRecommendations = excludedRecommendations.filter((r) =>
|
|
|
|
recommendations.includes(r)
|
|
|
|
);
|
2020-10-29 12:46:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get cpu() {
|
|
|
|
const included = this.includedRecommendations.filterBy('resource', 'CPU');
|
|
|
|
const excluded = this.excludedRecommendations.filterBy('resource', 'CPU');
|
|
|
|
|
|
|
|
return new ResourceDiffs(
|
|
|
|
this.model.reservedCPU,
|
|
|
|
'reservedCPU',
|
|
|
|
'MHz',
|
|
|
|
this.multiplier,
|
|
|
|
included,
|
|
|
|
excluded
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get memory() {
|
2021-12-28 16:08:12 +00:00
|
|
|
const included = this.includedRecommendations.filterBy(
|
|
|
|
'resource',
|
|
|
|
'MemoryMB'
|
|
|
|
);
|
|
|
|
const excluded = this.excludedRecommendations.filterBy(
|
|
|
|
'resource',
|
|
|
|
'MemoryMB'
|
|
|
|
);
|
2020-10-29 12:46:42 +00:00
|
|
|
|
|
|
|
return new ResourceDiffs(
|
|
|
|
this.model.reservedMemory,
|
|
|
|
'reservedMemory',
|
|
|
|
'MiB',
|
|
|
|
this.multiplier,
|
|
|
|
included,
|
|
|
|
excluded
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
get includedRecommendations() {
|
2021-12-28 16:08:12 +00:00
|
|
|
return this.recommendations.reject((r) =>
|
|
|
|
this.excludedRecommendations.includes(r)
|
|
|
|
);
|
2020-10-29 12:46:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ResourceDiffs {
|
|
|
|
constructor(
|
|
|
|
base,
|
|
|
|
baseTaskPropertyName,
|
|
|
|
units,
|
|
|
|
multiplier,
|
|
|
|
includedRecommendations,
|
|
|
|
excludedRecommendations
|
|
|
|
) {
|
|
|
|
this.base = base;
|
|
|
|
this.baseTaskPropertyName = baseTaskPropertyName;
|
|
|
|
this.units = units;
|
|
|
|
this.multiplier = multiplier;
|
|
|
|
this.included = includedRecommendations;
|
|
|
|
this.excluded = excludedRecommendations;
|
|
|
|
}
|
|
|
|
|
|
|
|
get recommended() {
|
|
|
|
if (this.included.length) {
|
|
|
|
return (
|
|
|
|
this.included.mapBy('value').reduce(sumAggregate, 0) +
|
2021-12-28 16:08:12 +00:00
|
|
|
this.excluded
|
|
|
|
.mapBy(`task.${this.baseTaskPropertyName}`)
|
|
|
|
.reduce(sumAggregate, 0)
|
2020-10-29 12:46:42 +00:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return this.base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get delta() {
|
|
|
|
return this.recommended - this.base;
|
|
|
|
}
|
|
|
|
|
|
|
|
get aggregateDiff() {
|
|
|
|
return this.delta * this.multiplier;
|
|
|
|
}
|
|
|
|
|
|
|
|
get absoluteAggregateDiff() {
|
|
|
|
const delta = Math.abs(this.aggregateDiff);
|
|
|
|
|
|
|
|
if (this.units === 'MiB') {
|
2021-03-29 23:16:48 +00:00
|
|
|
return formatBytes(delta, 'MiB');
|
|
|
|
} else if (this.units === 'MHz') {
|
|
|
|
return formatHertz(delta, 'MHz');
|
2020-10-29 12:46:42 +00:00
|
|
|
} else {
|
|
|
|
return `${delta} ${this.units}`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get signedDiff() {
|
|
|
|
const delta = this.aggregateDiff;
|
|
|
|
return `${signForDelta(delta)}${this.absoluteAggregateDiff}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
get percentDiff() {
|
|
|
|
return formatPercent(this.delta / this.base);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function signForDelta(delta) {
|
|
|
|
if (delta > 0) {
|
|
|
|
return '+';
|
|
|
|
} else if (delta < 0) {
|
|
|
|
return '-';
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|