AIRAVATA-3691 Only show GRP compute resources in statistics filter
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue
index f6c2dce..db4628e 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/statistics/ExperimentStatisticsContainer.vue
@@ -335,6 +335,7 @@
hostnameFilter: null,
appInterfaces: null,
computeResourceNames: null,
+ groupResourceProfiles: null,
experimentDetailTabs: [],
experimentId: null,
jobId: null,
@@ -345,6 +346,7 @@
this.loadStatistics();
this.loadApplicationInterfaces();
this.loadComputeResources();
+ this.loadGroupResourceProfiles();
},
components: {
ExperimentDetailsView,
@@ -454,13 +456,22 @@
}
},
hostnameOptions() {
- if (this.computeResourceNames) {
- const options = this.computeResourceNames.map((name) => {
- return {
- value: name.host_id,
- text: name.host,
- };
- });
+ if (this.computeResourceNames && this.groupResourceProfiles) {
+ // Only show compute resources that are configured in the Group Resource Profiles
+ // First create a Set of all compute resource ids in the GRPs
+ const groupResourceProfileCompResources = new Set(
+ this.groupResourceProfiles.flatMap((grp) =>
+ grp.computePreferences.map((cp) => cp.computeResourceId)
+ )
+ );
+ const options = this.computeResourceNames
+ .filter((name) => groupResourceProfileCompResources.has(name.host_id))
+ .map((name) => {
+ return {
+ value: name.host_id,
+ text: name.host,
+ };
+ });
return utils.StringUtils.sortIgnoreCase(options, (o) => o.text);
} else {
return [];
@@ -505,6 +516,9 @@
(names) => (this.computeResourceNames = names)
);
},
+ async loadGroupResourceProfiles() {
+ this.groupResourceProfiles = await services.GroupResourceProfileService.list();
+ },
loadStatistics() {
const requestData = {
fromTime: this.fromTime.toJSON(),
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/tests/unit/components/statistics/ExperimentStatisticsContainer.spec.js b/django_airavata/apps/admin/static/django_airavata_admin/tests/unit/components/statistics/ExperimentStatisticsContainer.spec.js
index 5bdba0b..f593f2b 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/tests/unit/components/statistics/ExperimentStatisticsContainer.spec.js
+++ b/django_airavata/apps/admin/static/django_airavata_admin/tests/unit/components/statistics/ExperimentStatisticsContainer.spec.js
@@ -35,19 +35,25 @@
FullExperimentService: {
retrieve: jest.fn(),
},
+ GroupResourceProfileService: {
+ list: jest.fn(),
+ },
},
};
});
-// beforeEach(() => {
-// jest.resetAllMocks();
-// });
+beforeEach(() => {
+ jest.resetAllMocks();
-test("load experiment by job id when job id matches unique experiment", async () => {
const spinner = document.createElement("div");
spinner.id = "airavata-spinner";
document.body.appendChild(spinner);
+ // jsdom doesn't implement scrollIntoView so just provide a stubbed implementation
+ Element.prototype.scrollIntoView = jest.fn();
+});
+
+test("load experiment by job id when job id matches unique experiment", async () => {
// Service call mocks
services.ApplicationInterfaceService.list.mockResolvedValue([]);
services.ExperimentStatisticsService.get.mockResolvedValue(
@@ -108,9 +114,6 @@
})
);
- // jsdom doesn't implement scrollIntoView so just provide a stubbed implementation
- Element.prototype.scrollIntoView = jest.fn();
-
// The render method returns a collection of utilities to query your component.
const { findByText, findByPlaceholderText } = render(
ExperimentStatisticsContainer
@@ -148,3 +151,89 @@
lookup: experiment.experimentId,
});
});
+
+test("Hostname filter only shows compute resources that are configured in a GRP", async () => {
+ // Service call mocks
+ services.ApplicationInterfaceService.list.mockResolvedValue([]);
+ services.ExperimentStatisticsService.get.mockResolvedValue(
+ new utils.PaginationIterator(
+ {
+ count: 0,
+ next: null,
+ previous: null,
+ results: {
+ allExperimentCount: 0,
+ completedExperimentCount: 0,
+ cancelledExperimentCount: 0,
+ failedExperimentCount: 0,
+ createdExperimentCount: 0,
+ runningExperimentCount: 0,
+ allExperiments: [],
+ completedExperiments: [],
+ failedExperiments: [],
+ cancelledExperiments: [],
+ createdExperiments: [],
+ runningExperiments: [],
+ },
+ limit: 50,
+ offset: 0,
+ },
+ models.ExperimentStatistics
+ )
+ );
+ services.ComputeResourceService.namesList.mockResolvedValue([
+ { host_id: "compute4-abcd", host: "d-compute4" },
+ { host_id: "compute2-abcd", host: "b-compute2" },
+ { host_id: "compute5-abcd", host: "e-compute5" },
+ { host_id: "compute3-abcd", host: "c-compute3" },
+ { host_id: "compute1-abcd", host: "a-compute1" },
+ ]);
+
+ services.GroupResourceProfileService.list.mockResolvedValue([
+ new models.GroupResourceProfile({
+ computePreferences: [
+ new models.GroupComputeResourcePreference({
+ computeResourceId: "compute1-abcd",
+ }),
+ new models.GroupComputeResourcePreference({
+ computeResourceId: "compute3-abcd",
+ }),
+ ],
+ }),
+ new models.GroupResourceProfile({
+ computePreferences: [
+ new models.GroupComputeResourcePreference({
+ computeResourceId: "compute1-abcd",
+ }),
+ new models.GroupComputeResourcePreference({
+ computeResourceId: "compute4-abcd",
+ }),
+ ],
+ }),
+ ]);
+
+ // The render method returns a collection of utilities to query your component.
+ const { findByText } = render(ExperimentStatisticsContainer);
+
+ const addFiltersMenu = await findByText("Add Filters");
+
+ await fireEvent.click(addFiltersMenu);
+
+ const hostnameMenuItem = await findByText("Hostname");
+
+ await fireEvent.click(hostnameMenuItem);
+
+ const computeResourcesSelect = await findByText(
+ "Select compute resource to filter on"
+ );
+
+ const options = computeResourcesSelect.parentElement.options;
+
+ expect(options.length).toBe(4);
+ // option 0 is the null one ("Select compute resource to filter on")
+ // verify that options 1-3 are compute resources 1, 3, 4. That is, verify that
+ // filtering worked and that they were sorted.
+ expect(options[1].value).toBe("compute1-abcd");
+ expect(options[2].value).toBe("compute3-abcd");
+ expect(options[3].value).toBe("compute4-abcd");
+});