Skip to content

Commit

Permalink
chore: refactor PodInstancesTable
Browse files Browse the repository at this point in the history
while trying to consolidate implementations for the ServicesTable and the
PodInstancesTable (we'll also later need to have a look at the
ServicesInstancesContainer) these changes emerged.

They help in comprehending what's going on and will be utterly helpful when
fixing the FilterBar on that Table (which has several bugs, as i learned during
this exercise).
  • Loading branch information
pierrebeitz committed Apr 24, 2020
1 parent 5a1ab89 commit 6a8701a
Show file tree
Hide file tree
Showing 19 changed files with 95 additions and 317 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import * as EventTypes from "#SRC/js/constants/EventTypes";
import MesosStateStore from "#SRC/js/stores/MesosStateStore";
import DSLExpression from "#SRC/js/structs/DSLExpression";

import Util from "#SRC/js/utils/Util";

import PodInstanceStatusFilter from "#PLUGINS/services/src/js/filters/PodInstanceStatusFilter";
import PodInstancesZoneFilter from "#PLUGINS/services/src/js/filters/PodInstancesZoneFilter";
import PodInstancesRegionFilter from "#PLUGINS/services/src/js/filters/PodInstancesRegionFilter";
Expand All @@ -34,16 +32,35 @@ class PodInstancesContainer extends React.Component {
static propTypes = {
pod: PropTypes.instanceOf(Pod),
};
constructor(...args) {
super(...args);
constructor(props) {
super(props);

const instances = PodUtil.mergeHistoricalInstanceList(
props.pod.getInstanceList(),
MesosStateStore.getPodHistoricalInstances(props.pod)
).getItems();

const nodes = TaskMergeDataUtil.mergeTaskData(instances).map(
InstanceUtil.getNode
);

this.state = {
actionErrors: {},
lastUpdate: 0,
pendingActions: {},
filterExpression: new DSLExpression(""),
filters: [new PodInstanceStatusFilter(), new PodInstanceTextFilter()],
defaultFilterData: { zones: [], regions: [] },
filterExpression: new DSLExpression(
props?.location?.query?.q || "is:active"
),
filters: [
PodInstanceStatusFilter,
PodInstancesZoneFilter,
PodInstancesRegionFilter,
PodInstanceTextFilter,
],
defaultFilterData: {
regions: nodes.map((i) => i?.getRegionName()).filter(interesting),
zones: nodes.map((i) => i?.getZoneName()).filter(interesting),
},
};
}

Expand All @@ -57,10 +74,6 @@ class PodInstancesContainer extends React.Component {
this.dispatcher = AppDispatcher.register(this.handleServerAction);
}

UNSAFE_componentWillMount() {
this.setFilterOptions(this.props);
}

componentWillUnmount() {
MesosStateStore.removeChangeListener(
EventTypes.MESOS_STATE_CHANGE,
Expand All @@ -71,87 +84,12 @@ class PodInstancesContainer extends React.Component {
}
handleExpressionChange = (filterExpression = { value: "" }) => {
const { router } = this.context;
const {
location: { pathname },
} = this.props;
const { pathname } = this.props.location;
router.push({ pathname, query: { q: filterExpression.value } });

this.setState({ filterExpression });
};

setFilterOptions(props) {
const historicalInstances = MesosStateStore.getPodHistoricalInstances(
props.pod
);

const instances = PodUtil.mergeHistoricalInstanceList(
props.pod.getInstanceList(),
historicalInstances
);

const {
defaultFilterData: { regions, zones },
filterExpression,
} = this.state;

const query =
Util.findNestedPropertyInObject(props, "location.query.q") || "is:active";

const mergedInstances = TaskMergeDataUtil.mergeTaskData(
instances.getItems()
);

const newZones = Object.keys(
mergedInstances.reduce((prev, instance) => {
const node = InstanceUtil.getNode(instance);

if (!node || node.getZoneName() === "N/A") {
return prev;
}
prev[node.getZoneName()] = "";

return prev;
}, {})
);

const newRegions = Object.keys(
mergedInstances.reduce((prev, instance) => {
const node = InstanceUtil.getNode(instance);

if (!node || node.getRegionName() === "N/A") {
return prev;
}
prev[node.getRegionName()] = "";

return prev;
}, {})
);

// If no region/ zones added from props return
if (
newRegions.length === regions.length &&
newRegions.every((region) => regions.indexOf(region) !== -1) &&
newZones.length === zones.length &&
newZones.every((zone) => zones.indexOf(zone) !== -1) &&
filterExpression.value === query
) {
return;
}

const filters = [
new PodInstanceStatusFilter(),
new PodInstancesZoneFilter(newZones),
new PodInstancesRegionFilter(newRegions),
new PodInstanceTextFilter(),
];

this.setState({
filterExpression: new DSLExpression(query),
filters,
defaultFilterData: { regions: newRegions, zones: newZones },
});
}

getChildContext() {
return {
modalHandlers: this.getModalHandlers(),
Expand Down Expand Up @@ -335,6 +273,8 @@ class PodInstancesContainer extends React.Component {
}
}

const interesting = (i) => i && i !== "N/A";

// Make these modal handlers available via context
// so any child can trigger the opening of modals
PodInstancesContainer.childContextTypes = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ class PodInstancesTable extends React.Component {
let containerResources = container.getResources();

// TODO: Remove the following 4 lines when DCOS-10098 is addressed
const containerSpec = podSpec.getContainerSpec(container.name);
const containerSpec = podSpec
.getContainers()
.find(({ name }) => container.name === name);
if (containerSpec) {
containerResources = containerSpec.resources;
}
Expand All @@ -257,7 +259,7 @@ class PodInstancesTable extends React.Component {
cpus: containerResources.cpus,
mem: containerResources.mem,
resourceLimits:
containerSpec.resourceLimits || containerSpec.resources || {},
containerSpec?.resourceLimits || containerSpec?.resources || {},
updated: container.getLastUpdated(),
version: "",
isHistoricalInstance: container.isHistoricalInstance,
Expand Down
41 changes: 14 additions & 27 deletions plugins/services/src/js/filters/PodInstanceStatusFilter.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,40 @@
import DSLFilterTypes from "#SRC/js/constants/DSLFilterTypes";
import DSLFilter from "#SRC/js/structs/DSLFilter";

const LABEL = "is";

const LABEL_TO_STATUS = {
active: "active",
completed: "completed",
};
const getStatus = (label) =>
({
active: "active",
completed: "completed",
}[label.toLowerCase()]);

/**
* This filter handles the `is:state` for instances
*/
class PodInstanceStatusFilter extends DSLFilter {
export default {
/**
* Handle all `is:XXXX` attribute filters that we can handle.
*
* @override
*/
filterCanHandle(filterType, filterArguments) {
filterCanHandle(filterType, { label, text }) {
return (
filterType === DSLFilterTypes.ATTRIB &&
filterArguments.label === LABEL &&
LABEL_TO_STATUS[filterArguments.text.toLowerCase()] != null
filterType === DSLFilterTypes.ATTRIB && label === "is" && getStatus(text)
);
}
},

/**
* Keep only instances whose state matches the value of
* the `is` label
*
* @override
* Keep only instances whose state matches the value of the `is` label
*/
filterApply(resultSet, filterType, filterArguments) {
const testStatus = LABEL_TO_STATUS[filterArguments.text.toLowerCase()];
filterApply(resultSet, _filterType, { text }) {
const testStatus = getStatus(text);

return resultSet.filterItems((instance) => {
let instanceStatus = "completed";

if (instance.isStaging()) {
instanceStatus = "staging";
}

if (instance.isRunning()) {
instanceStatus = "active";
}

return instanceStatus === testStatus;
});
}
}

export default PodInstanceStatusFilter;
},
};
27 changes: 7 additions & 20 deletions plugins/services/src/js/filters/PodInstanceTextFilter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import DSLFilterTypes from "#SRC/js/constants/DSLFilterTypes";
import DSLFilter from "#SRC/js/structs/DSLFilter";

/**
* This filter handles the `text` attributes against pod instance's `id` value
*/
class PodInstanceTextFilter extends DSLFilter {
export default {
/**
* Handle all `id` attribute filters that we can handle.
*
Expand All @@ -14,27 +13,15 @@ class PodInstanceTextFilter extends DSLFilter {
return (
filterType === DSLFilterTypes.EXACT || filterType === DSLFilterTypes.FUZZY
);
}
},

/**
* Keep only tasks whose id contains part of the filter's text
*
* @override
*/
filterApply(resultSet, filterType, filterArguments) {
const filteredItems = resultSet.filterItems(
(instance) => instance.id.indexOf(filterArguments.text) !== -1
);

if (
filteredItems.getItems().length !== 0 &&
filteredItems.getItems().length < resultSet.getItems().length
) {
return filteredItems;
}

return resultSet;
}
}

export default PodInstanceTextFilter;
filterApply(resultSet, _filterType, { text }) {
const filteredItems = resultSet.filterItems(({ id }) => id.includes(text));
return filteredItems.list.length !== 0 ? filteredItems : resultSet;
},
};
53 changes: 12 additions & 41 deletions plugins/services/src/js/filters/PodInstancesRegionFilter.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,23 @@
import DSLFilterTypes from "#SRC/js/constants/DSLFilterTypes";
import DSLFilter from "#SRC/js/structs/DSLFilter";
import InstanceUtil from "../utils/InstanceUtil";

const LABEL = "region";

/**
* This filter handles the `region:XXXX` for instances
*/
class PodInstancesRegionFilter extends DSLFilter {
constructor(regions = []) {
super();
this.regions = regions;
}
export default {
/**
* Handle all `region:XXXX` attribute filters that we can handle.
*
* @override
*/
filterCanHandle(filterType, filterArguments) {
const regions = this.regions;

return (
filterType === DSLFilterTypes.ATTRIB &&
filterArguments.label === LABEL &&
regions.includes(filterArguments.text.toLowerCase())
);
}
filterCanHandle(filterType, { label }) {
return filterType === DSLFilterTypes.ATTRIB && label === "region";
},

/**
* Keep only instances whose region matches the value of
* the `region` label
*
* @override
*/
filterApply(resultSet, filterType, filterArguments) {
let region = "";
const filterArgumentsValue = filterArguments.text.toLowerCase();

if (this.regions.includes(filterArgumentsValue)) {
region = filterArgumentsValue;
}

return resultSet.filterItems((instance) => {
const node = InstanceUtil.getNode(instance);

return node && node.getRegionName().toLowerCase() === region;
});
}
}

export default PodInstancesRegionFilter;
filterApply(resultSet, _filterType, { text }) {
const region = text.toLowerCase();
return resultSet.filterItems(
(instance) =>
InstanceUtil.getNode(instance)?.getRegionName().toLowerCase() === region
);
},
};
Loading

0 comments on commit 6a8701a

Please sign in to comment.