mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Adjust JobMetrics component tests and add AwsEstimate component tests
This commit is contained in:
committed by
Dannon Baker
parent
7e02181d20
commit
dc1a24e4d4
@@ -0,0 +1,86 @@
|
||||
import ec2 from "./ec2.json";
|
||||
import flushPromises from "flush-promises";
|
||||
import { getLocalVue } from "tests/jest/helpers";
|
||||
import AwsEstimate from "./AwsEstimate";
|
||||
import { mount } from "@vue/test-utils";
|
||||
|
||||
// Ignore all axios calls, data is mocked locally -- just say "OKAY!"
|
||||
jest.mock("axios", () => ({
|
||||
get: async () => {
|
||||
return { response: { status: 200 } };
|
||||
},
|
||||
}));
|
||||
|
||||
const localVue = getLocalVue();
|
||||
|
||||
describe("JobMetrics/AwsEstimate.vue", () => {
|
||||
it("renders nothing if no matching EC2 instance exists.", async () => {
|
||||
const wrapper = mount(AwsEstimate, {
|
||||
propsData: {
|
||||
jobId: "0",
|
||||
jobRuntime: 0,
|
||||
coresAllocated: -999,
|
||||
memoryAllocated: -999,
|
||||
},
|
||||
localVue,
|
||||
});
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.find("#aws-name").exists()).toBe(false);
|
||||
});
|
||||
|
||||
it("renders correct AWS estimates.", async () => {
|
||||
const deriveRenderedAwsEstimate = async (cores, seconds, memory) => {
|
||||
const JOB_ID = Math.random().toString(36).substring(2);
|
||||
|
||||
const wrapper = mount(AwsEstimate, {
|
||||
localVue,
|
||||
propsData: {
|
||||
jobId: JOB_ID,
|
||||
jobRuntime: Number(seconds),
|
||||
coresAllocated: Number(cores),
|
||||
memoryAllocated: Number(memory),
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for axios and rendering.
|
||||
await flushPromises();
|
||||
|
||||
if (wrapper.find("#aws-estimate").exists()) {
|
||||
return {
|
||||
cost: wrapper.find("#aws-cost").text(),
|
||||
vcpus: wrapper.find("#aws-vcpus").text(),
|
||||
cpu: wrapper.find("#aws-cpu").text(),
|
||||
mem: wrapper.find("#aws-mem").text(),
|
||||
name: wrapper.find("#aws-name").text(),
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
const assertAwsInstance = (estimates) => {
|
||||
const instance = ec2.find((instance) => estimates.name === instance.name);
|
||||
expect(estimates.mem).toBe(instance.mem.toString());
|
||||
expect(estimates.vcpus).toBe(instance.vcpus.toString());
|
||||
expect(estimates.cpu).toBe(instance.cpu.join(", "));
|
||||
};
|
||||
|
||||
const estimates_small = await deriveRenderedAwsEstimate("1.0000000", "9.0000000", "2048.0000000");
|
||||
expect(estimates_small.name).toBe("t2.small");
|
||||
expect(estimates_small.cost).toBe("0.00 USD");
|
||||
assertAwsInstance(estimates_small);
|
||||
|
||||
const estimates_large = await deriveRenderedAwsEstimate("40.0000000", "18000.0000000", "194560.0000000");
|
||||
expect(estimates_large.name).toBe("m5d.12xlarge");
|
||||
expect(estimates_large.cost).toBe("16.32 USD");
|
||||
assertAwsInstance(estimates_large);
|
||||
|
||||
const estimates_not_available = await deriveRenderedAwsEstimate(
|
||||
"99999.0000000",
|
||||
"18000.0000000",
|
||||
"99999.0000000"
|
||||
);
|
||||
expect(estimates_not_available).toEqual({});
|
||||
});
|
||||
});
|
||||
@@ -5,60 +5,55 @@ import ec2 from "./ec2.json";
|
||||
export interface AwsEstimateProps {
|
||||
jobRuntime: number;
|
||||
coresAllocated: number;
|
||||
memoryAllocated: number;
|
||||
memoryAllocated?: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<AwsEstimateProps>(), {
|
||||
memoryAllocated: 0.5,
|
||||
});
|
||||
const props = defineProps<AwsEstimateProps>();
|
||||
|
||||
const computedAwsEstimate = computed(() => {
|
||||
const aws: Record<string, any> = {};
|
||||
|
||||
const { coresAllocated, jobRuntime, memoryAllocated } = props;
|
||||
|
||||
aws.seconds = jobRuntime;
|
||||
aws.vcpus = coresAllocated;
|
||||
aws.memory = memoryAllocated;
|
||||
|
||||
if (aws.memory) {
|
||||
aws.memory /= 1024;
|
||||
} else {
|
||||
// if memory was not specified, assign the smallest amount (we judge based on CPU-count only)
|
||||
aws.memory = 0.5;
|
||||
}
|
||||
|
||||
// Estimate EC2 instance. Data is already sorted
|
||||
aws.instance = ec2.find((ec) => {
|
||||
return ec.mem >= aws.memory && ec.vcpus >= aws.vcpus;
|
||||
});
|
||||
|
||||
if (!aws.instance) {
|
||||
if (coresAllocated <= 0 || jobRuntime <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
aws.price = ((aws.seconds * aws.instance.price) / 3600).toFixed(2);
|
||||
const adjustedMemoryAllocated = memoryAllocated ? memoryAllocated / 1024 : 0.5;
|
||||
|
||||
return aws;
|
||||
// Estimate EC2 instance. Data is already sorted
|
||||
const ec2Instance = ec2.find((ec) => {
|
||||
return ec.mem >= adjustedMemoryAllocated && ec.vcpus >= coresAllocated;
|
||||
});
|
||||
|
||||
if (!ec2Instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
seconds: jobRuntime,
|
||||
vcpus: coresAllocated,
|
||||
memory: adjustedMemoryAllocated,
|
||||
price: ((jobRuntime * ec2Instance.price) / 3600).toFixed(2),
|
||||
instance: ec2Instance
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="computedAwsEstimate" class="aws mt-4">
|
||||
<div v-if="computedAwsEstimate" id="aws-estimate" class="mt-4">
|
||||
<h3>AWS estimate</h3>
|
||||
|
||||
<strong>{{ computedAwsEstimate.price }} USD</strong>
|
||||
<strong id="aws-cost">{{ computedAwsEstimate.price }} USD</strong>
|
||||
|
||||
<br />
|
||||
|
||||
This job requested {{ computedAwsEstimate.vcpus }} core{{ computedAwsEstimate.vcpus > 1 ? "s" : "" }} and
|
||||
{{ computedAwsEstimate.memory.toFixed(3) }} GiB of memory. Given this information, the smallest EC2 machine we
|
||||
could find is:
|
||||
This job requested {{ computedAwsEstimate.vcpus }} core(s) and
|
||||
{{ computedAwsEstimate.memory.toFixed(3) }} GiB of memory. Given this
|
||||
information, the smallest EC2 machine we could find is:
|
||||
|
||||
<span id="aws_name">{{ computedAwsEstimate.instance.name }}</span>
|
||||
(<span id="aws_mem">{{ computedAwsEstimate.instance.mem }}</span> GB /
|
||||
<span id="aws_vcpus">{{ computedAwsEstimate.instance.vcpus }}</span> vCPUs /
|
||||
<span v-for="cpu in computedAwsEstimate.instance.cpu" id="aws_cpu" :key="cpu">{{ cpu }}</span
|
||||
<span id="aws-name">{{ computedAwsEstimate.instance.name }}</span>
|
||||
(<span id="aws-mem">{{ computedAwsEstimate.instance.mem }}</span> GB /
|
||||
<span id="aws-vcpus">{{ computedAwsEstimate.instance.vcpus }}</span> vCPUs /
|
||||
<span id="aws-cpu">{{ computedAwsEstimate.instance.cpu.join(", ") }}</span
|
||||
>). This instance is priced at {{ computedAwsEstimate.instance.price }} USD/hour.
|
||||
|
||||
<br />
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createTestingPinia } from "@pinia/testing";
|
||||
import ec2 from "./ec2.json";
|
||||
import flushPromises from "flush-promises";
|
||||
import { getLocalVue } from "tests/jest/helpers";
|
||||
import JobMetrics from "./JobMetrics";
|
||||
@@ -69,76 +68,4 @@ describe("JobMetrics/JobMetrics.vue", () => {
|
||||
expect(metricsTables.at(1).find(".metrics_plugin_title").text()).toBe("extended");
|
||||
expect(metricsTables.at(1).findAll("tr").length).toBe(1);
|
||||
});
|
||||
|
||||
it("renders correct AWS estimates", async () => {
|
||||
const deriveRenderedAwsEstimate = async (cores, seconds, memory) => {
|
||||
const JOB_ID = Math.random().toString(36).substring(2);
|
||||
const mockMetricsResponse = [
|
||||
{ plugin: "core", name: "galaxy_slots", raw_value: cores },
|
||||
{ plugin: "core", name: "runtime_seconds", raw_value: seconds },
|
||||
{ plugin: "core", name: "galaxy_memory_mb", raw_value: memory },
|
||||
];
|
||||
|
||||
const pinia = createTestingPinia({
|
||||
initialState: {
|
||||
jobMetricsStore: {
|
||||
jobMetricsByJobId: {
|
||||
[`${JOB_ID}`]: mockMetricsResponse,
|
||||
},
|
||||
jobMetricsByHdaId: {},
|
||||
jobMetricsByLddaId: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
setActivePinia(pinia);
|
||||
|
||||
const wrapper = mount(JobMetrics, {
|
||||
localVue,
|
||||
pinia,
|
||||
propsData: {
|
||||
jobId: JOB_ID,
|
||||
shouldShowAwsEstimate: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Wait for axios and rendering.
|
||||
await flushPromises();
|
||||
|
||||
if (wrapper.find("#aws-estimate").exists()) {
|
||||
return {
|
||||
cost: wrapper.find("#aws-estimate b").text(),
|
||||
vcpus: wrapper.find("#aws_vcpus").text(),
|
||||
cpu: wrapper.find("#aws_cpu").text(),
|
||||
mem: wrapper.find("#aws_mem").text(),
|
||||
name: wrapper.find("#aws_name").text(),
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
const assertAwsInstance = (estimates) => {
|
||||
const instance = ec2.find((instance) => estimates.name === instance.name);
|
||||
expect(estimates.mem).toBe(instance.mem.toString());
|
||||
expect(estimates.vcpus).toBe(instance.vcpus.toString());
|
||||
expect(estimates.cpu).toBe(instance.cpu.toString());
|
||||
};
|
||||
|
||||
const estimates_small = await deriveRenderedAwsEstimate("1.0000000", "9.0000000", "2048.0000000");
|
||||
expect(estimates_small.name).toBe("t2.small");
|
||||
expect(estimates_small.cost).toBe("0.00 USD");
|
||||
assertAwsInstance(estimates_small);
|
||||
|
||||
const estimates_large = await deriveRenderedAwsEstimate("40.0000000", "18000.0000000", "194560.0000000");
|
||||
expect(estimates_large.name).toBe("m5d.12xlarge");
|
||||
expect(estimates_large.cost).toBe("16.32 USD");
|
||||
assertAwsInstance(estimates_large);
|
||||
|
||||
const estimates_not_available = await deriveRenderedAwsEstimate(
|
||||
"99999.0000000",
|
||||
"18000.0000000",
|
||||
"99999.0000000"
|
||||
);
|
||||
expect(estimates_not_available).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,18 +6,20 @@ import { useJobMetricsStore } from "@/stores/jobMetricsStore";
|
||||
import { computed, unref } from "vue";
|
||||
|
||||
export interface JobMetricsProps {
|
||||
jobId: string;
|
||||
datasetId: string;
|
||||
shouldShowAwsEstimate: boolean;
|
||||
datasetType?: string;
|
||||
datasetFilesize?: number;
|
||||
datasetId?: string;
|
||||
datasetType?: string;
|
||||
includeTitle?: boolean;
|
||||
jobId: string;
|
||||
shouldShowAwsEstimate?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<JobMetricsProps>(), {
|
||||
datasetType: "hda",
|
||||
datasetFilesize: 0,
|
||||
datasetId: "",
|
||||
datasetType: "hda",
|
||||
includeTitle: true,
|
||||
shouldShowAwsEstimate: false
|
||||
});
|
||||
|
||||
const jobMetricsStore = useJobMetricsStore();
|
||||
|
||||
Reference in New Issue
Block a user