Skip to content

Commit 0b34e01

Browse files
authored
Disable Cost Monitoring in unsupported regions (#240)
* Add a way to handle unsupported regions for features in featureFlagProvider * Update tests and references to reflect changes in featureFlagProvider
1 parent 8c14152 commit 0b34e01

File tree

9 files changed

+110
-23
lines changed

9 files changed

+110
-23
lines changed

frontend/src/feature-flags/__tests__/FeatureFlagsProvider.test.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,25 @@ import {AvailableFeature} from '../types'
1313

1414
describe('given a feature flags provider and a list of rules', () => {
1515
const subject = featureFlagsProvider
16+
let region: string | undefined = 'us-west-1'
1617

1718
describe('when the features list is retrieved', () => {
1819
it('should return the list', async () => {
19-
const features = await subject('0.0.0')
20+
const features = await subject('0.0.0', region)
2021
expect(features).toEqual<AvailableFeature[]>([])
2122
})
2223
})
2324

2425
describe('when the version is between 3.1.0 and 3.2.0', () => {
2526
it('should return the list of available features', async () => {
26-
const features = await subject('3.1.5')
27+
const features = await subject('3.1.5', region)
2728
expect(features).toEqual<AvailableFeature[]>(['multiuser_cluster'])
2829
})
2930
})
3031

3132
describe('when the version is between 3.2.0 and 3.3.0', () => {
3233
it('should return the list of available features', async () => {
33-
const features = await subject('3.2.5')
34+
const features = await subject('3.2.5', region)
3435
expect(features).toEqual<AvailableFeature[]>([
3536
'multiuser_cluster',
3637
'fsx_ontap',
@@ -46,7 +47,7 @@ describe('given a feature flags provider and a list of rules', () => {
4647

4748
describe('when the version is between 3.3.0 and 3.4.0', () => {
4849
it('should return the list of available features', async () => {
49-
const features = await subject('3.3.2')
50+
const features = await subject('3.3.2', region)
5051
expect(features).toEqual<AvailableFeature[]>([
5152
'multiuser_cluster',
5253
'fsx_ontap',
@@ -68,7 +69,7 @@ describe('given a feature flags provider and a list of rules', () => {
6869

6970
describe('when the version is between 3.4.0 and 3.6.0', () => {
7071
it('should return the list of available features', async () => {
71-
const features = await subject('3.4.1')
72+
const features = await subject('3.4.1', region)
7273
expect(features).toEqual<AvailableFeature[]>([
7374
'multiuser_cluster',
7475
'fsx_ontap',
@@ -92,7 +93,7 @@ describe('given a feature flags provider and a list of rules', () => {
9293

9394
describe('when the version is above and 3.6.0', () => {
9495
it('should return the list of available features', async () => {
95-
const features = await subject('3.6.0')
96+
const features = await subject('3.6.0', region)
9697
expect(features).toEqual<AvailableFeature[]>([
9798
'multiuser_cluster',
9899
'fsx_ontap',
@@ -122,7 +123,7 @@ describe('given a feature flags provider and a list of rules', () => {
122123
window.sessionStorage.setItem('additionalFeatures', '["cost_monitoring"]')
123124
})
124125
it('should be included in the list of features', async () => {
125-
const features = await subject('3.1.5')
126+
const features = await subject('3.1.5', region)
126127
expect(features).toEqual<AvailableFeature[]>([
127128
'multiuser_cluster',
128129
'cost_monitoring',
@@ -135,8 +136,24 @@ describe('given a feature flags provider and a list of rules', () => {
135136
window.sessionStorage.clear()
136137
})
137138
it('should not be included in the list of features', async () => {
138-
const features = await subject('3.1.5')
139+
const features = await subject('3.1.5', region)
139140
expect(features).toEqual<AvailableFeature[]>(['multiuser_cluster'])
140141
})
141142
})
143+
144+
describe('when a feature is not supported in a region', () => {
145+
it('should return the list of available features without the unsupported feature', async () => {
146+
region = 'us-gov-west-1'
147+
const features = await subject('3.6.0', region)
148+
expect(features).not.toContain<AvailableFeature[]>(['cost_monitoring'])
149+
})
150+
})
151+
152+
describe('when a feature is not supported in a region and the region is undefined', () => {
153+
it('should return an empty list', async () => {
154+
region = undefined
155+
const features = await subject('3.6.0', region)
156+
expect(features).not.toContain<AvailableFeature[]>(['cost_monitoring'])
157+
})
158+
})
142159
})

frontend/src/feature-flags/featureFlagsProvider.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,26 @@ const versionToFeaturesMap: Record<string, AvailableFeature[]> = {
3434
'3.6.0': ['rhel8', 'new_resources_limits'],
3535
}
3636

37+
const featureToUnsupportedRegionsMap: Partial<
38+
Record<AvailableFeature, string[]>
39+
> = {
40+
cost_monitoring: ['us-gov-west-1'],
41+
}
42+
43+
function isSupportedInRegion(
44+
feature: AvailableFeature,
45+
region?: string,
46+
): boolean {
47+
if (feature in featureToUnsupportedRegionsMap) {
48+
if (!region) {
49+
return false
50+
} else {
51+
return !featureToUnsupportedRegionsMap[feature]!.includes(region)
52+
}
53+
}
54+
return true
55+
}
56+
3757
function composeFlagsListByVersion(currentVersion: string): AvailableFeature[] {
3858
let features: Set<AvailableFeature> = new Set([])
3959

@@ -46,7 +66,10 @@ function composeFlagsListByVersion(currentVersion: string): AvailableFeature[] {
4666
return Array.from(features)
4767
}
4868

49-
export function featureFlagsProvider(version: string): AvailableFeature[] {
69+
export function featureFlagsProvider(
70+
version: string,
71+
region?: string,
72+
): AvailableFeature[] {
5073
const features: AvailableFeature[] = []
5174
const additionalFeatures = window.sessionStorage.getItem('additionalFeatures')
5275
const additionalFeaturesParsed = additionalFeatures
@@ -56,4 +79,5 @@ export function featureFlagsProvider(version: string): AvailableFeature[] {
5679
return features
5780
.concat(composeFlagsListByVersion(version))
5881
.concat(additionalFeaturesParsed)
82+
.filter(feature => isSupportedInRegion(feature, region))
5983
}

frontend/src/feature-flags/useFeatureFlag.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ import {AvailableFeature} from './types'
1414

1515
export function useFeatureFlag(feature: AvailableFeature): boolean {
1616
const version = useState(['app', 'version', 'full'])
17-
return isFeatureEnabled(version, feature)
17+
const region = useState(['aws', 'region'])
18+
return isFeatureEnabled(version, region, feature)
1819
}
1920

2021
export function isFeatureEnabled(
2122
version: string,
23+
region: string,
2224
feature: AvailableFeature,
2325
): boolean {
24-
const features = new Set(featureFlagsProvider(version))
26+
const features = new Set(featureFlagsProvider(version, region))
2527

2628
return features.has(feature)
2729
}

frontend/src/old-pages/Clusters/Costs/__tests__/EnableCostMonitoringButton.test.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ describe('given a component to activate cost monitoring for the account', () =>
6161
app: {
6262
version: {full: '3.2.0'},
6363
},
64+
aws: {
65+
region: 'us-west-1',
66+
},
6467
})
6568

6669
screen = render(
@@ -91,6 +94,9 @@ describe('given a component to activate cost monitoring for the account', () =>
9194
app: {
9295
version: {full: '3.2.0'},
9396
},
97+
aws: {
98+
region: 'us-west-1',
99+
},
94100
})
95101
mockGetCostMonitoringStatus.mockResolvedValue(true)
96102

@@ -117,6 +123,9 @@ describe('given a component to activate cost monitoring for the account', () =>
117123
app: {
118124
version: {full: '3.1.5'},
119125
},
126+
aws: {
127+
region: 'us-west-1',
128+
},
120129
})
121130

122131
screen = render(

frontend/src/old-pages/Clusters/Costs/__tests__/useCostMonitoringStatus.test.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ jest.mock('../../../../model', () => {
4141
describe('given a hook to get the cost monitoring status', () => {
4242
beforeEach(() => {
4343
jest.clearAllMocks()
44+
mockQueryClient.resetQueries()
4445
})
4546

4647
describe('when PC version is at least 3.2.0', () => {
@@ -49,6 +50,9 @@ describe('given a hook to get the cost monitoring status', () => {
4950
app: {
5051
version: {full: '3.2.0'},
5152
},
53+
aws: {
54+
region: 'us-west-1',
55+
},
5256
})
5357
})
5458

@@ -65,6 +69,27 @@ describe('given a hook to get the cost monitoring status', () => {
6569
app: {
6670
version: {full: '3.1.5'},
6771
},
72+
aws: {
73+
region: 'us-west-1',
74+
},
75+
})
76+
})
77+
it('should not request the cost monitoring status', async () => {
78+
renderHook(() => useCostMonitoringStatus(), {wrapper})
79+
80+
expect(mockGetCostMonitoringStatus).toHaveBeenCalledTimes(0)
81+
})
82+
})
83+
84+
describe('when PC version is at least 3.2.0, and the region is us-gov-west-1', () => {
85+
beforeEach(() => {
86+
mockStore.getState.mockReturnValue({
87+
app: {
88+
version: {full: '3.2.0'},
89+
},
90+
aws: {
91+
region: 'us-gov-west-1',
92+
},
6893
})
6994
})
7095
it('should not request the cost monitoring status', async () => {

frontend/src/old-pages/Configure/Queues/Queues.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import InfoLink from '../../../components/InfoLink'
6868
// Constants
6969
const queuesPath = ['app', 'wizard', 'config', 'Scheduling', 'SlurmQueues']
7070
const queuesErrorsPath = ['app', 'wizard', 'errors', 'queues']
71+
const defaultRegion = getState(['aws', 'region'])
7172

7273
export function useClusterResourcesLimits(): ClusterResourcesLimits {
7374
const newResourcesLimits = useFeatureFlag('new_resources_limits')
@@ -203,7 +204,7 @@ function queueValidate(queueIndex: any) {
203204
}
204205

205206
const version = getState(['app', 'version', 'full'])
206-
const isMultiAZActive = isFeatureEnabled(version, 'multi_az')
207+
const isMultiAZActive = isFeatureEnabled(version, defaultRegion, 'multi_az')
207208
if (!queueSubnet) {
208209
let message: string
209210
if (isMultiAZActive) {
@@ -219,6 +220,7 @@ function queueValidate(queueIndex: any) {
219220

220221
const isMultiInstanceTypesActive = isFeatureEnabled(
221222
version,
223+
defaultRegion,
222224
'queues_multiple_instance_types',
223225
)
224226
const {validateComputeResources} = !isMultiInstanceTypesActive
@@ -246,6 +248,7 @@ function queueValidate(queueIndex: any) {
246248

247249
const isMemoryBasedSchedulingActive = isFeatureEnabled(
248250
version,
251+
defaultRegion,
249252
'memory_based_scheduling',
250253
)
251254
if (isMemoryBasedSchedulingActive) {

frontend/src/old-pages/Configure/Queues/__tests__/mapComputeResources.test.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717

1818
describe('given a mapper to import the ComputeResources section of the Scheduling config', () => {
1919
let mockVersion: string
20+
let mockRegion: string
2021

2122
describe('when the application supports multiple instance types', () => {
2223
beforeEach(() => {
@@ -49,9 +50,9 @@ describe('given a mapper to import the ComputeResources section of the Schedulin
4950
],
5051
},
5152
]
52-
expect(mapComputeResources(mockVersion, mockComputeResources)).toEqual(
53-
expected,
54-
)
53+
expect(
54+
mapComputeResources(mockVersion, mockRegion, mockComputeResources),
55+
).toEqual(expected)
5556
})
5657
})
5758
describe('when the configuration was created with the flexible instance types format', () => {
@@ -72,9 +73,9 @@ describe('given a mapper to import the ComputeResources section of the Schedulin
7273
]
7374
})
7475
it('should leave the configuration as is', () => {
75-
expect(mapComputeResources(mockVersion, mockComputeResources)).toEqual(
76-
mockComputeResources,
77-
)
76+
expect(
77+
mapComputeResources(mockVersion, mockRegion, mockComputeResources),
78+
).toEqual(mockComputeResources)
7879
})
7980
})
8081
})
@@ -95,9 +96,9 @@ describe('given a mapper to import the ComputeResources section of the Schedulin
9596
})
9697

9798
it('should leave the configuration as is', () => {
98-
expect(mapComputeResources(mockVersion, mockComputeResources)).toEqual(
99-
mockComputeResources,
100-
)
99+
expect(
100+
mapComputeResources(mockVersion, mockRegion, mockComputeResources),
101+
).toEqual(mockComputeResources)
101102
})
102103
})
103104
})

frontend/src/old-pages/Configure/Queues/queues.mapper.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,12 @@ function mapComputeResource(
3535

3636
export function mapComputeResources(
3737
version: string,
38+
region: string,
3839
computeResourcesConfig:
3940
| SingleInstanceComputeResource[]
4041
| MultiInstanceComputeResource[],
4142
) {
42-
if (!isFeatureEnabled(version, 'queues_multiple_instance_types')) {
43+
if (!isFeatureEnabled(version, region, 'queues_multiple_instance_types')) {
4344
return computeResourcesConfig
4445
}
4546

frontend/src/old-pages/Configure/util.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ function loadTemplateLazy(config: any, callback?: () => void) {
2626
const keypairNames = new Set(keypairs.map((kp: any) => kp.KeyName))
2727
const keypairPath = ['HeadNode', 'Ssh', 'KeyName']
2828
const version = getState(['app', 'version', 'full'])
29+
const defaultRegion = getState(['aws', 'region'])
2930
if (getIn(config, ['Image', 'CustomAmi']))
3031
setState(['app', 'wizard', 'customAMI', 'enabled'], true)
3132

@@ -67,7 +68,11 @@ function loadTemplateLazy(config: any, callback?: () => void) {
6768
i,
6869
'ComputeResources',
6970
])
70-
computeResources = mapComputeResources(version, computeResources)
71+
computeResources = mapComputeResources(
72+
version,
73+
defaultRegion,
74+
computeResources,
75+
)
7176
config = setIn(
7277
config,
7378
['Scheduling', 'SlurmQueues', i, 'ComputeResources'],

0 commit comments

Comments
 (0)