@spinnaker/cloudfoundry 2026.2.2 → 2026.3.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/image/image.reader.cf.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/instance/details/CloudFoundryInstanceActions.d.ts +5 -2
- package/dist/loadBalancer/configure/CloudFoundryMapLoadBalancerModal.d.ts +5 -4
- package/dist/loadBalancer/details/CloudFoundryLoadBalancerActions.d.ts +5 -2
- package/dist/loadBalancer/loadBalancer.transformer.d.ts +2 -5
- package/dist/pipeline/stages/cloneServerGroup/CloudFoundryCloneServerGroupStageConfig.d.ts +3 -0
- package/dist/serverGroup/configure/serverGroupCommandBuilderShim.service.cf.d.ts +5 -9
- package/dist/serverGroup/configure/wizard/CreateServerGroupModal.d.ts +5 -3
- package/dist/serverGroup/details/cloudFoundryServerGroupActions.d.ts +8 -2
- package/dist/serverGroup/details/mapLoadBalancers/CloudFoundryMapLoadBalancersModal.d.ts +5 -3
- package/dist/serverGroup/details/mapLoadBalancers/CloudFoundryUnmapLoadBalancersModal.d.ts +5 -3
- package/dist/serverGroup/details/resize/CloudFoundryResizeServerGroupModal.d.ts +5 -3
- package/dist/serverGroup/details/rollback/CloudFoundryRollbackServerGroupModal.d.ts +5 -3
- package/dist/serverGroup/serverGroup.transformer.d.ts +1 -4
- package/package.json +3 -9
- package/src/image/image.reader.cf.ts +1 -1
- package/src/instance/details/CloudFoundryInstanceActions.tsx +11 -6
- package/src/instance/details/CloudFoundryInstanceDetails.tsx +0 -2
- package/src/loadBalancer/configure/CloudFoundryMapLoadBalancerModal.tsx +10 -16
- package/src/loadBalancer/details/CloudFoundryLoadBalancerActions.tsx +10 -7
- package/src/loadBalancer/details/CloudFoundryLoadBalancerDetails.tsx +1 -3
- package/src/loadBalancer/loadBalancer.transformer.ts +3 -6
- package/src/pipeline/stages/cloneServerGroup/CloudFoundryCloneServerGroupStageConfig.tsx +13 -7
- package/src/pipeline/stages/createServiceBindings/CloudFoundryCreateServiceBindingsStageConfigForm.tsx +1 -2
- package/src/pipeline/stages/createServiceBindings/cloudFoundryCreateServiceBindingsStageForm.spec.tsx +25 -21
- package/src/pipeline/stages/deleteServiceBindings/CloudFoundryDeleteServiceBindingsStageConfigForm.tsx +1 -2
- package/src/pipeline/stages/deleteServiceBindings/cloudFoundryDeleteServiceBindingsStageForm.spec.tsx +23 -18
- package/src/pipeline/stages/resizeAsg/CloudFoundryResizeAsgStageConfig.tsx +1 -2
- package/src/pipeline/stages/rollbackCluster/cloudFoundryRollbackClusterStage.module.ts +0 -1
- package/src/pipeline/stages/runJob/CloudFoundryRunJobStageConfig.tsx +1 -2
- package/src/pipeline/stages/unshareService/cloudFoundryUnshareServiceStage.module.ts +0 -1
- package/src/presentation/pipeline/stages/CloudFoundryAsgStageConfig.tsx +1 -2
- package/src/presentation/pipeline/stages/CloudFoundryLoadBalancersStageConfig.tsx +1 -2
- package/src/presentation/widgets/accountRegionClusterSelector/AccountRegionClusterSelector.spec.tsx +41 -43
- package/src/routerActions.spec.tsx +76 -0
- package/src/serverGroup/configure/serverGroupCommandBuilderShim.service.cf.ts +12 -18
- package/src/serverGroup/configure/wizard/CreateServerGroupModal.tsx +13 -7
- package/src/serverGroup/details/cfServerGroupDetailsGetter.ts +1 -1
- package/src/serverGroup/details/cloudFoundryServerGroupActions.tsx +39 -25
- package/src/serverGroup/details/mapLoadBalancers/CloudFoundryMapLoadBalancersModal.tsx +19 -6
- package/src/serverGroup/details/mapLoadBalancers/CloudFoundryUnmapLoadBalancersModal.tsx +19 -6
- package/src/serverGroup/details/resize/CloudFoundryResizeServerGroupModal.tsx +19 -6
- package/src/serverGroup/details/rollback/CloudFoundryRollbackServerGroupModal.tsx +13 -6
- package/src/serverGroup/serverGroup.transformer.ts +2 -5
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { mount } from 'enzyme';
|
|
1
|
+
import type { Application, IStage } from 'core';
|
|
2
|
+
import { AccountService, StageConfigField } from 'core';
|
|
3
|
+
import { shallow } from 'enzyme';
|
|
5
4
|
import React from 'react';
|
|
6
5
|
|
|
7
|
-
import { mockServerGroupDataSourceConfig } from '@spinnaker/mocks';
|
|
8
|
-
|
|
9
6
|
import { CloudFoundryCreateServiceBindingsStageConfigForm } from './CloudFoundryCreateServiceBindingsStageConfigForm';
|
|
10
7
|
|
|
11
8
|
describe('<CloudFoundryCreateServiceBindingsStageConfigForm/>', function () {
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const application = {
|
|
10
|
+
ready: () => Promise.resolve(),
|
|
11
|
+
getDataSource: () => ({ data: [] }),
|
|
12
|
+
} as Application;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
spyOn(AccountService, 'listAccounts').and.returnValue(Promise.resolve([]));
|
|
16
|
+
spyOn(AccountService, 'getRegionsForAccount').and.returnValue(Promise.resolve([]));
|
|
17
|
+
});
|
|
14
18
|
|
|
15
19
|
const getProps = () => {
|
|
16
20
|
return {
|
|
17
|
-
application
|
|
21
|
+
application,
|
|
18
22
|
pipeline: {
|
|
19
23
|
application: 'my-application',
|
|
20
24
|
id: 'pipeline-id',
|
|
@@ -32,19 +36,19 @@ describe('<CloudFoundryCreateServiceBindingsStageConfigForm/>', function () {
|
|
|
32
36
|
const stage = ({
|
|
33
37
|
serviceBindingRequests: [{ serviceInstanceName: 'service1' }, { serviceInstanceName: 'service2' }],
|
|
34
38
|
} as unknown) as IStage;
|
|
39
|
+
const formik = {
|
|
40
|
+
values: stage,
|
|
41
|
+
setFieldValue: jasmine.createSpy('setFieldValue'),
|
|
42
|
+
} as any;
|
|
35
43
|
|
|
36
44
|
const props = getProps();
|
|
37
|
-
const component =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
-
expect(component.find(StageConfigField).findWhere((x) => x.text() === 'Target').length).toBe(1);
|
|
46
|
-
expect(component.find(StageConfigField).findWhere((x) => x.text() === 'Restage Required').length).toBe(1);
|
|
47
|
-
expect(component.find(StageConfigField).findWhere((x) => x.text() === 'Restart Required').length).toBe(1);
|
|
48
|
-
expect(component.find(StageConfigField).findWhere((x) => x.text() === 'Service Instance Name').length).toBe(2);
|
|
45
|
+
const component = shallow(<CloudFoundryCreateServiceBindingsStageConfigForm {...props} formik={formik} />);
|
|
46
|
+
|
|
47
|
+
expect(component.find(StageConfigField).filterWhere((x) => x.prop('label') === 'Target').length).toBe(1);
|
|
48
|
+
expect(component.find(StageConfigField).filterWhere((x) => x.prop('label') === 'Restage Required').length).toBe(1);
|
|
49
|
+
expect(component.find(StageConfigField).filterWhere((x) => x.prop('label') === 'Restart Required').length).toBe(1);
|
|
50
|
+
expect(
|
|
51
|
+
component.find(StageConfigField).filterWhere((x) => x.prop('label') === 'Service Instance Name').length,
|
|
52
|
+
).toBe(2);
|
|
49
53
|
});
|
|
50
54
|
});
|
|
@@ -3,7 +3,7 @@ import { from as observableFrom, Subject } from 'rxjs';
|
|
|
3
3
|
import { takeUntil } from 'rxjs/operators';
|
|
4
4
|
|
|
5
5
|
import type { Application, IAccount, IFormikStageConfigInjectedProps, IRegion } from '@spinnaker/core';
|
|
6
|
-
import { AccountService,
|
|
6
|
+
import { AccountService, StageConfigField, StageConstants, TargetSelect, TextInput } from '@spinnaker/core';
|
|
7
7
|
|
|
8
8
|
import { AccountRegionClusterSelector } from '../../../presentation/widgets/accountRegionClusterSelector';
|
|
9
9
|
|
|
@@ -96,7 +96,6 @@ export class CloudFoundryDeleteServiceBindingsStageConfigForm extends React.Comp
|
|
|
96
96
|
const stage = this.props.formik.values;
|
|
97
97
|
const { accounts, application } = this.state;
|
|
98
98
|
const { target } = stage;
|
|
99
|
-
const { TargetSelect } = NgReact;
|
|
100
99
|
|
|
101
100
|
return (
|
|
102
101
|
<>
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { mount } from 'enzyme';
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
|
|
5
|
-
import type { IStage } from '@spinnaker/core';
|
|
6
|
-
import {
|
|
7
|
-
import { mockServerGroupDataSourceConfig } from '@spinnaker/mocks';
|
|
4
|
+
import type { Application, IStage } from '@spinnaker/core';
|
|
5
|
+
import { AccountService, StageConfigField } from '@spinnaker/core';
|
|
8
6
|
|
|
9
7
|
import { CloudFoundryDeleteServiceBindingsStageConfigForm } from './CloudFoundryDeleteServiceBindingsStageConfigForm';
|
|
10
8
|
|
|
11
9
|
describe('<CloudFoundryDeleteServiceBindingsStageConfigForm/>', function () {
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const application = {
|
|
11
|
+
ready: () => Promise.resolve(),
|
|
12
|
+
getDataSource: () => ({ data: [] }),
|
|
13
|
+
} as Application;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
spyOn(AccountService, 'listAccounts').and.returnValue(Promise.resolve([]));
|
|
17
|
+
spyOn(AccountService, 'getRegionsForAccount').and.returnValue(Promise.resolve([]));
|
|
18
|
+
});
|
|
14
19
|
|
|
15
20
|
const getProps = () => {
|
|
16
21
|
return {
|
|
17
|
-
application
|
|
22
|
+
application,
|
|
18
23
|
pipeline: {
|
|
19
24
|
application: 'my-application',
|
|
20
25
|
id: 'pipeline-id',
|
|
@@ -32,18 +37,18 @@ describe('<CloudFoundryDeleteServiceBindingsStageConfigForm/>', function () {
|
|
|
32
37
|
const stage = ({
|
|
33
38
|
serviceUnbindingRequests: [{ serviceInstanceName: 'service1' }, { serviceInstanceName: 'service2' }],
|
|
34
39
|
} as unknown) as IStage;
|
|
40
|
+
const formik = {
|
|
41
|
+
values: stage,
|
|
42
|
+
setFieldValue: jasmine.createSpy('setFieldValue'),
|
|
43
|
+
} as any;
|
|
35
44
|
|
|
36
45
|
const props = getProps();
|
|
37
46
|
|
|
38
|
-
const component =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/>,
|
|
45
|
-
);
|
|
46
|
-
expect(component.find(StageConfigField).findWhere((x) => x.text() === 'Target').length).toBe(1);
|
|
47
|
-
expect(component.find(StageConfigField).findWhere((x) => x.text() === 'Service Instance Name').length).toBe(2);
|
|
47
|
+
const component = shallow(<CloudFoundryDeleteServiceBindingsStageConfigForm {...props} formik={formik} />);
|
|
48
|
+
|
|
49
|
+
expect(component.find(StageConfigField).filterWhere((x) => x.prop('label') === 'Target').length).toBe(1);
|
|
50
|
+
expect(
|
|
51
|
+
component.find(StageConfigField).filterWhere((x) => x.prop('label') === 'Service Instance Name').length,
|
|
52
|
+
).toBe(2);
|
|
48
53
|
});
|
|
49
54
|
});
|
|
@@ -3,7 +3,7 @@ import { from as observableFrom, Subject } from 'rxjs';
|
|
|
3
3
|
import { takeUntil } from 'rxjs/operators';
|
|
4
4
|
|
|
5
5
|
import type { IAccount, IStageConfigProps } from '@spinnaker/core';
|
|
6
|
-
import { AccountService,
|
|
6
|
+
import { AccountService, StageConfigField, StageConstants, TargetSelect } from '@spinnaker/core';
|
|
7
7
|
import { AccountRegionClusterSelector } from '../../../presentation';
|
|
8
8
|
|
|
9
9
|
export interface ICloudFoundryResizeAsgStageConfigState {
|
|
@@ -87,7 +87,6 @@ export class CloudFoundryResizeAsgStageConfig extends React.Component<
|
|
|
87
87
|
const { application, pipeline, stage } = this.props;
|
|
88
88
|
const { capacity, diskQuota, memory, target } = stage;
|
|
89
89
|
const instanceCount = capacity.desired;
|
|
90
|
-
const { TargetSelect } = NgReact;
|
|
91
90
|
return (
|
|
92
91
|
<div className="cloudfoundry-resize-asg-stage form-horizontal">
|
|
93
92
|
{!pipeline.strategy && (
|
|
@@ -10,7 +10,6 @@ Registry.pipeline.registerStage({
|
|
|
10
10
|
key: 'rollbackCluster',
|
|
11
11
|
cloudProvider: 'cloudfoundry',
|
|
12
12
|
component: CloudFoundryRollbackClusterStageConfig,
|
|
13
|
-
controller: 'cfRollbackClusterStageCtrl',
|
|
14
13
|
validators: [
|
|
15
14
|
{ type: 'requiredField', preventSave: true, fieldName: 'cluster' },
|
|
16
15
|
{ type: 'requiredField', preventSave: true, fieldName: 'regions' },
|
|
@@ -3,7 +3,7 @@ import { from as observableFrom, Subject } from 'rxjs';
|
|
|
3
3
|
import { takeUntil } from 'rxjs/operators';
|
|
4
4
|
|
|
5
5
|
import type { IAccount, IStageConfigProps } from '@spinnaker/core';
|
|
6
|
-
import { AccountService,
|
|
6
|
+
import { AccountService, SpelText, StageConfigField, StageConstants, TargetSelect, TextInput } from '@spinnaker/core';
|
|
7
7
|
import { AccountRegionClusterSelector } from '../../../presentation';
|
|
8
8
|
|
|
9
9
|
export interface ICloudFoundryRunTaskStageConfigState {
|
|
@@ -49,7 +49,6 @@ export class CloudFoundryRunJobStageConfig extends React.Component<
|
|
|
49
49
|
const { application, stage } = this.props;
|
|
50
50
|
const { target, jobName, command, logsUrl } = stage;
|
|
51
51
|
const { accounts } = this.state;
|
|
52
|
-
const { TargetSelect } = NgReact;
|
|
53
52
|
|
|
54
53
|
return (
|
|
55
54
|
<div className="cloudfoundry-resize-asg-stage form-horizontal">
|
|
@@ -11,7 +11,6 @@ Registry.pipeline.registerStage({
|
|
|
11
11
|
key: 'unshareService',
|
|
12
12
|
cloudProvider: 'cloudfoundry',
|
|
13
13
|
component: CloudFoundryUnshareServiceStageConfig,
|
|
14
|
-
controller: 'cfUnshareServiceStageCtrl',
|
|
15
14
|
executionDetailsSections: [CloudFoundryUnshareServiceExecutionDetails, ExecutionDetailsTasks],
|
|
16
15
|
supportsCustomTimeout: true,
|
|
17
16
|
validators: [
|
|
@@ -3,7 +3,7 @@ import { from as observableFrom, Subject } from 'rxjs';
|
|
|
3
3
|
import { takeUntil } from 'rxjs/operators';
|
|
4
4
|
|
|
5
5
|
import type { IAccount, IStageConfigProps } from '@spinnaker/core';
|
|
6
|
-
import { AccountService,
|
|
6
|
+
import { AccountService, StageConfigField, StageConstants, TargetSelect } from '@spinnaker/core';
|
|
7
7
|
|
|
8
8
|
import { AccountRegionClusterSelector } from '../../widgets/accountRegionClusterSelector';
|
|
9
9
|
|
|
@@ -46,7 +46,6 @@ export class CloudFoundryAsgStageConfig extends React.Component<IStageConfigProp
|
|
|
46
46
|
const { application, pipeline, stage } = this.props;
|
|
47
47
|
const { target } = stage;
|
|
48
48
|
const { accounts } = this.state;
|
|
49
|
-
const { TargetSelect } = NgReact;
|
|
50
49
|
return (
|
|
51
50
|
<div className="form-horizontal">
|
|
52
51
|
{!pipeline.strategy && (
|
|
@@ -4,7 +4,7 @@ import { from as observableFrom, Subject } from 'rxjs';
|
|
|
4
4
|
import { takeUntil } from 'rxjs/operators';
|
|
5
5
|
|
|
6
6
|
import type { Application, IAccount, IPipeline, IStageConfigProps } from '@spinnaker/core';
|
|
7
|
-
import { AccountService,
|
|
7
|
+
import { AccountService, SpinFormik, StageConfigField, StageConstants, TargetSelect } from '@spinnaker/core';
|
|
8
8
|
|
|
9
9
|
import { Routes } from '../../forms/serverGroup';
|
|
10
10
|
import { AccountRegionClusterSelector } from '../../widgets/accountRegionClusterSelector';
|
|
@@ -76,7 +76,6 @@ export class CloudFoundryLoadBalancersStageConfig extends React.Component<
|
|
|
76
76
|
const { stage } = this.props;
|
|
77
77
|
const { accounts, application, initialValues, pipeline } = this.state;
|
|
78
78
|
const { target } = stage;
|
|
79
|
-
const { TargetSelect } = NgReact;
|
|
80
79
|
return (
|
|
81
80
|
<div className="form-horizontal">
|
|
82
81
|
{!pipeline.strategy && (
|
package/src/presentation/widgets/accountRegionClusterSelector/AccountRegionClusterSelector.spec.tsx
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { mock, noop } from 'angular';
|
|
1
|
+
import type { ReactWrapper, ShallowWrapper } from 'enzyme';
|
|
3
2
|
import { mount, shallow } from 'enzyme';
|
|
4
3
|
import React from 'react';
|
|
5
4
|
|
|
6
|
-
import type { Application,
|
|
7
|
-
import { ApplicationModelBuilder, REACT_MODULE } from '@spinnaker/core';
|
|
5
|
+
import type { Application, IMoniker, IServerGroup } from '@spinnaker/core';
|
|
8
6
|
|
|
9
7
|
import type { IAccountRegionClusterSelectorProps } from './AccountRegionClusterSelector';
|
|
10
8
|
import { AccountRegionClusterSelector } from './AccountRegionClusterSelector';
|
|
11
9
|
|
|
12
10
|
describe('<AccountRegionClusterSelector />', () => {
|
|
13
|
-
let $scope: IScope;
|
|
14
11
|
let application: Application;
|
|
12
|
+
const noop = () => {};
|
|
15
13
|
|
|
16
14
|
function createServerGroup(account: string, cluster: string, name: string, region: string): IServerGroup {
|
|
17
15
|
return {
|
|
@@ -26,27 +24,27 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
26
24
|
} as IServerGroup;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
it('initializes properly with provided component', () => {
|
|
27
|
+
async function flushComponent(component: ReactWrapper | ShallowWrapper): Promise<void> {
|
|
28
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
29
|
+
component.update();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
const serverGroups = [
|
|
34
|
+
createServerGroup('account-name-one', 'app-stack-detailOne', 'app', 'region-one'),
|
|
35
|
+
createServerGroup('account-name-two', 'app-stack-detailTwo', 'app', 'region-two'),
|
|
36
|
+
createServerGroup('account-name-one', 'app-stack-detailOne', 'app', 'region-three'),
|
|
37
|
+
createServerGroup('account-name-one', 'app-stack-detailThree', 'app', 'region-one'),
|
|
38
|
+
createServerGroup('account-name-one', 'app-stack-detailFour', 'app', 'region-three'),
|
|
39
|
+
createServerGroup('account-name-one', 'app-stack-detailFive', 'app', 'region-two'),
|
|
40
|
+
];
|
|
41
|
+
application = {
|
|
42
|
+
ready: () => Promise.resolve(),
|
|
43
|
+
getDataSource: () => ({ data: serverGroups }),
|
|
44
|
+
} as Application;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('initializes properly with provided component', async () => {
|
|
50
48
|
const accountRegionClusterProps: IAccountRegionClusterSelectorProps = {
|
|
51
49
|
accounts: [
|
|
52
50
|
{
|
|
@@ -68,7 +66,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
68
66
|
const component = shallow<AccountRegionClusterSelector>(
|
|
69
67
|
<AccountRegionClusterSelector {...accountRegionClusterProps} />,
|
|
70
68
|
);
|
|
71
|
-
|
|
69
|
+
await flushComponent(component);
|
|
72
70
|
|
|
73
71
|
expect(component.state().availableRegions.length).toBe(3, 'number of available regions does not match');
|
|
74
72
|
expect(component.state().availableRegions).toContain('region-one');
|
|
@@ -81,7 +79,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
81
79
|
expect(component.state().componentName).toBe('');
|
|
82
80
|
});
|
|
83
81
|
|
|
84
|
-
it('retrieves the correct list of regions when account is changed', () => {
|
|
82
|
+
it('retrieves the correct list of regions when account is changed', async () => {
|
|
85
83
|
let credentials = '';
|
|
86
84
|
let region = 'SHOULD-CHANGE';
|
|
87
85
|
let regions = ['SHOULD-CHANGE'];
|
|
@@ -118,7 +116,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
118
116
|
const component = mount<AccountRegionClusterSelector>(
|
|
119
117
|
<AccountRegionClusterSelector {...accountRegionClusterProps} />,
|
|
120
118
|
);
|
|
121
|
-
|
|
119
|
+
await flushComponent(component);
|
|
122
120
|
|
|
123
121
|
expect(component.state().availableRegions.length).toBe(3, 'number of available regions does not match');
|
|
124
122
|
expect(component.state().availableRegions).toContain('region-one');
|
|
@@ -132,7 +130,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
132
130
|
accountSelectComponent.simulate('mouseDown');
|
|
133
131
|
accountSelectComponent.simulate('change', { target: { value: 'account-name-two' } });
|
|
134
132
|
accountSelectComponent.simulate('keyDown', { keyCode: 9, key: 'Tab' });
|
|
135
|
-
|
|
133
|
+
await flushComponent(component);
|
|
136
134
|
|
|
137
135
|
expect(component.state().availableRegions.length).toBe(1, 'number of available regions does not match');
|
|
138
136
|
expect(component.state().availableRegions).toContain('region-two');
|
|
@@ -143,7 +141,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
143
141
|
expect(cluster).toBeUndefined('selected cluster is not cleared');
|
|
144
142
|
});
|
|
145
143
|
|
|
146
|
-
it('retrieves the correct list of clusters when the selector is multi-region and the region is changed', () => {
|
|
144
|
+
it('retrieves the correct list of clusters when the selector is multi-region and the region is changed', async () => {
|
|
147
145
|
let regions: string[] = [];
|
|
148
146
|
let cluster = 'SHOULD-CHANGE';
|
|
149
147
|
const accountRegionClusterProps: IAccountRegionClusterSelectorProps = {
|
|
@@ -177,7 +175,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
177
175
|
const component = mount<AccountRegionClusterSelector>(
|
|
178
176
|
<AccountRegionClusterSelector {...accountRegionClusterProps} />,
|
|
179
177
|
);
|
|
180
|
-
|
|
178
|
+
await flushComponent(component);
|
|
181
179
|
|
|
182
180
|
expect(component.state().availableRegions.length).toBe(3, 'number of available regions does not match');
|
|
183
181
|
expect(component.state().availableRegions).toContain('region-one');
|
|
@@ -191,7 +189,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
191
189
|
accountSelectComponent.simulate('mouseDown');
|
|
192
190
|
accountSelectComponent.simulate('change', { target: { value: 'region-three' } });
|
|
193
191
|
accountSelectComponent.simulate('keyDown', { keyCode: 9, key: 'Tab' });
|
|
194
|
-
|
|
192
|
+
await flushComponent(component);
|
|
195
193
|
|
|
196
194
|
expect(component.state().clusters.length).toBe(3, 'number of clusters does not match');
|
|
197
195
|
expect(component.state().clusters).toContain('app-stack-detailOne');
|
|
@@ -203,7 +201,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
203
201
|
expect(regions).toContain('region-three');
|
|
204
202
|
});
|
|
205
203
|
|
|
206
|
-
it('retrieves the correct list of clusters on startup and the selector is single-region', () => {
|
|
204
|
+
it('retrieves the correct list of clusters on startup and the selector is single-region', async () => {
|
|
207
205
|
const accountRegionClusterProps: IAccountRegionClusterSelectorProps = {
|
|
208
206
|
accounts: [
|
|
209
207
|
{
|
|
@@ -233,7 +231,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
233
231
|
const component = mount<AccountRegionClusterSelector>(
|
|
234
232
|
<AccountRegionClusterSelector {...accountRegionClusterProps} />,
|
|
235
233
|
);
|
|
236
|
-
|
|
234
|
+
await flushComponent(component);
|
|
237
235
|
|
|
238
236
|
expect(component.state().availableRegions.length).toBe(3, 'number of available regions does not match');
|
|
239
237
|
expect(component.state().availableRegions).toContain('region-one');
|
|
@@ -244,7 +242,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
244
242
|
expect(component.state().clusters).toContain('app-stack-detailThree');
|
|
245
243
|
});
|
|
246
244
|
|
|
247
|
-
it('the cluster value is updated in the component when cluster is changed', () => {
|
|
245
|
+
it('the cluster value is updated in the component when cluster is changed', async () => {
|
|
248
246
|
let cluster = '';
|
|
249
247
|
let moniker: IMoniker = { app: '' };
|
|
250
248
|
const accountRegionClusterProps: IAccountRegionClusterSelectorProps = {
|
|
@@ -287,7 +285,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
287
285
|
const component = mount<AccountRegionClusterSelector>(
|
|
288
286
|
<AccountRegionClusterSelector {...accountRegionClusterProps} />,
|
|
289
287
|
);
|
|
290
|
-
|
|
288
|
+
await flushComponent(component);
|
|
291
289
|
|
|
292
290
|
expect(component.state().availableRegions.length).toBe(3, 'number of available regions does not match');
|
|
293
291
|
expect(component.state().availableRegions).toContain('region-one');
|
|
@@ -301,13 +299,13 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
301
299
|
clusterSelectComponent.simulate('mouseDown');
|
|
302
300
|
clusterSelectComponent.simulate('change', { target: { value: 'app-stack-detailThree' } });
|
|
303
301
|
clusterSelectComponent.simulate('keyDown', { keyCode: 9, key: 'Tab' });
|
|
304
|
-
|
|
302
|
+
await flushComponent(component);
|
|
305
303
|
|
|
306
304
|
expect(cluster).toBe('app-stack-detailThree');
|
|
307
305
|
expect(moniker).toEqual(expectedMoniker);
|
|
308
306
|
});
|
|
309
307
|
|
|
310
|
-
it('the cluster value is updated in the component when cluster is changed to freeform value', () => {
|
|
308
|
+
it('the cluster value is updated in the component when cluster is changed to freeform value', async () => {
|
|
311
309
|
let cluster = '';
|
|
312
310
|
let moniker: IMoniker = { app: '' };
|
|
313
311
|
const accountRegionClusterProps: IAccountRegionClusterSelectorProps = {
|
|
@@ -342,20 +340,20 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
342
340
|
const component = mount<AccountRegionClusterSelector>(
|
|
343
341
|
<AccountRegionClusterSelector {...accountRegionClusterProps} />,
|
|
344
342
|
);
|
|
345
|
-
|
|
343
|
+
await flushComponent(component);
|
|
346
344
|
|
|
347
345
|
const clusterSelectComponent = component.find('Select[name="newCluster"] .Select-control input');
|
|
348
346
|
clusterSelectComponent.simulate('mouseDown');
|
|
349
347
|
clusterSelectComponent.simulate('change', { target: { value: 'app-stack-freeform' } });
|
|
350
348
|
clusterSelectComponent.simulate('keyDown', { keyCode: 9, key: 'Tab' });
|
|
351
|
-
|
|
349
|
+
await flushComponent(component);
|
|
352
350
|
|
|
353
351
|
expect(cluster).toBe('app-stack-freeform');
|
|
354
352
|
expect(moniker).toBeUndefined();
|
|
355
353
|
expect(component.state().clusters).toContain('app-stack-freeform');
|
|
356
354
|
});
|
|
357
355
|
|
|
358
|
-
it('initialize with form names', () => {
|
|
356
|
+
it('initialize with form names', async () => {
|
|
359
357
|
const accountRegionClusterProps: IAccountRegionClusterSelectorProps = {
|
|
360
358
|
accounts: [
|
|
361
359
|
{
|
|
@@ -376,7 +374,7 @@ describe('<AccountRegionClusterSelector />', () => {
|
|
|
376
374
|
};
|
|
377
375
|
|
|
378
376
|
const component = shallow(<AccountRegionClusterSelector {...accountRegionClusterProps} />);
|
|
379
|
-
|
|
377
|
+
await flushComponent(component);
|
|
380
378
|
|
|
381
379
|
expect(component.find('Select[name="form.credentials"]').length).toBe(1, 'select for account not found');
|
|
382
380
|
expect(component.find('Select[name="form.regions"]').length).toBe(1, 'select for regions not found');
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { ConfirmationModalService, ServerGroupWarningMessageService } from '@spinnaker/core';
|
|
5
|
+
|
|
6
|
+
import { CloudFoundryInstanceActionsComponent } from './instance/details/CloudFoundryInstanceActions';
|
|
7
|
+
import { CloudFoundryLoadBalancerActionsComponent } from './loadBalancer/details/CloudFoundryLoadBalancerActions';
|
|
8
|
+
import { CloudFoundryServerGroupActionsComponent } from './serverGroup/details/cloudFoundryServerGroupActions';
|
|
9
|
+
|
|
10
|
+
describe('Cloud Foundry routed actions', () => {
|
|
11
|
+
const routerProps = (includes: jasmine.Spy, go: jasmine.Spy) =>
|
|
12
|
+
({ router: {}, stateParams: {}, stateService: { go, includes } } as any);
|
|
13
|
+
|
|
14
|
+
it('closes instance details through the injected state service', () => {
|
|
15
|
+
const includes = jasmine.createSpy('includes').and.returnValue(true);
|
|
16
|
+
const go = jasmine.createSpy('go');
|
|
17
|
+
const confirm = spyOn(ConfirmationModalService, 'confirm');
|
|
18
|
+
const component = shallow(
|
|
19
|
+
<CloudFoundryInstanceActionsComponent
|
|
20
|
+
{...routerProps(includes, go)}
|
|
21
|
+
application={{} as any}
|
|
22
|
+
instance={{ account: 'test', name: 'instance-id' } as any}
|
|
23
|
+
/>,
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
(component.instance() as any).terminateInstance();
|
|
27
|
+
confirm.calls.mostRecent().args[0].taskMonitorConfig.onTaskComplete();
|
|
28
|
+
|
|
29
|
+
expect(go).toHaveBeenCalledWith('^');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('closes load balancer details through the injected state service', () => {
|
|
33
|
+
const includes = jasmine.createSpy('includes').and.returnValue(true);
|
|
34
|
+
const go = jasmine.createSpy('go');
|
|
35
|
+
const confirm = spyOn(ConfirmationModalService, 'confirm');
|
|
36
|
+
const component = shallow(
|
|
37
|
+
<CloudFoundryLoadBalancerActionsComponent
|
|
38
|
+
{...routerProps(includes, go)}
|
|
39
|
+
application={{} as any}
|
|
40
|
+
loadBalancer={{ account: 'test', name: 'route', region: 'test' } as any}
|
|
41
|
+
/>,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
(component.instance() as any).deleteLoadBalancer();
|
|
45
|
+
confirm.calls.mostRecent().args[0].taskMonitorConfig.onTaskComplete();
|
|
46
|
+
|
|
47
|
+
expect(go).toHaveBeenCalledWith('^');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('closes server group details through the injected state service', () => {
|
|
51
|
+
const includes = jasmine.createSpy('includes').and.returnValue(true);
|
|
52
|
+
const go = jasmine.createSpy('go');
|
|
53
|
+
spyOn(ServerGroupWarningMessageService, 'addDestroyWarningMessage');
|
|
54
|
+
const confirm = spyOn(ConfirmationModalService, 'confirm');
|
|
55
|
+
const component = shallow(
|
|
56
|
+
<CloudFoundryServerGroupActionsComponent
|
|
57
|
+
{...routerProps(includes, go)}
|
|
58
|
+
app={{ attributes: {} } as any}
|
|
59
|
+
serverGroup={
|
|
60
|
+
{
|
|
61
|
+
account: 'test',
|
|
62
|
+
cloudProvider: 'cloudfoundry',
|
|
63
|
+
moniker: { cluster: 'app' },
|
|
64
|
+
name: 'app-v001',
|
|
65
|
+
region: 'test',
|
|
66
|
+
} as any
|
|
67
|
+
}
|
|
68
|
+
/>,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
(component.instance() as any).destroyServerGroup();
|
|
72
|
+
confirm.calls.mostRecent().args[0].taskMonitorConfig.onTaskComplete();
|
|
73
|
+
|
|
74
|
+
expect(go).toHaveBeenCalledWith('^');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { IQService } from 'angular';
|
|
2
|
-
|
|
3
1
|
import type { Application, IPipeline, IStage } from '@spinnaker/core';
|
|
4
2
|
import type { ICloudFoundryApplication, ICloudFoundryServerGroup } from '../../domain';
|
|
5
3
|
|
|
@@ -10,22 +8,16 @@ import type {
|
|
|
10
8
|
} from './serverGroupConfigurationModel.cf';
|
|
11
9
|
|
|
12
10
|
export class CloudFoundryServerGroupCommandBuilderShim {
|
|
13
|
-
public
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
public buildNewServerGroupCommand(
|
|
17
|
-
app: Application,
|
|
18
|
-
defaults: any,
|
|
19
|
-
): PromiseLike<ICloudFoundryCreateServerGroupCommand> {
|
|
20
|
-
return this.$q.when(CloudFoundryServerGroupCommandBuilder.buildNewServerGroupCommand(app, defaults));
|
|
11
|
+
public buildNewServerGroupCommand(app: Application, defaults: any): Promise<ICloudFoundryCreateServerGroupCommand> {
|
|
12
|
+
return Promise.resolve(CloudFoundryServerGroupCommandBuilder.buildNewServerGroupCommand(app, defaults));
|
|
21
13
|
}
|
|
22
14
|
|
|
23
15
|
public buildServerGroupCommandFromExisting(
|
|
24
16
|
app: Application,
|
|
25
17
|
serverGroup: ICloudFoundryServerGroup,
|
|
26
18
|
mode = 'clone',
|
|
27
|
-
):
|
|
28
|
-
return
|
|
19
|
+
): Promise<ICloudFoundryCreateServerGroupCommand> {
|
|
20
|
+
return Promise.resolve(
|
|
29
21
|
CloudFoundryServerGroupCommandBuilder.buildServerGroupCommandFromExisting(app, serverGroup, mode),
|
|
30
22
|
);
|
|
31
23
|
}
|
|
@@ -33,8 +25,10 @@ export class CloudFoundryServerGroupCommandBuilderShim {
|
|
|
33
25
|
public buildNewServerGroupCommandForPipeline(
|
|
34
26
|
stage: IStage,
|
|
35
27
|
pipeline: IPipeline,
|
|
36
|
-
):
|
|
37
|
-
return
|
|
28
|
+
): Promise<ICloudFoundryCreateServerGroupCommand> {
|
|
29
|
+
return Promise.resolve(
|
|
30
|
+
CloudFoundryServerGroupCommandBuilder.buildNewServerGroupCommandForPipeline(stage, pipeline),
|
|
31
|
+
);
|
|
38
32
|
}
|
|
39
33
|
|
|
40
34
|
public buildServerGroupCommandFromPipeline(
|
|
@@ -42,8 +36,8 @@ export class CloudFoundryServerGroupCommandBuilderShim {
|
|
|
42
36
|
originalCluster: ICloudFoundryDeployConfiguration,
|
|
43
37
|
stage: IStage,
|
|
44
38
|
pipeline: IPipeline,
|
|
45
|
-
):
|
|
46
|
-
return
|
|
39
|
+
): Promise<ICloudFoundryCreateServerGroupCommand> {
|
|
40
|
+
return Promise.resolve(
|
|
47
41
|
CloudFoundryServerGroupCommandBuilder.buildServerGroupCommandFromPipeline(
|
|
48
42
|
application,
|
|
49
43
|
originalCluster,
|
|
@@ -56,8 +50,8 @@ export class CloudFoundryServerGroupCommandBuilderShim {
|
|
|
56
50
|
public buildCloneServerGroupCommandFromPipeline(
|
|
57
51
|
stage: IStage,
|
|
58
52
|
pipeline: IPipeline,
|
|
59
|
-
):
|
|
60
|
-
return
|
|
53
|
+
): Promise<ICloudFoundryCreateServerGroupCommand> {
|
|
54
|
+
return Promise.resolve(
|
|
61
55
|
CloudFoundryServerGroupCommandBuilder.buildCloneServerGroupCommandFromPipeline(stage, pipeline),
|
|
62
56
|
);
|
|
63
57
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { get } from 'lodash';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
-
import type { Application, IModalComponentProps, IPipeline, IStage } from '@spinnaker/core';
|
|
5
|
-
import {
|
|
4
|
+
import type { Application, DeckRuntimeServices, IModalComponentProps, IPipeline, IStage } from '@spinnaker/core';
|
|
5
|
+
import { DeckRuntimeContext, noop, ReactModal, TaskMonitor, WizardModal, WizardPage } from '@spinnaker/core';
|
|
6
6
|
|
|
7
7
|
import { ServerGroupTemplateSelection } from './ServerGroupTemplateSelection';
|
|
8
8
|
import type { ICloudFoundryServerGroup } from '../../../domain';
|
|
@@ -36,14 +36,20 @@ export class CloudFoundryCreateServerGroupModal extends React.Component<
|
|
|
36
36
|
ICloudFoundryCreateServerGroupProps,
|
|
37
37
|
ICloudFoundryCreateServerGroupState
|
|
38
38
|
> {
|
|
39
|
+
public static contextType = DeckRuntimeContext;
|
|
40
|
+
public declare context: React.ContextType<typeof DeckRuntimeContext>;
|
|
41
|
+
|
|
39
42
|
public static defaultProps: Partial<ICloudFoundryCreateServerGroupProps> = {
|
|
40
43
|
closeModal: noop,
|
|
41
44
|
dismissModal: noop,
|
|
42
45
|
};
|
|
43
46
|
|
|
44
|
-
public static show(
|
|
47
|
+
public static show(
|
|
48
|
+
props: ICloudFoundryCreateServerGroupProps,
|
|
49
|
+
runtimeServices: DeckRuntimeServices,
|
|
50
|
+
): Promise<ICloudFoundryCreateServerGroupCommand> {
|
|
45
51
|
const modalProps = { dialogClassName: 'wizard-modal modal-lg' };
|
|
46
|
-
return ReactModal.show(CloudFoundryCreateServerGroupModal, props, modalProps);
|
|
52
|
+
return ReactModal.show(CloudFoundryCreateServerGroupModal, props, modalProps, runtimeServices);
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
constructor(props: ICloudFoundryCreateServerGroupProps) {
|
|
@@ -60,7 +66,7 @@ export class CloudFoundryCreateServerGroupModal extends React.Component<
|
|
|
60
66
|
taskMonitor: new TaskMonitor({
|
|
61
67
|
application: props.application,
|
|
62
68
|
title: 'Creating your server group',
|
|
63
|
-
|
|
69
|
+
onDismiss: () => this.props.dismissModal(),
|
|
64
70
|
onTaskComplete: this.onTaskComplete,
|
|
65
71
|
}),
|
|
66
72
|
};
|
|
@@ -89,11 +95,11 @@ export class CloudFoundryCreateServerGroupModal extends React.Component<
|
|
|
89
95
|
this.props.closeModal && this.props.closeModal(command);
|
|
90
96
|
} else if (command.viewState.mode === 'clone') {
|
|
91
97
|
this.state.taskMonitor.submit(() =>
|
|
92
|
-
|
|
98
|
+
this.context.services.serverGroupWriter.cloneServerGroup(command, this.props.application),
|
|
93
99
|
);
|
|
94
100
|
} else {
|
|
95
101
|
this.state.taskMonitor.submit(() =>
|
|
96
|
-
|
|
102
|
+
this.context.services.serverGroupWriter.cloneServerGroup(command, this.props.application),
|
|
97
103
|
);
|
|
98
104
|
}
|
|
99
105
|
};
|