@spinnaker/google 2026.3.1 → 2026.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autoscalingPolicy/GceAutoScalingFieldLayout.d.ts +2 -2
- package/dist/domain/loadBalancer.d.ts +6 -3
- package/dist/image/ImageSelect.d.ts +1 -1
- package/dist/index.js +159 -1
- package/dist/index.js.map +1 -1
- package/dist/loadBalancer/configure/common/gceLoadBalancerModels.d.ts +13 -2
- package/dist/loadBalancer/configure/http/GceHttpLoadBalancerEditor.d.ts +3 -0
- package/dist/loadBalancer/configure/http/GceHttpLoadBalancerModal.d.ts +1 -1
- package/dist/loadBalancer/configure/network/GceRegionalExternalNetworkLoadBalancerEditor.d.ts +30 -0
- package/dist/loadBalancer/configure/network/GceRegionalExternalNetworkLoadBalancerModal.d.ts +53 -0
- package/dist/loadBalancer/httpLoadBalancerUtils.service.d.ts +3 -1
- package/dist/serverGroup/configure/wizard/GceCloneServerGroupModal.d.ts +3 -0
- package/dist/serverGroup/configure/wizard/GceServerGroupWizard.types.d.ts +1 -0
- package/dist/serverGroup/configure/wizard/customInstance/CustomInstanceConfigurer.d.ts +1 -1
- package/dist/serverGroup/configure/wizard/customInstance/GceCustomInstanceBuilder.d.ts +2 -2
- package/dist/serverGroup/configure/wizard/pages/AdvancedSettings.d.ts +3 -0
- package/dist/serverGroup/configure/wizard/pages/GceServerGroupLoadBalancers.d.ts +1 -0
- package/dist/serverGroup/configure/wizard/pages/Policies.d.ts +21 -3
- package/dist/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.d.ts +1 -0
- package/dist/serverGroup/configure/wizard/pages/ServerGroupCapacity.d.ts +1 -0
- package/dist/serverGroup/configure/wizard/pages/ServerGroupImageSettings.d.ts +1 -0
- package/dist/serverGroup/configure/wizard/pages/ServerGroupInstanceType.d.ts +1 -0
- package/dist/serverGroup/configure/wizard/zones/GceInstanceFlexibilityConfigurer.d.ts +2 -2
- package/dist/serverGroup/details/GceInstanceFlexibilityPolicyDetails.d.ts +2 -2
- package/dist/serverGroup/details/stateful/MarkDiskStatefulButton.d.ts +2 -2
- package/dist/serverGroup/details/stateful/UpdateBootImageButton.d.ts +2 -2
- package/package.json +5 -5
- package/src/autoHealingPolicy/GceAutoHealingPolicyEditor.spec.tsx +68 -52
- package/src/autoscalingPolicy/GceAutoscalingPolicyEditor.spec.tsx +43 -50
- package/src/autoscalingPolicy/GceAutoscalingPolicyEditor.tsx +1 -1
- package/src/autoscalingPolicy/GceAutoscalingPolicyWriter.spec.ts +1 -1
- package/src/domain/loadBalancer.ts +6 -3
- package/src/gce.module.spec.ts +132 -153
- package/src/instance/details/GceInstanceDetails.spec.tsx +86 -83
- package/src/loadBalancer/configure/choice/GceLoadBalancerChoiceModal.spec.tsx +162 -121
- package/src/loadBalancer/configure/choice/GceLoadBalancerChoiceModal.tsx +13 -1
- package/src/loadBalancer/configure/common/GceProxyLoadBalancerEditor.spec.tsx +47 -30
- package/src/loadBalancer/configure/common/GceProxyLoadBalancerEditor.tsx +2 -1
- package/src/loadBalancer/configure/common/GceProxyLoadBalancerModal.spec.tsx +85 -57
- package/src/loadBalancer/configure/common/gceLoadBalancerData.spec.ts +17 -16
- package/src/loadBalancer/configure/common/gceLoadBalancerModels.spec.ts +230 -5
- package/src/loadBalancer/configure/common/gceLoadBalancerModels.ts +186 -22
- package/src/loadBalancer/configure/common/gceLoadBalancerSubmission.spec.ts +298 -2
- package/src/loadBalancer/configure/common/gceLoadBalancerSubmission.ts +35 -5
- package/src/loadBalancer/configure/common/useGceLoadBalancerData.spec.tsx +37 -46
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerEditor.spec.tsx +399 -58
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerEditor.tsx +148 -41
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerListenerEditor.spec.tsx +169 -36
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerListenerEditor.tsx +80 -12
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerModal.spec.tsx +224 -124
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerModal.tsx +8 -2
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerResourceEditors.spec.tsx +57 -22
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerResourceEditors.tsx +21 -0
- package/src/loadBalancer/configure/http/GceHttpLoadBalancerRoutingEditor.spec.tsx +24 -20
- package/src/loadBalancer/configure/network/GceNetworkLoadBalancerEditor.spec.tsx +41 -32
- package/src/loadBalancer/configure/network/GceNetworkLoadBalancerModal.spec.tsx +35 -30
- package/src/loadBalancer/configure/network/GceRegionalExternalNetworkLoadBalancerEditor.spec.tsx +443 -0
- package/src/loadBalancer/configure/network/GceRegionalExternalNetworkLoadBalancerEditor.tsx +401 -0
- package/src/loadBalancer/configure/network/GceRegionalExternalNetworkLoadBalancerModal.spec.tsx +330 -0
- package/src/loadBalancer/configure/network/GceRegionalExternalNetworkLoadBalancerModal.tsx +348 -0
- package/src/loadBalancer/details/gceLoadBalancerDetails.spec.tsx +439 -35
- package/src/loadBalancer/details/gceLoadBalancerDetails.tsx +104 -21
- package/src/loadBalancer/httpLoadBalancerUtils.service.spec.ts +126 -0
- package/src/loadBalancer/httpLoadBalancerUtils.service.ts +27 -11
- package/src/loadBalancer/loadBalancer.setTransformer.spec.ts +165 -0
- package/src/loadBalancer/loadBalancer.setTransformer.ts +15 -2
- package/src/pipeline/stages/googleStageConfig.spec.js +22 -16
- package/src/securityGroup/configure/GceSecurityGroupModal.spec.tsx +177 -193
- package/src/securityGroup/configure/GceSecurityGroupModal.tsx +14 -2
- package/src/securityGroup/details/GceSecurityGroupDetails.spec.tsx +69 -78
- package/src/serverGroup/configure/serverGroupCommandBuilder.service.spec.js +35 -15
- package/src/serverGroup/configure/serverGroupConfiguration.service.js +7 -1
- package/src/serverGroup/configure/serverGroupConfiguration.service.spec.js +74 -4
- package/src/serverGroup/configure/wizard/GceCloneServerGroupModal.spec.tsx +593 -855
- package/src/serverGroup/configure/wizard/GceCloneServerGroupModal.tsx +120 -38
- package/src/serverGroup/configure/wizard/GceServerGroupWizard.types.ts +1 -0
- package/src/serverGroup/configure/wizard/GceServerGroupWizardPage.spec.tsx +53 -50
- package/src/serverGroup/configure/wizard/customInstance/GceCustomInstanceBuilder.spec.tsx +65 -49
- package/src/serverGroup/configure/wizard/hiddenMetadataKeys.value.js +1 -0
- package/src/serverGroup/configure/wizard/pages/AdvancedSettings.spec.tsx +101 -108
- package/src/serverGroup/configure/wizard/pages/AdvancedSettings.tsx +32 -28
- package/src/serverGroup/configure/wizard/pages/GceServerGroupFirewalls.spec.tsx +60 -59
- package/src/serverGroup/configure/wizard/pages/GceServerGroupLoadBalancers.spec.tsx +240 -114
- package/src/serverGroup/configure/wizard/pages/GceServerGroupLoadBalancers.tsx +152 -63
- package/src/serverGroup/configure/wizard/pages/Policies.spec.tsx +93 -48
- package/src/serverGroup/configure/wizard/pages/Policies.tsx +80 -55
- package/src/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.spec.tsx +123 -94
- package/src/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.tsx +24 -18
- package/src/serverGroup/configure/wizard/pages/ServerGroupCapacity.spec.tsx +152 -133
- package/src/serverGroup/configure/wizard/pages/ServerGroupCapacity.tsx +40 -37
- package/src/serverGroup/configure/wizard/pages/ServerGroupImageSettings.spec.tsx +66 -60
- package/src/serverGroup/configure/wizard/pages/ServerGroupImageSettings.tsx +8 -2
- package/src/serverGroup/configure/wizard/pages/ServerGroupInstanceType.spec.tsx +131 -101
- package/src/serverGroup/configure/wizard/pages/ServerGroupInstanceType.tsx +29 -28
- package/src/serverGroup/configure/wizard/zones/GceInstanceFlexibilityConfigurer.spec.tsx +104 -81
- package/src/serverGroup/details/GceInstanceFlexibilityPolicyDetails.spec.tsx +10 -11
- package/src/serverGroup/details/autoHealingPolicy/GceAutoHealingPolicyDetails.spec.tsx +51 -59
- package/src/serverGroup/details/autoHealingPolicy/modal/GceUpsertAutoHealingPolicyModal.spec.tsx +3 -3
- package/src/serverGroup/details/autoscalingPolicy/GceAutoscalingPolicyDetails.spec.tsx +49 -58
- package/src/serverGroup/details/autoscalingPolicy/modal/GceUpsertAutoscalingPolicyModal.spec.tsx +3 -3
- package/src/serverGroup/details/gceServerGroupDetails.spec.tsx +162 -141
- package/src/serverGroup/details/resize/GceResizeServerGroupModal.spec.tsx +102 -86
- package/src/serverGroup/details/resize/GceResizeServerGroupModal.tsx +4 -0
- package/src/serverGroup/details/rollback/GceRollbackServerGroupModal.spec.tsx +40 -31
- package/src/serverGroup/serverGroup.transformer.js +1 -0
- package/src/serverGroup/serverGroup.transformer.spec.js +48 -0
- package/src/validation/ApplicationNameValidator.spec.ts +1 -1
- /package/dist/{gce.logo2ae85d8704b1d6b8.png → gce.logoChI3w_A5.png} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { AccountService, ReactModal } from '@spinnaker/core';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
buildGceAutoscalerResizeRequest,
|
|
@@ -10,7 +10,23 @@ import {
|
|
|
10
10
|
validateGceResizeValues,
|
|
11
11
|
} from './GceResizeServerGroupModal';
|
|
12
12
|
|
|
13
|
+
vi.mock('@spinnaker/core', async (importOriginal) => {
|
|
14
|
+
const actual = await importOriginal<typeof import('@spinnaker/core')>();
|
|
15
|
+
const ReactModule = await import('react');
|
|
16
|
+
return {
|
|
17
|
+
...actual,
|
|
18
|
+
TaskMonitorWrapper: ({ monitor }: any) =>
|
|
19
|
+
ReactModule.createElement(
|
|
20
|
+
'button',
|
|
21
|
+
{ onClick: () => monitor.closeModal(), type: 'button' },
|
|
22
|
+
'Close monitored task',
|
|
23
|
+
),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
|
|
13
27
|
describe('GceResizeServerGroupModal', () => {
|
|
28
|
+
beforeEach(() => vi.spyOn(AccountService, 'challengeDestructiveActions').mockResolvedValue(true));
|
|
29
|
+
|
|
14
30
|
it('rejects autoscaler minimum capacity greater than maximum capacity', () => {
|
|
15
31
|
const serverGroup = {
|
|
16
32
|
autoscalingPolicy: { minNumReplicas: 1, maxNumReplicas: 10 },
|
|
@@ -125,11 +141,11 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
125
141
|
});
|
|
126
142
|
|
|
127
143
|
it('renders fixed-capacity mode for a server group without an autoscaler', () => {
|
|
128
|
-
|
|
144
|
+
render(
|
|
129
145
|
<GceResizeServerGroupModal
|
|
130
|
-
application={{ name: 'fnord', serverGroups: { refresh:
|
|
131
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
132
|
-
dismissModal={
|
|
146
|
+
application={{ name: 'fnord', serverGroups: { refresh: vi.fn() } } as any}
|
|
147
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
148
|
+
dismissModal={vi.fn()}
|
|
133
149
|
serverGroup={
|
|
134
150
|
{
|
|
135
151
|
account: 'prod',
|
|
@@ -138,20 +154,20 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
138
154
|
region: 'us-central1',
|
|
139
155
|
} as any
|
|
140
156
|
}
|
|
141
|
-
serverGroupWriter={{ resizeServerGroup:
|
|
157
|
+
serverGroupWriter={{ resizeServerGroup: vi.fn() } as any}
|
|
142
158
|
/>,
|
|
143
159
|
);
|
|
144
160
|
|
|
145
|
-
expect(
|
|
146
|
-
expect(
|
|
161
|
+
expect(screen.getByRole('spinbutton', { name: 'Resize to' })).toBeInTheDocument();
|
|
162
|
+
expect(screen.getByText('Sets desired instance count for this server group.')).toBeInTheDocument();
|
|
147
163
|
});
|
|
148
164
|
|
|
149
165
|
it('renders min/max mode for a server group with an autoscaler', () => {
|
|
150
|
-
|
|
166
|
+
render(
|
|
151
167
|
<GceResizeServerGroupModal
|
|
152
|
-
application={{ name: 'fnord', serverGroups: { refresh:
|
|
153
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
154
|
-
dismissModal={
|
|
168
|
+
application={{ name: 'fnord', serverGroups: { refresh: vi.fn() } } as any}
|
|
169
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
170
|
+
dismissModal={vi.fn()}
|
|
155
171
|
serverGroup={
|
|
156
172
|
{
|
|
157
173
|
account: 'prod',
|
|
@@ -160,27 +176,27 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
160
176
|
region: 'us-central1',
|
|
161
177
|
} as any
|
|
162
178
|
}
|
|
163
|
-
serverGroupWriter={{ resizeServerGroup:
|
|
179
|
+
serverGroupWriter={{ resizeServerGroup: vi.fn() } as any}
|
|
164
180
|
/>,
|
|
165
181
|
);
|
|
166
182
|
|
|
167
|
-
expect(
|
|
168
|
-
expect(
|
|
169
|
-
expect(
|
|
183
|
+
expect(screen.getByRole('spinbutton', { name: 'Minimum replicas' })).toBeInTheDocument();
|
|
184
|
+
expect(screen.getByRole('spinbutton', { name: 'Maximum replicas' })).toBeInTheDocument();
|
|
185
|
+
expect(screen.queryByRole('spinbutton', { name: 'Resize to' })).not.toBeInTheDocument();
|
|
170
186
|
});
|
|
171
187
|
|
|
172
188
|
it('renders reason, account verification, and the Google platform-health override', () => {
|
|
173
|
-
|
|
189
|
+
render(
|
|
174
190
|
<GceResizeServerGroupModal
|
|
175
191
|
application={
|
|
176
192
|
{
|
|
177
193
|
attributes: { platformHealthOnly: true, platformHealthOnlyShowOverride: true },
|
|
178
194
|
name: 'fnord',
|
|
179
|
-
serverGroups: { refresh:
|
|
195
|
+
serverGroups: { refresh: vi.fn() },
|
|
180
196
|
} as any
|
|
181
197
|
}
|
|
182
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
183
|
-
dismissModal={
|
|
198
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
199
|
+
dismissModal={vi.fn()}
|
|
184
200
|
serverGroup={
|
|
185
201
|
{
|
|
186
202
|
account: 'prod',
|
|
@@ -189,20 +205,20 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
189
205
|
region: 'us-central1',
|
|
190
206
|
} as any
|
|
191
207
|
}
|
|
192
|
-
serverGroupWriter={{ resizeServerGroup:
|
|
208
|
+
serverGroupWriter={{ resizeServerGroup: vi.fn() } as any}
|
|
193
209
|
/>,
|
|
194
210
|
);
|
|
195
211
|
|
|
196
|
-
expect(
|
|
197
|
-
expect(
|
|
198
|
-
expect(
|
|
212
|
+
expect(screen.getByRole('textbox', { name: 'Reason' })).toBeInTheDocument();
|
|
213
|
+
expect(screen.getByText(/Type the name of the account/)).toHaveTextContent('prod');
|
|
214
|
+
expect(screen.getByRole('checkbox', { name: 'Consider only Google health' })).toBeChecked();
|
|
199
215
|
});
|
|
200
216
|
|
|
201
|
-
it('submits fixed capacity through the server group writer after verification', () => {
|
|
217
|
+
it('submits fixed capacity through the server group writer after verification', async () => {
|
|
202
218
|
const application = {
|
|
203
219
|
attributes: { platformHealthOnly: true, platformHealthOnlyShowOverride: true },
|
|
204
220
|
name: 'fnord',
|
|
205
|
-
serverGroups: { refresh:
|
|
221
|
+
serverGroups: { refresh: vi.fn() },
|
|
206
222
|
} as any;
|
|
207
223
|
const serverGroup = {
|
|
208
224
|
account: 'prod',
|
|
@@ -210,24 +226,23 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
210
226
|
name: 'fnord-main-v004',
|
|
211
227
|
region: 'us-central1',
|
|
212
228
|
} as any;
|
|
213
|
-
const resizeServerGroup =
|
|
214
|
-
|
|
229
|
+
const resizeServerGroup = vi.fn().mockReturnValue(new Promise(() => undefined));
|
|
230
|
+
render(
|
|
215
231
|
<GceResizeServerGroupModal
|
|
216
232
|
application={application}
|
|
217
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
218
|
-
dismissModal={
|
|
233
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
234
|
+
dismissModal={vi.fn()}
|
|
219
235
|
serverGroup={serverGroup}
|
|
220
236
|
serverGroupWriter={{ resizeServerGroup }}
|
|
221
237
|
/>,
|
|
222
238
|
);
|
|
223
239
|
|
|
224
|
-
expect(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
wrapper.find('button.btn-primary').simulate('click');
|
|
240
|
+
expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
|
|
241
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Resize to' }), { target: { value: '6' } });
|
|
242
|
+
fireEvent.change(screen.getByRole('textbox', { name: 'Reason' }), { target: { value: 'capacity adjustment' } });
|
|
243
|
+
fireEvent.change(screen.getByRole('textbox', { name: 'Confirm account prod' }), { target: { value: 'prod' } });
|
|
244
|
+
await waitFor(() => expect(screen.getByRole('button', { name: 'Submit' })).toBeEnabled());
|
|
245
|
+
fireEvent.click(screen.getByRole('button', { name: 'Submit' }));
|
|
231
246
|
|
|
232
247
|
expect(resizeServerGroup).toHaveBeenCalledWith(serverGroup, application, {
|
|
233
248
|
capacity: { desired: 6, max: 6, min: 6 },
|
|
@@ -239,11 +254,11 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
239
254
|
});
|
|
240
255
|
});
|
|
241
256
|
|
|
242
|
-
it('submits autoscaler bounds through the injected policy writer after verification', () => {
|
|
257
|
+
it('submits autoscaler bounds through the injected policy writer after verification', async () => {
|
|
243
258
|
const application = {
|
|
244
259
|
attributes: { platformHealthOnly: true, platformHealthOnlyShowOverride: true },
|
|
245
260
|
name: 'fnord',
|
|
246
|
-
serverGroups: { refresh:
|
|
261
|
+
serverGroups: { refresh: vi.fn() },
|
|
247
262
|
} as any;
|
|
248
263
|
const serverGroup = {
|
|
249
264
|
account: 'prod',
|
|
@@ -251,25 +266,26 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
251
266
|
name: 'fnord-main-v004',
|
|
252
267
|
region: 'us-central1',
|
|
253
268
|
} as any;
|
|
254
|
-
const upsertAutoscalingPolicy =
|
|
255
|
-
const resizeServerGroup =
|
|
256
|
-
|
|
269
|
+
const upsertAutoscalingPolicy = vi.fn().mockReturnValue(new Promise(() => undefined));
|
|
270
|
+
const resizeServerGroup = vi.fn();
|
|
271
|
+
render(
|
|
257
272
|
<GceResizeServerGroupModal
|
|
258
273
|
application={application}
|
|
259
274
|
autoscalingPolicyWriter={{ upsertAutoscalingPolicy }}
|
|
260
|
-
dismissModal={
|
|
275
|
+
dismissModal={vi.fn()}
|
|
261
276
|
serverGroup={serverGroup}
|
|
262
277
|
serverGroupWriter={{ resizeServerGroup } as any}
|
|
263
278
|
/>,
|
|
264
279
|
);
|
|
265
280
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
281
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Minimum replicas' }), { target: { value: '3' } });
|
|
282
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Maximum replicas' }), { target: { value: '12' } });
|
|
283
|
+
fireEvent.change(screen.getByRole('textbox', { name: 'Reason' }), {
|
|
284
|
+
target: { value: 'raise autoscaling ceiling' },
|
|
285
|
+
});
|
|
286
|
+
fireEvent.change(screen.getByRole('textbox', { name: 'Confirm account prod' }), { target: { value: 'prod' } });
|
|
287
|
+
await waitFor(() => expect(screen.getByRole('button', { name: 'Submit' })).toBeEnabled());
|
|
288
|
+
fireEvent.click(screen.getByRole('button', { name: 'Submit' }));
|
|
273
289
|
|
|
274
290
|
expect(resizeServerGroup).not.toHaveBeenCalled();
|
|
275
291
|
expect(upsertAutoscalingPolicy).toHaveBeenCalledWith(
|
|
@@ -284,11 +300,11 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
284
300
|
});
|
|
285
301
|
|
|
286
302
|
it('surfaces invalid autoscaler min/max validation', () => {
|
|
287
|
-
|
|
303
|
+
render(
|
|
288
304
|
<GceResizeServerGroupModal
|
|
289
|
-
application={{ name: 'fnord', serverGroups: { refresh:
|
|
290
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
291
|
-
dismissModal={
|
|
305
|
+
application={{ name: 'fnord', serverGroups: { refresh: vi.fn() } } as any}
|
|
306
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
307
|
+
dismissModal={vi.fn()}
|
|
292
308
|
serverGroup={
|
|
293
309
|
{
|
|
294
310
|
account: 'prod',
|
|
@@ -297,24 +313,24 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
297
313
|
region: 'us-central1',
|
|
298
314
|
} as any
|
|
299
315
|
}
|
|
300
|
-
serverGroupWriter={{ resizeServerGroup:
|
|
316
|
+
serverGroupWriter={{ resizeServerGroup: vi.fn() } as any}
|
|
301
317
|
/>,
|
|
302
318
|
);
|
|
303
319
|
|
|
304
|
-
|
|
305
|
-
|
|
320
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Minimum replicas' }), { target: { value: '8' } });
|
|
321
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Maximum replicas' }), { target: { value: '4' } });
|
|
306
322
|
|
|
307
|
-
expect(
|
|
323
|
+
expect(screen.getByText('Min cannot be larger than Max')).toBeInTheDocument();
|
|
308
324
|
});
|
|
309
325
|
|
|
310
326
|
it('opens as a standalone React modal', () => {
|
|
311
327
|
const props = {
|
|
312
328
|
application: { name: 'fnord' },
|
|
313
|
-
autoscalingPolicyWriter: { upsertAutoscalingPolicy:
|
|
329
|
+
autoscalingPolicyWriter: { upsertAutoscalingPolicy: vi.fn() },
|
|
314
330
|
serverGroup: { account: 'prod', name: 'fnord-main-v004', region: 'us-central1' },
|
|
315
|
-
serverGroupWriter: { resizeServerGroup:
|
|
331
|
+
serverGroupWriter: { resizeServerGroup: vi.fn() },
|
|
316
332
|
} as any;
|
|
317
|
-
const show = spyOn(ReactModal, 'show').
|
|
333
|
+
const show = vi.spyOn(ReactModal, 'show').mockReturnValue(Promise.resolve({}) as any);
|
|
318
334
|
|
|
319
335
|
GceResizeServerGroupModal.show(props);
|
|
320
336
|
|
|
@@ -322,11 +338,11 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
322
338
|
});
|
|
323
339
|
|
|
324
340
|
it('keeps submit disabled when fixed capacity is cleared', () => {
|
|
325
|
-
|
|
341
|
+
render(
|
|
326
342
|
<GceResizeServerGroupModal
|
|
327
|
-
application={{ name: 'fnord', serverGroups: { refresh:
|
|
328
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
329
|
-
dismissModal={
|
|
343
|
+
application={{ name: 'fnord', serverGroups: { refresh: vi.fn() } } as any}
|
|
344
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
345
|
+
dismissModal={vi.fn()}
|
|
330
346
|
serverGroup={
|
|
331
347
|
{
|
|
332
348
|
account: 'prod',
|
|
@@ -335,23 +351,23 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
335
351
|
region: 'us-central1',
|
|
336
352
|
} as any
|
|
337
353
|
}
|
|
338
|
-
serverGroupWriter={{ resizeServerGroup:
|
|
354
|
+
serverGroupWriter={{ resizeServerGroup: vi.fn() } as any}
|
|
339
355
|
/>,
|
|
340
356
|
);
|
|
341
357
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
358
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Resize to' }), { target: { value: '6' } });
|
|
359
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Resize to' }), { target: { value: '' } });
|
|
360
|
+
fireEvent.change(screen.getByRole('textbox', { name: 'Confirm account prod' }), { target: { value: 'prod' } });
|
|
345
361
|
|
|
346
|
-
expect(
|
|
362
|
+
expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
|
|
347
363
|
});
|
|
348
364
|
|
|
349
365
|
it('requires autoscaler bounds after an input is cleared', () => {
|
|
350
|
-
|
|
366
|
+
render(
|
|
351
367
|
<GceResizeServerGroupModal
|
|
352
|
-
application={{ name: 'fnord', serverGroups: { refresh:
|
|
353
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
354
|
-
dismissModal={
|
|
368
|
+
application={{ name: 'fnord', serverGroups: { refresh: vi.fn() } } as any}
|
|
369
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
370
|
+
dismissModal={vi.fn()}
|
|
355
371
|
serverGroup={
|
|
356
372
|
{
|
|
357
373
|
account: 'prod',
|
|
@@ -360,30 +376,30 @@ describe('GceResizeServerGroupModal', () => {
|
|
|
360
376
|
region: 'us-central1',
|
|
361
377
|
} as any
|
|
362
378
|
}
|
|
363
|
-
serverGroupWriter={{ resizeServerGroup:
|
|
379
|
+
serverGroupWriter={{ resizeServerGroup: vi.fn() } as any}
|
|
364
380
|
/>,
|
|
365
381
|
);
|
|
366
382
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
383
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Minimum replicas' }), { target: { value: '3' } });
|
|
384
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Maximum replicas' }), { target: { value: '12' } });
|
|
385
|
+
fireEvent.change(screen.getByRole('spinbutton', { name: 'Minimum replicas' }), { target: { value: '' } });
|
|
370
386
|
|
|
371
|
-
expect(
|
|
387
|
+
expect(screen.getByText('Min is required')).toBeInTheDocument();
|
|
372
388
|
});
|
|
373
389
|
|
|
374
390
|
it('dismisses the modal from the task monitor', () => {
|
|
375
|
-
const dismissModal =
|
|
376
|
-
|
|
391
|
+
const dismissModal = vi.fn();
|
|
392
|
+
render(
|
|
377
393
|
<GceResizeServerGroupModal
|
|
378
|
-
application={{ name: 'fnord', serverGroups: { refresh:
|
|
379
|
-
autoscalingPolicyWriter={{ upsertAutoscalingPolicy:
|
|
394
|
+
application={{ name: 'fnord', serverGroups: { refresh: vi.fn() } } as any}
|
|
395
|
+
autoscalingPolicyWriter={{ upsertAutoscalingPolicy: vi.fn() } as any}
|
|
380
396
|
dismissModal={dismissModal}
|
|
381
397
|
serverGroup={{ account: 'prod', name: 'fnord-main-v004', region: 'us-central1' } as any}
|
|
382
|
-
serverGroupWriter={{ resizeServerGroup:
|
|
398
|
+
serverGroupWriter={{ resizeServerGroup: vi.fn() } as any}
|
|
383
399
|
/>,
|
|
384
400
|
);
|
|
385
401
|
|
|
386
|
-
(
|
|
402
|
+
fireEvent.click(screen.getByRole('button', { name: 'Close monitored task' }));
|
|
387
403
|
|
|
388
404
|
expect(dismissModal).toHaveBeenCalled();
|
|
389
405
|
});
|
|
@@ -227,6 +227,7 @@ export class GceResizeServerGroupModal extends React.Component<
|
|
|
227
227
|
<label className="col-md-3 sm-label-right">Current</label>
|
|
228
228
|
<div className="col-md-2">
|
|
229
229
|
<input
|
|
230
|
+
aria-label="Current minimum replicas"
|
|
230
231
|
className="form-control input-sm"
|
|
231
232
|
disabled={true}
|
|
232
233
|
type="number"
|
|
@@ -235,6 +236,7 @@ export class GceResizeServerGroupModal extends React.Component<
|
|
|
235
236
|
</div>
|
|
236
237
|
<div className="col-md-2">
|
|
237
238
|
<input
|
|
239
|
+
aria-label="Current maximum replicas"
|
|
238
240
|
className="form-control input-sm"
|
|
239
241
|
disabled={true}
|
|
240
242
|
type="number"
|
|
@@ -246,6 +248,7 @@ export class GceResizeServerGroupModal extends React.Component<
|
|
|
246
248
|
<label className="col-md-3 sm-label-right">Resize to</label>
|
|
247
249
|
<div className="col-md-2">
|
|
248
250
|
<input
|
|
251
|
+
aria-label="Minimum replicas"
|
|
249
252
|
className="form-control input-sm"
|
|
250
253
|
min={0}
|
|
251
254
|
name="newMinNumReplicas"
|
|
@@ -263,6 +266,7 @@ export class GceResizeServerGroupModal extends React.Component<
|
|
|
263
266
|
</div>
|
|
264
267
|
<div className="col-md-2">
|
|
265
268
|
<input
|
|
269
|
+
aria-label="Maximum replicas"
|
|
266
270
|
className="form-control input-sm"
|
|
267
271
|
min={0}
|
|
268
272
|
name="newMaxNumReplicas"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { AccountService } from '@spinnaker/core';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
buildGceRollbackJob,
|
|
@@ -9,6 +9,20 @@ import {
|
|
|
9
9
|
getGceRollbackCandidates,
|
|
10
10
|
} from './GceRollbackServerGroupModal';
|
|
11
11
|
|
|
12
|
+
vi.mock('@spinnaker/core', async (importOriginal) => {
|
|
13
|
+
const actual = await importOriginal<typeof import('@spinnaker/core')>();
|
|
14
|
+
const ReactModule = await import('react');
|
|
15
|
+
return {
|
|
16
|
+
...actual,
|
|
17
|
+
TaskMonitorWrapper: ({ monitor }: any) =>
|
|
18
|
+
ReactModule.createElement(
|
|
19
|
+
'button',
|
|
20
|
+
{ onClick: () => monitor.closeModal(), type: 'button' },
|
|
21
|
+
'Close monitored task',
|
|
22
|
+
),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
|
|
12
26
|
describe('GceRollbackServerGroupModal', () => {
|
|
13
27
|
const application = { name: 'fnord' } as any;
|
|
14
28
|
const serverGroup = {
|
|
@@ -19,6 +33,8 @@ describe('GceRollbackServerGroupModal', () => {
|
|
|
19
33
|
region: 'us-central1',
|
|
20
34
|
} as any;
|
|
21
35
|
|
|
36
|
+
beforeEach(() => vi.spyOn(AccountService, 'challengeDestructiveActions').mockResolvedValue(true));
|
|
37
|
+
|
|
22
38
|
it('keeps only disabled candidates in the same application, cluster, account, and region', () => {
|
|
23
39
|
const eligible = {
|
|
24
40
|
account: 'prod',
|
|
@@ -78,7 +94,7 @@ describe('GceRollbackServerGroupModal', () => {
|
|
|
78
94
|
});
|
|
79
95
|
|
|
80
96
|
it('renders reason, account verification, and the Google platform-health override', () => {
|
|
81
|
-
|
|
97
|
+
render(
|
|
82
98
|
<GceRollbackServerGroupModal
|
|
83
99
|
application={
|
|
84
100
|
{
|
|
@@ -86,28 +102,23 @@ describe('GceRollbackServerGroupModal', () => {
|
|
|
86
102
|
name: 'fnord',
|
|
87
103
|
} as any
|
|
88
104
|
}
|
|
89
|
-
dismissModal={
|
|
105
|
+
dismissModal={vi.fn()}
|
|
90
106
|
serverGroup={serverGroup}
|
|
91
107
|
serverGroups={[]}
|
|
92
|
-
serverGroupWriter={{ rollbackServerGroup:
|
|
108
|
+
serverGroupWriter={{ rollbackServerGroup: vi.fn() } as any}
|
|
93
109
|
/>,
|
|
94
110
|
);
|
|
95
111
|
|
|
96
|
-
expect(
|
|
97
|
-
expect(
|
|
98
|
-
expect(
|
|
99
|
-
jasmine.objectContaining({
|
|
100
|
-
interestingHealthProviderNames: ['Google'],
|
|
101
|
-
platformHealthType: 'Google',
|
|
102
|
-
}),
|
|
103
|
-
);
|
|
112
|
+
expect(screen.getByRole('textbox', { name: 'Reason' })).toBeInTheDocument();
|
|
113
|
+
expect(screen.getByText(/Type the name of the account/)).toHaveTextContent('prod');
|
|
114
|
+
expect(screen.getByRole('checkbox', { name: 'Consider only Google health' })).toBeChecked();
|
|
104
115
|
});
|
|
105
116
|
|
|
106
|
-
it('submits the exact rollback writer job only after account verification', () => {
|
|
117
|
+
it('submits the exact rollback writer job only after account verification', async () => {
|
|
107
118
|
const applicationWithHealthOverride = {
|
|
108
119
|
attributes: { platformHealthOnly: true, platformHealthOnlyShowOverride: true },
|
|
109
120
|
name: 'fnord',
|
|
110
|
-
serverGroups: { refresh:
|
|
121
|
+
serverGroups: { refresh: vi.fn() },
|
|
111
122
|
} as any;
|
|
112
123
|
const candidate = {
|
|
113
124
|
account: 'prod',
|
|
@@ -117,25 +128,23 @@ describe('GceRollbackServerGroupModal', () => {
|
|
|
117
128
|
name: 'fnord-main-v003',
|
|
118
129
|
region: 'us-central1',
|
|
119
130
|
} as any;
|
|
120
|
-
const rollbackServerGroup =
|
|
121
|
-
|
|
131
|
+
const rollbackServerGroup = vi.fn().mockReturnValue(new Promise(() => undefined));
|
|
132
|
+
render(
|
|
122
133
|
<GceRollbackServerGroupModal
|
|
123
134
|
application={applicationWithHealthOverride}
|
|
124
|
-
dismissModal={
|
|
135
|
+
dismissModal={vi.fn()}
|
|
125
136
|
serverGroup={serverGroup}
|
|
126
137
|
serverGroups={[candidate]}
|
|
127
138
|
serverGroupWriter={{ rollbackServerGroup }}
|
|
128
139
|
/>,
|
|
129
140
|
);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
wrapper.find('select').simulate('change', { target: { value: candidate.name } });
|
|
134
|
-
wrapper.find(TaskReason).prop('onChange')('bad release');
|
|
135
|
-
expect(wrapper.find('button.btn-primary').prop('disabled')).toBe(true);
|
|
141
|
+
fireEvent.change(screen.getByRole('combobox', { name: 'Restore to' }), { target: { value: candidate.name } });
|
|
142
|
+
fireEvent.change(screen.getByRole('textbox', { name: 'Reason' }), { target: { value: 'bad release' } });
|
|
143
|
+
expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled();
|
|
136
144
|
|
|
137
|
-
|
|
138
|
-
|
|
145
|
+
fireEvent.change(screen.getByRole('textbox', { name: 'Confirm account prod' }), { target: { value: 'prod' } });
|
|
146
|
+
await waitFor(() => expect(screen.getByRole('button', { name: 'Submit' })).toBeEnabled());
|
|
147
|
+
fireEvent.click(screen.getByRole('button', { name: 'Submit' }));
|
|
139
148
|
|
|
140
149
|
expect(rollbackServerGroup).toHaveBeenCalledWith(serverGroup, applicationWithHealthOverride, {
|
|
141
150
|
interestingHealthProviderNames: ['Google'],
|
|
@@ -150,18 +159,18 @@ describe('GceRollbackServerGroupModal', () => {
|
|
|
150
159
|
});
|
|
151
160
|
|
|
152
161
|
it('dismisses the modal from the task monitor', () => {
|
|
153
|
-
const dismissModal =
|
|
154
|
-
|
|
162
|
+
const dismissModal = vi.fn();
|
|
163
|
+
render(
|
|
155
164
|
<GceRollbackServerGroupModal
|
|
156
|
-
application={{ name: 'fnord', serverGroups: { refresh:
|
|
165
|
+
application={{ name: 'fnord', serverGroups: { refresh: vi.fn() } } as any}
|
|
157
166
|
dismissModal={dismissModal}
|
|
158
167
|
serverGroup={serverGroup}
|
|
159
168
|
serverGroups={[]}
|
|
160
|
-
serverGroupWriter={{ rollbackServerGroup:
|
|
169
|
+
serverGroupWriter={{ rollbackServerGroup: vi.fn() } as any}
|
|
161
170
|
/>,
|
|
162
171
|
);
|
|
163
172
|
|
|
164
|
-
(
|
|
173
|
+
fireEvent.click(screen.getByRole('button', { name: 'Close monitored task' }));
|
|
165
174
|
|
|
166
175
|
expect(dismissModal).toHaveBeenCalled();
|
|
167
176
|
});
|
|
@@ -47,6 +47,54 @@ describe('gceServerGroupTransformer', () => {
|
|
|
47
47
|
expect(normalizedServerGroup.loadBalancers.includes('network-load-balancer')).toEqual(true);
|
|
48
48
|
expect(normalizedServerGroup.loadBalancers.includes('internal-load-balancer')).toEqual(true);
|
|
49
49
|
});
|
|
50
|
+
|
|
51
|
+
it('scopes EXTERNAL_MANAGED listener normalization by server group region', async function () {
|
|
52
|
+
app = {
|
|
53
|
+
getDataSource: () => ({
|
|
54
|
+
ready: () => Promise.resolve(),
|
|
55
|
+
data: [
|
|
56
|
+
{
|
|
57
|
+
account: 'my-google-account',
|
|
58
|
+
listeners: [{ name: 'external-listener' }],
|
|
59
|
+
loadBalancerType: 'EXTERNAL_MANAGED',
|
|
60
|
+
name: 'app-main (my-google-account/us-central1/EXTERNAL_MANAGED)',
|
|
61
|
+
provider: 'gce',
|
|
62
|
+
region: 'us-central1',
|
|
63
|
+
urlMapName: 'app-main',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
account: 'my-google-account',
|
|
67
|
+
listeners: [{ name: 'external-listener' }],
|
|
68
|
+
loadBalancerType: 'EXTERNAL_MANAGED',
|
|
69
|
+
name: 'app-main (my-google-account/europe-west1/EXTERNAL_MANAGED)',
|
|
70
|
+
provider: 'gce',
|
|
71
|
+
region: 'europe-west1',
|
|
72
|
+
urlMapName: 'app-main',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const centralServerGroup = await transformer.normalizeServerGroup(
|
|
79
|
+
{
|
|
80
|
+
account: 'my-google-account',
|
|
81
|
+
region: 'us-central1',
|
|
82
|
+
loadBalancers: ['external-listener'],
|
|
83
|
+
},
|
|
84
|
+
app,
|
|
85
|
+
);
|
|
86
|
+
const europeServerGroup = await transformer.normalizeServerGroup(
|
|
87
|
+
{
|
|
88
|
+
account: 'my-google-account',
|
|
89
|
+
region: 'europe-west1',
|
|
90
|
+
loadBalancers: ['external-listener'],
|
|
91
|
+
},
|
|
92
|
+
app,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
expect(centralServerGroup.loadBalancers).toEqual(['app-main (my-google-account/us-central1/EXTERNAL_MANAGED)']);
|
|
96
|
+
expect(europeServerGroup.loadBalancers).toEqual(['app-main (my-google-account/europe-west1/EXTERNAL_MANAGED)']);
|
|
97
|
+
});
|
|
50
98
|
});
|
|
51
99
|
|
|
52
100
|
describe('convert server group command to deploy configuration', () => {
|
|
@@ -32,7 +32,7 @@ describe('Google application name validator', () => {
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
it('is registered directly when the Google module is imported', async () => {
|
|
35
|
-
spyOn(AccountService, 'listProviders').
|
|
35
|
+
vi.spyOn(AccountService, 'listProviders').mockReturnValue(Promise.resolve(['gce']));
|
|
36
36
|
|
|
37
37
|
const result = await ApplicationNameValidator.validate('invalid-name', ['gce']);
|
|
38
38
|
|
|
File without changes
|