diff --git a/ui/src/app/components/apps-panel/runtime-cost.tsx b/ui/src/app/components/apps-panel/runtime-cost.tsx index 98249f7ce79..a5c8efd2579 100644 --- a/ui/src/app/components/apps-panel/runtime-cost.tsx +++ b/ui/src/app/components/apps-panel/runtime-cost.tsx @@ -3,8 +3,12 @@ import * as React from 'react'; import { RuntimeStatus } from 'generated/fetch'; import { switchCase } from '@terra-ui-packages/core-utils'; -import { toAnalysisConfig } from 'app/utils/analysis-config'; -import { machineRunningCost, machineStorageCost } from 'app/utils/machines'; +import { + ComputeType, + findMachineByName, + machineRunningCostPerHour, + machineStorageCostPerHour, +} from 'app/utils/machines'; import { formatUsd } from 'app/utils/numbers'; import { isVisible } from 'app/utils/runtime-utils'; import { runtimeDiskStore, runtimeStore, useStore } from 'app/utils/stores'; @@ -17,9 +21,29 @@ export const RuntimeCost = () => { return null; } - const analysisConfig = toAnalysisConfig(runtime, gcePersistentDisk); - const runningCost = formatUsd(machineRunningCost(analysisConfig)); - const storageCost = formatUsd(machineStorageCost(analysisConfig)); + const storageCostParams = { + dataprocConfig: runtime.dataprocConfig, + persistentDisk: gcePersistentDisk, + }; + + const machineType = + runtime.gceConfig?.machineType ?? + runtime.gceWithPdConfig?.machineType ?? + runtime.dataprocConfig.masterMachineType; + + const runningCostParams = { + ...storageCostParams, + computeType: runtime.dataprocConfig + ? ComputeType.Dataproc + : ComputeType.Standard, + machine: findMachineByName(machineType), + gpuConfig: + // not available for dataproc + runtime.gceConfig?.gpuConfig ?? runtime.gceWithPdConfig?.gpuConfig, + }; + + const runningCost = formatUsd(machineRunningCostPerHour(runningCostParams)); + const storageCost = formatUsd(machineStorageCostPerHour(storageCostParams)); // display running cost or stopped (storage) cost // Error and Deleted statuses are not included because they're not "visible" [isVisible() = false] diff --git a/ui/src/app/components/common-env-conf-panels/confirm-delete-environment-with-pd.tsx b/ui/src/app/components/common-env-conf-panels/confirm-delete-environment-with-pd.tsx index c557112b915..65c93822b14 100644 --- a/ui/src/app/components/common-env-conf-panels/confirm-delete-environment-with-pd.tsx +++ b/ui/src/app/components/common-env-conf-panels/confirm-delete-environment-with-pd.tsx @@ -9,7 +9,7 @@ import { FlexRow } from 'app/components/flex'; import { ClrIcon } from 'app/components/icons'; import { RadioButton } from 'app/components/inputs'; import colors from 'app/styles/colors'; -import { detachableDiskPricePerMonth } from 'app/utils/machines'; +import { persistentDiskPricePerMonth } from 'app/utils/machines'; import { formatUsd } from 'app/utils/numbers'; import { BackupFilesHelpSection } from './backup-files-help-section'; @@ -80,7 +80,7 @@ export const ConfirmDeleteEnvironmentWithPD = ({

You will continue to incur persistent disk cost at{' '} - {formatUsd(detachableDiskPricePerMonth(disk))} per month. You + {formatUsd(persistentDiskPricePerMonth(disk))} per month. You can delete your disk at any time via the {appType} configuration panel.

@@ -178,7 +178,7 @@ export const ConfirmDeleteEnvironmentWithPD = ({

You will continue to incur persistent disk cost at{' '} - {formatUsd(detachableDiskPricePerMonth(disk))} per month. + {formatUsd(persistentDiskPricePerMonth(disk))} per month.

diff --git a/ui/src/app/components/common-env-conf-panels/environment-cost-estimator.tsx b/ui/src/app/components/common-env-conf-panels/environment-cost-estimator.tsx index 89348fb4462..ca2ad5fa14f 100644 --- a/ui/src/app/components/common-env-conf-panels/environment-cost-estimator.tsx +++ b/ui/src/app/components/common-env-conf-panels/environment-cost-estimator.tsx @@ -1,18 +1,18 @@ import { CSSProperties } from 'react'; -import { cond } from '@terra-ui-packages/core-utils'; import { FlexColumn, FlexRow } from 'app/components/flex'; import { TooltipTrigger } from 'app/components/popups'; import colors from 'app/styles/colors'; import { reactStyles } from 'app/utils'; import { AnalysisConfig } from 'app/utils/analysis-config'; import { - detachableDiskPricePerMonth, - diskConfigPricePerMonth, - machineRunningCost, + derivePdFromAnalysisConfig, machineRunningCostBreakdown, - machineStorageCost, + machineRunningCostPerHour, machineStorageCostBreakdown, + machineStorageCostPerHour, + persistentDiskPricePerMonth, + RunningCost, } from 'app/utils/machines'; import { formatUsd } from 'app/utils/numbers'; @@ -54,15 +54,29 @@ export const EnvironmentCostEstimator = ({ costTextColor = colors.accent, style, }: Props) => { - const { detachedDisk, diskConfig } = analysisConfig; + const { computeType, gpuConfig, machine, dataprocConfig } = analysisConfig; + + // temp derive from analysisConfig + const persistentDisk = derivePdFromAnalysisConfig(analysisConfig); + + const runningCostParams: RunningCost = { + dataprocConfig, + persistentDisk, + computeType, + gpuConfig, + machine, + }; const runningCost = - machineRunningCost(analysisConfig) + + machineRunningCostPerHour(runningCostParams) + (isGKEApp ? GKE_APP_HOURLY_USD_COST_PER_WORKSPACE : 0); - const runningCostBreakdown = machineRunningCostBreakdown(analysisConfig); + const runningCostBreakdown = machineRunningCostBreakdown(runningCostParams); const pausedCost = - machineStorageCost(analysisConfig) + + machineStorageCostPerHour({ dataprocConfig, persistentDisk }) + (isGKEApp ? GKE_APP_HOURLY_USD_COST_PER_WORKSPACE : 0); - const pausedCostBreakdown = machineStorageCostBreakdown(analysisConfig); + const pausedCostBreakdown = machineStorageCostBreakdown({ + dataprocConfig, + persistentDisk, + }); if (isGKEApp) { const gkeBaseCost = `${formatUsd( @@ -76,11 +90,9 @@ export const EnvironmentCostEstimator = ({ ...styles.cost, color: costTextColor, }; - const pdCost = cond( - [diskConfig.detachable, () => diskConfigPricePerMonth(diskConfig)], - [!!detachedDisk, () => detachableDiskPricePerMonth(detachedDisk)], - () => 0 - ); + const pdCost = persistentDisk + ? persistentDiskPricePerMonth(persistentDisk) + : 0; return ( diff --git a/ui/src/app/components/common-env-conf-panels/environment-informed-action-panel.tsx b/ui/src/app/components/common-env-conf-panels/environment-informed-action-panel.tsx index 47e94787a9a..bee7997da9b 100644 --- a/ui/src/app/components/common-env-conf-panels/environment-informed-action-panel.tsx +++ b/ui/src/app/components/common-env-conf-panels/environment-informed-action-panel.tsx @@ -122,7 +122,6 @@ export const EnvironmentInformedActionPanel = ({ )} diff --git a/ui/src/app/components/runtime-configuration-panel.tsx b/ui/src/app/components/runtime-configuration-panel.tsx index 3060f770955..ee07ca7fd03 100644 --- a/ui/src/app/components/runtime-configuration-panel.tsx +++ b/ui/src/app/components/runtime-configuration-panel.tsx @@ -32,7 +32,8 @@ import { findCdrVersion } from 'app/utils/cdr-versions'; import { ComputeType, DATAPROC_MIN_DISK_SIZE_GB, - machineRunningCost, + derivePdFromAnalysisConfig, + machineRunningCostPerHour, MIN_DISK_SIZE_GB, } from 'app/utils/machines'; import { @@ -197,7 +198,13 @@ export const getErrorsAndWarnings = ({ }; const runningCostErrors = validate( - { currentRunningCost: machineRunningCost(analysisConfig) }, + { + currentRunningCost: machineRunningCostPerHour({ + ...analysisConfig, + // temp derive from analysisConfig + persistentDisk: derivePdFromAnalysisConfig(analysisConfig), + }), + }, { currentRunningCost: runningCostValidatorWithMessage(), } @@ -363,10 +370,9 @@ export const RuntimeConfigurationPanel = fp.flow( (analysisConfig.computeType === ComputeType.Dataproc && !analysisConfig.diskConfig.detachable)); - let runtimeCannotBeCreatedExplanation; - if (workspace.billingStatus !== BillingStatus.ACTIVE) { - runtimeCannotBeCreatedExplanation = BILLING_ACCOUNT_DISABLED_TOOLTIP; - } + const runtimeCannotBeCreatedExplanation = + workspace.billingStatus !== BillingStatus.ACTIVE && + BILLING_ACCOUNT_DISABLED_TOOLTIP; const runtimeCanBeUpdated = runtimeCanBeCreated && diff --git a/ui/src/app/components/runtime-configuration-panel/customize-panel.tsx b/ui/src/app/components/runtime-configuration-panel/customize-panel.tsx index a6115dda0a6..e8b3c163a05 100644 --- a/ui/src/app/components/runtime-configuration-panel/customize-panel.tsx +++ b/ui/src/app/components/runtime-configuration-panel/customize-panel.tsx @@ -346,9 +346,15 @@ export const CustomizePanel = ({ gcePersistentDisk ); + const dataprocConfig = analysisConfig.dataprocConfig && { + ...analysisConfig.dataprocConfig, + masterDiskSize: diskConfig.size, + }; + setAnalysisConfig({ ...analysisConfig, diskConfig, + dataprocConfig, detachedDisk: diskConfig.detachable ? null : gcePersistentDisk, }); }} diff --git a/ui/src/app/components/runtime-configuration-panel/offer-delete-disk-with-update.tsx b/ui/src/app/components/runtime-configuration-panel/offer-delete-disk-with-update.tsx index d3bf9de4700..2e0e59bf532 100644 --- a/ui/src/app/components/runtime-configuration-panel/offer-delete-disk-with-update.tsx +++ b/ui/src/app/components/runtime-configuration-panel/offer-delete-disk-with-update.tsx @@ -10,7 +10,7 @@ import { FlexRow } from 'app/components/flex'; import { ClrIcon } from 'app/components/icons'; import { RadioButton } from 'app/components/inputs'; import colors from 'app/styles/colors'; -import { detachableDiskPricePerMonth } from 'app/utils/machines'; +import { persistentDiskPricePerMonth } from 'app/utils/machines'; import { formatUsd } from 'app/utils/numbers'; const { useState, Fragment } = React; @@ -69,7 +69,7 @@ export const OfferDeleteDiskWithUpdate = ({ Your disk will be saved for later and can be reattached when you next configure a standard VM analysis environment. You will continue to incur persistent disk cost at{' '} - {formatUsd(detachableDiskPricePerMonth(disk))} per month. + {formatUsd(persistentDiskPricePerMonth(disk))} per month.

diff --git a/ui/src/app/utils/analysis-config.spec.tsx b/ui/src/app/utils/analysis-config.spec.tsx index 56f9f47d25f..c04cb8841a7 100644 --- a/ui/src/app/utils/analysis-config.spec.tsx +++ b/ui/src/app/utils/analysis-config.spec.tsx @@ -1,5 +1,4 @@ import { - DataprocConfig, Disk, DiskType, GpuConfig, @@ -813,19 +812,11 @@ describe(withAnalysisConfigDefaults.name, () => { existingDiskName: null, }; - // yes it removes 3 fields. why? - const expectedDataprocConfig: DataprocConfig = { - ...inputConfig.dataprocConfig, - masterMachineType: undefined, - masterDiskSize: undefined, - numberOfWorkerLocalSSDs: undefined, - }; - const outConfig = withAnalysisConfigDefaults(inputConfig, inputDisk); expect(outConfig.computeType).toEqual(ComputeType.Dataproc); expect(outConfig.diskConfig).toEqual(expectedDiskConfig); - expect(outConfig.dataprocConfig).toEqual(expectedDataprocConfig); + expect(outConfig.dataprocConfig).toEqual(inputConfig.dataprocConfig); expect(outConfig.gpuConfig).toBeNull(); expect(outConfig.detachedDisk).toEqual(inputDisk); @@ -839,13 +830,7 @@ describe(withAnalysisConfigDefaults.name, () => { ); }); - const replaceableFields = [ - 'numberOfWorkers', - 'workerMachineType', - 'workerDiskSize', - 'numberOfPreemptibleWorkers', - ]; - it('replaces the replaceableFields with their defaults when dataprocConfig is missing', () => { + it('sets dataprocConfig to the preset default when it is missing', () => { const inputConfig = { ...defaultAnalysisConfig, computeType: ComputeType.Dataproc, @@ -853,34 +838,11 @@ describe(withAnalysisConfigDefaults.name, () => { }; const outConfig = withAnalysisConfigDefaults(inputConfig, undefined); - - replaceableFields.forEach((field: string) => - expect(outConfig.dataprocConfig[field]).toEqual( - runtimePresets().hailAnalysis.runtimeTemplate.dataprocConfig[field] - ) + expect(outConfig.dataprocConfig).toEqual( + runtimePresets().hailAnalysis.runtimeTemplate.dataprocConfig ); }); - test.each(replaceableFields)( - "it replaces %s with the default when it's missing", - (field: string) => { - const inputConfig = { - ...defaultAnalysisConfig, - computeType: ComputeType.Dataproc, - dataprocConfig: { - ...defaultAnalysisConfig.dataprocConfig, - [field]: undefined, - }, - }; - - const outConfig = withAnalysisConfigDefaults(inputConfig, undefined); - - expect(outConfig.dataprocConfig[field]).toEqual( - runtimePresets().hailAnalysis.runtimeTemplate.dataprocConfig[field] - ); - } - ); - // same as Standard VM it("should replace a missing diskConfig size with the persistent disk's when it exists", () => { const inputConfig = { diff --git a/ui/src/app/utils/analysis-config.tsx b/ui/src/app/utils/analysis-config.tsx index abeac7c1509..e3494a60c89 100644 --- a/ui/src/app/utils/analysis-config.tsx +++ b/ui/src/app/utils/analysis-config.tsx @@ -184,9 +184,15 @@ export const withAnalysisConfigDefaults = ( dataprocConfig = { numberOfWorkers: dataprocConfig?.numberOfWorkers ?? defaults.numberOfWorkers, + masterMachineType: + dataprocConfig?.masterMachineType ?? defaults.masterMachineType, + masterDiskSize: dataprocConfig?.masterDiskSize ?? defaults.masterDiskSize, workerMachineType: dataprocConfig?.workerMachineType ?? defaults.workerMachineType, workerDiskSize: dataprocConfig?.workerDiskSize ?? defaults.workerDiskSize, + numberOfWorkerLocalSSDs: + dataprocConfig?.numberOfWorkerLocalSSDs ?? + defaults.numberOfWorkerLocalSSDs, numberOfPreemptibleWorkers: dataprocConfig?.numberOfPreemptibleWorkers ?? defaults.numberOfPreemptibleWorkers, diff --git a/ui/src/app/utils/machines.ts b/ui/src/app/utils/machines.ts index 953a0cbcb1a..a0a7132e33e 100644 --- a/ui/src/app/utils/machines.ts +++ b/ui/src/app/utils/machines.ts @@ -1,7 +1,12 @@ import * as fp from 'lodash/fp'; import { SelectItem } from 'primereact/selectitem'; -import { Disk, DiskType } from 'generated/fetch'; +import { + DataprocConfig, + DiskType, + GpuConfig, + PersistentDiskRequest, +} from 'generated/fetch'; import { DEFAULT, switchCase } from '@terra-ui-packages/core-utils'; @@ -371,24 +376,29 @@ export const DEFAULT_MACHINE_TYPE: Machine = export const DEFAULT_DISK_SIZE = MIN_DISK_SIZE_GB; const approxHoursPerMonth = 730; -export const diskPricePerMonth = 0.04; // per GB month -export const diskPrice = diskPricePerMonth / approxHoursPerMonth; // per GB hour, from https://cloud.google.com/compute/pricing -export const ssdPricePerMonth = 0.17; // per GB month -export const dataprocCpuPrice = 0.01; // dataproc costs $0.01 per cpu per hour +const standardDiskPricePerMonth = 0.04; // per GB month, from https://cloud.google.com/compute/pricing +const ssdPricePerMonth = 0.17; // per GB month +const dataprocCpuPricePerHour = 0.01; // dataproc costs $0.01 per cpu per hour -const dataprocSurcharge = ({ +interface DataprocSurcharge { + masterMachine: Machine; + workerMachine: Machine; + numberOfWorkers: number; + numberOfPreemptibleWorkers: number; +} +const dataprocCpuSurchargePerHour = ({ masterMachine, + workerMachine, numberOfWorkers, numberOfPreemptibleWorkers, - workerMachine, -}) => { - const costs = [masterMachine.cpu * dataprocCpuPrice]; +}: DataprocSurcharge) => { + const costs = [masterMachine.cpu * dataprocCpuPricePerHour]; if (workerMachine && numberOfWorkers) { - costs.push(numberOfWorkers * workerMachine.cpu * dataprocCpuPrice); + costs.push(numberOfWorkers * workerMachine.cpu * dataprocCpuPricePerHour); } if (workerMachine && numberOfPreemptibleWorkers) { costs.push( - numberOfPreemptibleWorkers * workerMachine.cpu * dataprocCpuPrice + numberOfPreemptibleWorkers * workerMachine.cpu * dataprocCpuPricePerHour ); } return fp.sum(costs); @@ -397,87 +407,123 @@ const dataprocSurcharge = ({ // The following calculations were based off of Terra UI's cost estimator: // https://github.com/DataBiosphere/terra-ui/blob/cf5ec4408db3bd1fcdbcc5302da62d42e4d03ca3/src/components/ClusterManager.js#L85 -export const diskConfigPricePerMonth = ({ - size, - detachableType, -}: Partial) => { +const diskPricePerMonth = ({ size, detachableType }: Partial) => { return ( size * - (detachableType === DiskType.SSD ? ssdPricePerMonth : diskPricePerMonth) + // also covers the case where the disk is not detachable/persistent (type is undefined) + (detachableType === DiskType.SSD + ? ssdPricePerMonth + : standardDiskPricePerMonth) ); }; -export const detachableDiskPricePerMonth = (disk: Disk) => { - return diskConfigPricePerMonth({ +export const persistentDiskPricePerMonth = (disk: PersistentDiskRequest) => { + return diskPricePerMonth({ size: disk.size, detachableType: disk.diskType, }); }; -export const diskConfigPrice = (config: Partial) => { - return diskConfigPricePerMonth(config) / approxHoursPerMonth; +const persistentDiskPricePerHour = (disk: PersistentDiskRequest) => { + return persistentDiskPricePerMonth(disk) / approxHoursPerMonth; +}; + +const dataprocDiskPricePerHour = (size: number) => { + return diskPricePerMonth({ size }) / approxHoursPerMonth; }; -const detachableDiskPrice = (disk: Disk) => { - return detachableDiskPricePerMonth(disk) / approxHoursPerMonth; +// temp until we can stop using AnalysisConfig in locations which need to calculate storage/running costs +export const derivePdFromAnalysisConfig = ( + analysisConfig: AnalysisConfig +): PersistentDiskRequest => { + // detachable means: is the diskConfig a PD? + // - yes when there's an active GceWithPd + // detachedDisk is only present when the diskConfig is NOT a PD + return analysisConfig.diskConfig.detachable + ? { + name: analysisConfig.diskConfig.existingDiskName, + size: analysisConfig.diskConfig.size, + diskType: analysisConfig.diskConfig.detachableType, + } + : analysisConfig.detachedDisk; }; -export const machineStorageCost = ({ - diskConfig, +interface StorageCost { + dataprocConfig: DataprocConfig; + persistentDisk: PersistentDiskRequest; +} +export const machineStorageCostPerHour = ({ dataprocConfig, - detachedDisk, -}: AnalysisConfig) => { - const { numberOfWorkers, numberOfPreemptibleWorkers, workerDiskSize } = - dataprocConfig ?? {}; + persistentDisk, +}: StorageCost) => { + const { + numberOfWorkers, + numberOfPreemptibleWorkers, + masterDiskSize, + workerDiskSize, + } = dataprocConfig ?? {}; return fp.sum([ - diskConfigPrice(diskConfig), - detachedDisk ? detachableDiskPrice(detachedDisk) : 0, - numberOfWorkers ? numberOfWorkers * workerDiskSize * diskPrice : 0, + persistentDisk ? persistentDiskPricePerHour(persistentDisk) : 0, + masterDiskSize ? dataprocDiskPricePerHour(masterDiskSize) : 0, + numberOfWorkers + ? numberOfWorkers * dataprocDiskPricePerHour(workerDiskSize) + : 0, numberOfPreemptibleWorkers - ? numberOfPreemptibleWorkers * workerDiskSize * diskPrice + ? numberOfPreemptibleWorkers * dataprocDiskPricePerHour(workerDiskSize) : 0, ]); }; export const machineStorageCostBreakdown = ({ - diskConfig, dataprocConfig, - detachedDisk, -}: AnalysisConfig) => { - const { numberOfWorkers, numberOfPreemptibleWorkers, workerDiskSize } = - dataprocConfig ?? {}; + persistentDisk, +}: StorageCost) => { + const { + numberOfWorkers, + numberOfPreemptibleWorkers, + masterDiskSize, + workerDiskSize, + } = dataprocConfig ?? {}; const costs = []; if (dataprocConfig) { - costs.push(`${formatUsd(diskConfigPrice(diskConfig))}/hr Master Disk`); + costs.push( + `${formatUsd(dataprocDiskPricePerHour(masterDiskSize))}/hr Master Disk` + ); if (numberOfWorkers) { costs.push( `${formatUsd( - numberOfWorkers * workerDiskSize * diskPrice + numberOfWorkers * dataprocDiskPricePerHour(workerDiskSize) )}/hr Worker Disk(s)` ); } if (numberOfPreemptibleWorkers) { costs.push( `${formatUsd( - numberOfPreemptibleWorkers * workerDiskSize * diskPrice + numberOfPreemptibleWorkers * dataprocDiskPricePerHour(workerDiskSize) )}/hr Preemptible Worker Disk(s)` ); } - } else { - costs.push(`${formatUsd(diskConfigPrice(diskConfig))}/hr Disk`); } - if (detachedDisk) { + // note: there may still be a detached PD if there's an active Dataproc runtime + if (persistentDisk) { costs.push( - `${formatUsd(detachableDiskPrice(detachedDisk))}/hr Detached Disk` + `${formatUsd( + persistentDiskPricePerHour(persistentDisk) + )}/hr Persistent Disk` ); } return costs; }; -export const machineRunningCost = (analysisConfig: AnalysisConfig) => { - const { computeType, machine, gpuConfig, numNodes } = analysisConfig; +export interface RunningCost extends StorageCost { + computeType: ComputeType; + machine: Machine; + gpuConfig: GpuConfig; +} +export const machineRunningCostPerHour = (props: RunningCost) => { + const { computeType, machine, gpuConfig, dataprocConfig } = props; const { workerMachineType, numberOfWorkers, numberOfPreemptibleWorkers } = - analysisConfig.dataprocConfig ?? {}; + dataprocConfig ?? {}; const workerMachine = workerMachineType && findMachineByName(workerMachineType); @@ -485,7 +531,7 @@ export const machineRunningCost = (analysisConfig: AnalysisConfig) => { const dataprocPrice = computeType === ComputeType.Dataproc ? fp.sum([ - dataprocSurcharge({ + dataprocCpuSurchargePerHour({ masterMachine: machine, numberOfWorkers, numberOfPreemptibleWorkers, @@ -501,16 +547,16 @@ export const machineRunningCost = (analysisConfig: AnalysisConfig) => { : 0; return fp.sum([ dataprocPrice, - machine.price * (numNodes ?? 1), + machine.price, gpu ? gpu.price : 0, - machineStorageCost(analysisConfig), + machineStorageCostPerHour(props), ]); }; -export const machineRunningCostBreakdown = (analysisConfig: AnalysisConfig) => { - const { computeType, machine, gpuConfig } = analysisConfig; +export const machineRunningCostBreakdown = (props: RunningCost) => { + const { computeType, machine, gpuConfig, dataprocConfig } = props; const { workerMachineType, numberOfWorkers, numberOfPreemptibleWorkers } = - analysisConfig.dataprocConfig ?? {}; + dataprocConfig ?? {}; const workerMachine = workerMachineType && findMachineByName(workerMachineType); @@ -534,7 +580,7 @@ export const machineRunningCostBreakdown = (analysisConfig: AnalysisConfig) => { ); } } - const dataprocSurchargeAmount = dataprocSurcharge({ + const dataprocSurchargeAmount = dataprocCpuSurchargePerHour({ masterMachine: machine, numberOfWorkers: numberOfWorkers, numberOfPreemptibleWorkers: numberOfPreemptibleWorkers, @@ -549,6 +595,6 @@ export const machineRunningCostBreakdown = (analysisConfig: AnalysisConfig) => { costs.push(`${formatUsd(gpu.price)}/hr GPU`); } } - costs.push(...machineStorageCostBreakdown(analysisConfig)); + costs.push(...machineStorageCostBreakdown(props)); return costs; };