@spinnaker/tencentcloud 0.0.0-2025.1-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/CHANGELOG.md +751 -0
- package/LICENSE.txt +203 -0
- package/dist/domain/IKeyPair.d.ts +8 -0
- package/dist/domain/IScalingPolicy.d.ts +44 -0
- package/dist/domain/IScalingProcess.d.ts +10 -0
- package/dist/domain/ITargetTrackingPolicy.d.ts +21 -0
- package/dist/domain/ITencentcloudCertificate.d.ts +5 -0
- package/dist/domain/ITencentcloudHealth.d.ts +18 -0
- package/dist/domain/ITencentcloudInstance.d.ts +4 -0
- package/dist/domain/ITencentcloudLoadBalancer.d.ts +278 -0
- package/dist/domain/ITencentcloudLoadBalancerSourceData.d.ts +171 -0
- package/dist/domain/ITencentcloudScalingPolicy.d.ts +19 -0
- package/dist/domain/ITencentcloudServerGroup.d.ts +43 -0
- package/dist/domain/index.d.ts +11 -0
- package/dist/help/tencentcloud.help.d.ts +1 -0
- package/dist/image/image.reader.d.ts +35 -0
- package/dist/image/index.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +553 -0
- package/dist/index.js.map +1 -0
- package/dist/keyPairs/KeyPairsReader.d.ts +4 -0
- package/dist/keyPairs/index.d.ts +1 -0
- package/dist/pipeline/stages/disableCluster/DisableClusterConfig.d.ts +3 -0
- package/dist/pipeline/stages/disableCluster/DisableClusterStageForm.d.ts +3 -0
- package/dist/pipeline/stages/disableCluster/disableClusterStage.d.ts +1 -0
- package/dist/pipeline/stages/disableCluster/disableClusterValidators.d.ts +2 -0
- package/dist/pipeline/stages/rollbackCluster/RollbackClusterConfig.d.ts +3 -0
- package/dist/pipeline/stages/rollbackCluster/RollbackClusterStageForm.d.ts +3 -0
- package/dist/pipeline/stages/rollbackCluster/rollbackClusterStage.d.ts +1 -0
- package/dist/pipeline/stages/rollbackCluster/rollbackClusterValidators.d.ts +2 -0
- package/dist/pipeline/stages/scaleDownCluster/ScaleDownClusterConfig.d.ts +3 -0
- package/dist/pipeline/stages/scaleDownCluster/ScaleDownClusterStageForm.d.ts +3 -0
- package/dist/pipeline/stages/scaleDownCluster/scaleDownClusterStage.d.ts +1 -0
- package/dist/pipeline/stages/scaleDownCluster/scaledownClusterValidators.d.ts +2 -0
- package/dist/pipeline/stages/shrinkCluster/ShrinkClusterConfig.d.ts +3 -0
- package/dist/pipeline/stages/shrinkCluster/ShrinkClusterStageForm.d.ts +3 -0
- package/dist/pipeline/stages/shrinkCluster/shrinkClusterStage.d.ts +1 -0
- package/dist/pipeline/stages/shrinkCluster/shrinkClusterValidators.d.ts +2 -0
- package/dist/reactShims/index.d.ts +2 -0
- package/dist/reactShims/tencentcloud.ngReact.d.ts +8 -0
- package/dist/reactShims/tencentcloud.react.injector.d.ts +7 -0
- package/dist/reactShims/tencentcloud.react.module.d.ts +1 -0
- package/dist/search/searchResultFormatter.d.ts +1 -0
- package/dist/tencentcloud.module.d.ts +7 -0
- package/dist/tencentcloud.settings.d.ts +26 -0
- package/dist/validation/ApplicationNameValidator.d.ts +1 -0
- package/package.json +37 -0
- package/src/domain/IKeyPair.ts +8 -0
- package/src/domain/IScalingPolicy.ts +84 -0
- package/src/domain/IScalingProcess.ts +11 -0
- package/src/domain/ITargetTrackingPolicy.ts +26 -0
- package/src/domain/ITencentcloudCertificate.ts +6 -0
- package/src/domain/ITencentcloudHealth.ts +21 -0
- package/src/domain/ITencentcloudInstance.ts +5 -0
- package/src/domain/ITencentcloudLoadBalancer.ts +326 -0
- package/src/domain/ITencentcloudLoadBalancerSourceData.ts +189 -0
- package/src/domain/ITencentcloudScalingPolicy.ts +23 -0
- package/src/domain/ITencentcloudServerGroup.ts +46 -0
- package/src/domain/index.ts +11 -0
- package/src/help/tencentcloud.help.ts +5 -0
- package/src/image/image.reader.ts +53 -0
- package/src/image/index.ts +1 -0
- package/src/index.ts +2 -0
- package/src/keyPairs/KeyPairsReader.ts +11 -0
- package/src/keyPairs/index.ts +1 -0
- package/src/logo/tencentcloud.icon.svg +24 -0
- package/src/logo/tencentcloud.logo.less +5 -0
- package/src/logo/tencentcloud.logo.svg +53 -0
- package/src/pipeline/stages/disableCluster/DisableClusterConfig.tsx +27 -0
- package/src/pipeline/stages/disableCluster/DisableClusterStageForm.tsx +87 -0
- package/src/pipeline/stages/disableCluster/disableClusterStage.ts +12 -0
- package/src/pipeline/stages/disableCluster/disableClusterValidators.ts +10 -0
- package/src/pipeline/stages/rollbackCluster/RollbackClusterConfig.tsx +27 -0
- package/src/pipeline/stages/rollbackCluster/RollbackClusterStageForm.tsx +74 -0
- package/src/pipeline/stages/rollbackCluster/rollbackClusterStage.ts +12 -0
- package/src/pipeline/stages/rollbackCluster/rollbackClusterValidators.ts +10 -0
- package/src/pipeline/stages/scaleDownCluster/ScaleDownClusterConfig.tsx +27 -0
- package/src/pipeline/stages/scaleDownCluster/ScaleDownClusterStageForm.tsx +102 -0
- package/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.ts +12 -0
- package/src/pipeline/stages/scaleDownCluster/scaledownClusterValidators.ts +10 -0
- package/src/pipeline/stages/shrinkCluster/ShrinkClusterConfig.tsx +27 -0
- package/src/pipeline/stages/shrinkCluster/ShrinkClusterStageForm.tsx +104 -0
- package/src/pipeline/stages/shrinkCluster/shrinkClusterStage.ts +12 -0
- package/src/pipeline/stages/shrinkCluster/shrinkClusterValidators.ts +10 -0
- package/src/reactShims/index.ts +2 -0
- package/src/reactShims/tencentcloud.ngReact.ts +21 -0
- package/src/reactShims/tencentcloud.react.injector.ts +14 -0
- package/src/reactShims/tencentcloud.react.module.ts +14 -0
- package/src/search/searchResultFormatter.js +10 -0
- package/src/tencentcloud.module.ts +32 -0
- package/src/tencentcloud.settings.ts +35 -0
- package/src/validation/ApplicationNameValidator.ts +71 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
width="120px" height="48px" viewBox="0 0 120 48" style="enable-background:new 0 0 120 48;" xml:space="preserve">
|
|
5
|
+
<g>
|
|
6
|
+
<g>
|
|
7
|
+
<path style="fill:#00A3FF;" d="M75.718,33.89c-0.764,0.756-2.125,1.613-4.361,1.689c-1.034,0.035-2.241,0.039-2.793,0.039
|
|
8
|
+
c-0.603,0-5.918,0-12.012,0c4.37-4.245,8.182-7.947,8.615-8.367c0.396-0.385,1.287-1.237,2.056-1.929
|
|
9
|
+
c1.687-1.519,3.206-1.825,4.28-1.815c1.683,0.016,3.214,0.703,4.308,1.813C78.152,27.712,78.097,31.536,75.718,33.89
|
|
10
|
+
M78.595,22.597c-1.795-1.83-4.296-2.983-7.077-2.984c-2.404,0-4.474,0.829-6.281,2.3c-0.788,0.641-1.614,1.409-2.653,2.419
|
|
11
|
+
c-0.516,0.501-15.485,15.026-15.485,15.026c0.785,0.112,1.864,0.145,2.826,0.151c0.902,0.006,18.1,0.004,18.82,0.004
|
|
12
|
+
c1.449,0,2.392-0.002,3.405-0.076c2.323-0.17,4.518-1.022,6.292-2.764C82.381,32.805,82.44,26.526,78.595,22.597z"/>
|
|
13
|
+
<path style="fill:#00C8DC;" d="M54.445,21.663c-1.76-1.317-3.729-2.053-5.963-2.05c-2.781,0-5.283,1.153-7.077,2.984
|
|
14
|
+
c-3.845,3.93-3.786,10.209,0.154,14.077c1.582,1.553,3.498,2.398,5.541,2.684l3.854-3.74c-0.623-0.003-1.518-0.011-2.311-0.038
|
|
15
|
+
c-2.235-0.076-3.597-0.934-4.361-1.689c-2.379-2.354-2.434-6.178-0.094-8.57c1.094-1.11,2.625-1.797,4.308-1.813
|
|
16
|
+
c1.055-0.004,2.486,0.302,4.103,1.643c0.772,0.64,2.486,2.147,3.239,2.825c0.038,0.035,0.084,0.038,0.129,0.001l2.654-2.589
|
|
17
|
+
c0.046-0.045,0.043-0.105-0.002-0.146C57.343,24.088,55.534,22.474,54.445,21.663"/>
|
|
18
|
+
<path style="fill:#006EFF;" d="M72.561,17.365C70.73,12.193,65.799,8.487,60,8.487c-6.652,0-12.165,4.892-13.164,11.264
|
|
19
|
+
c0.535-0.09,1.085-0.138,1.646-0.138c0.781-0.001,1.529,0.09,2.248,0.263c0.014,0.003,0.028,0.005,0.042,0.008
|
|
20
|
+
c0.901-4.302,4.705-7.498,9.228-7.498c3.767,0,7.072,2.272,8.562,5.492c0.023,0.051,0.063,0.067,0.104,0.056
|
|
21
|
+
c1.121-0.308,2.464-0.487,3.762-0.391C72.554,17.552,72.602,17.481,72.561,17.365"/>
|
|
22
|
+
</g>
|
|
23
|
+
</g>
|
|
24
|
+
</svg>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
width="120px" height="48px" viewBox="0 0 120 48" style="enable-background:new 0 0 120 48;" xml:space="preserve">
|
|
5
|
+
<g>
|
|
6
|
+
<g>
|
|
7
|
+
<path d="M93.829,13.731H81.181v1.83h3.808v6.673h-4.364v1.83h4.364v11.19h2.013v-11.19h4.814V35.02h3.802v-1.831h-1.788V13.731z
|
|
8
|
+
M87.002,22.234v-6.673h4.814v6.673H87.002z"/>
|
|
9
|
+
<rect x="58.743" y="30.136" width="9.979" height="1.83"/>
|
|
10
|
+
<path d="M51.944,26.749c0,3.328-0.269,5.854-0.823,8.093c-0.058,0.207,0.004,0.263,0.113,0.263c0.038,0,1.525,0,1.835,0
|
|
11
|
+
c0.613-3.075,0.693-5.626,0.703-7.477h2.565v5.69h-1.821c-0.089,0-0.157,0.058-0.11,0.184l0.502,1.646h3.257V13.777h-6.22V26.749z
|
|
12
|
+
M53.774,25.98V21.6h2.563v4.38H53.774z M56.337,15.607v4.346h-2.563v-4.346H56.337z"/>
|
|
13
|
+
<path d="M69.429,21.196h2.457v-1.647h-7.16c0.216-0.526,0.41-1.091,0.588-1.702h6.123V16.2h-1.794
|
|
14
|
+
c0.299-1.018,0.651-2.219,0.672-2.288c0.036-0.122-0.028-0.169-0.107-0.169h-1.558L67.927,16.2h-2.202
|
|
15
|
+
c0.205-0.952,0.384-2.007,0.547-3.191c0.019-0.137-0.055-0.164-0.146-0.164c-0.073,0-1.278,0-1.774,0
|
|
16
|
+
c-0.181,1.258-0.371,2.342-0.614,3.355h-1.08l-0.722-2.457h-1.558c-0.079,0-0.143,0.047-0.107,0.169
|
|
17
|
+
c0.02,0.07,0.373,1.271,0.672,2.288h-1.747v1.647h4.079c-0.166,0.52-0.41,1.133-0.67,1.702h-3.858v1.647h2.898
|
|
18
|
+
c-1.168,1.659-2.417,2.422-2.915,2.727c0,0.234,0,1.83,0,1.884c0,0.095,0.075,0.196,0.373,0.027
|
|
19
|
+
c0.542-0.307,1.12-0.655,1.705-1.087h6.817l-0.058,2.467h-5.382l0.082-1.475c0-0.064-0.046-0.111-0.112-0.111
|
|
20
|
+
c-0.102,0-1.721,0-1.721,0l-0.173,3.122c0,0.064,0.046,0.111,0.112,0.111c0.102,0,9.285,0,9.285,0v4.454h-4.185
|
|
21
|
+
c-0.089,0-0.157,0.058-0.11,0.184l0.502,1.646h5.807v-7.931h-2.273l0.075-3.203c0.85,0.79,1.712,1.379,2.497,1.824
|
|
22
|
+
c0.298,0.169,0.373,0.068,0.373-0.027c0-0.054,0-1.651,0-1.884C71.844,23.618,70.597,22.853,69.429,21.196z M67.188,21.196
|
|
23
|
+
c0.438,0.721,0.91,1.351,1.398,1.903h-5.991c0.465-0.537,0.915-1.163,1.335-1.903H67.188z"/>
|
|
24
|
+
<path d="M82.457,28.864c-0.034,0.026-1.742,1.32-3.395,2.572V19.538h-4.704v2.013h2.704v11.4
|
|
25
|
+
c-0.644,0.488-1.081,0.819-1.081,0.819l1.105,1.459l5.552-4.207c0,0,0-2.021,0-2.073C82.639,28.851,82.529,28.809,82.457,28.864z"
|
|
26
|
+
/>
|
|
27
|
+
<path d="M77.329,17.736c0,0,2.15,0,2.2,0c0.098,0,0.137-0.106,0.094-0.171c-0.04-0.061-2.775-4.238-2.775-4.238s-2.117,0-2.2,0
|
|
28
|
+
c-0.083,0-0.144,0.096-0.098,0.166C74.596,13.562,77.329,17.736,77.329,17.736z"/>
|
|
29
|
+
<rect x="99.874" y="14.22" width="15.888" height="2.013"/>
|
|
30
|
+
<path d="M105.637,23.841H118v-2.013H97.636v2.013h5.65c-1.167,3.064-4.095,10.753-4.115,10.809
|
|
31
|
+
c-0.032,0.089,0.026,0.155,0.104,0.155c0.049,0,17.523,0,17.564,0c0.083,0,0.131-0.082,0.101-0.16
|
|
32
|
+
c-0.019-0.049-2.619-6.885-2.619-6.885s-2.103,0-2.186,0s-0.133,0.08-0.105,0.153c0.028,0.073,1.853,4.879,1.853,4.879h-11.646
|
|
33
|
+
L105.637,23.841z"/>
|
|
34
|
+
</g>
|
|
35
|
+
<g>
|
|
36
|
+
<path style="fill:#00A3FF;" d="M39.157,33.89c-0.764,0.756-2.125,1.613-4.361,1.689c-1.034,0.035-2.241,0.039-2.793,0.039
|
|
37
|
+
c-0.603,0-5.918,0-12.012,0c4.37-4.245,8.182-7.947,8.615-8.367c0.396-0.385,1.287-1.237,2.056-1.929
|
|
38
|
+
c1.687-1.519,3.206-1.825,4.28-1.815c1.683,0.016,3.214,0.703,4.308,1.813C41.591,27.712,41.535,31.536,39.157,33.89
|
|
39
|
+
M42.034,22.597c-1.795-1.83-4.296-2.983-7.077-2.984c-2.404,0-4.474,0.829-6.281,2.3c-0.788,0.641-1.614,1.409-2.653,2.419
|
|
40
|
+
c-0.516,0.501-15.485,15.026-15.485,15.026c0.785,0.112,1.864,0.145,2.826,0.151c0.902,0.006,18.1,0.004,18.82,0.004
|
|
41
|
+
c1.449,0,2.392-0.002,3.405-0.076c2.323-0.17,4.518-1.022,6.292-2.764C45.82,32.805,45.879,26.526,42.034,22.597z"/>
|
|
42
|
+
<path style="fill:#00C8DC;" d="M17.883,21.663c-1.76-1.317-3.729-2.053-5.963-2.05c-2.781,0-5.283,1.153-7.077,2.984
|
|
43
|
+
c-3.845,3.93-3.786,10.209,0.154,14.077c1.582,1.553,3.498,2.398,5.541,2.684l3.854-3.74c-0.623-0.003-1.518-0.011-2.311-0.038
|
|
44
|
+
c-2.235-0.076-3.597-0.934-4.361-1.689c-2.379-2.354-2.434-6.178-0.094-8.57c1.094-1.11,2.625-1.797,4.308-1.813
|
|
45
|
+
c1.055-0.004,2.486,0.302,4.103,1.643c0.772,0.64,2.486,2.147,3.239,2.825c0.038,0.035,0.084,0.038,0.129,0.001l2.654-2.589
|
|
46
|
+
c0.046-0.045,0.043-0.105-0.002-0.146C20.781,24.088,18.972,22.474,17.883,21.663"/>
|
|
47
|
+
<path style="fill:#006EFF;" d="M36,17.365c-1.831-5.172-6.762-8.879-12.562-8.879c-6.652,0-12.165,4.892-13.164,11.264
|
|
48
|
+
c0.535-0.09,1.085-0.138,1.646-0.138c0.781-0.001,1.529,0.09,2.248,0.263c0.014,0.003,0.028,0.005,0.042,0.008
|
|
49
|
+
c0.901-4.302,4.705-7.498,9.228-7.498c3.767,0,7.072,2.272,8.562,5.492c0.023,0.051,0.063,0.067,0.104,0.056
|
|
50
|
+
c1.121-0.308,2.464-0.487,3.762-0.391C35.992,17.552,36.04,17.481,36,17.365"/>
|
|
51
|
+
</g>
|
|
52
|
+
</g>
|
|
53
|
+
</svg>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cloneDeep } from 'lodash';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import type { IStageConfigProps } from '@spinnaker/core';
|
|
5
|
+
import { FormikStageConfig } from '@spinnaker/core';
|
|
6
|
+
|
|
7
|
+
import { DisableClusterStageForm } from './DisableClusterStageForm';
|
|
8
|
+
|
|
9
|
+
export function DisableClusterConfig({ application, pipeline, stage, updateStage }: IStageConfigProps) {
|
|
10
|
+
const stageWithDefaults = React.useMemo(() => {
|
|
11
|
+
return {
|
|
12
|
+
cloudProvider: 'tencentcloud',
|
|
13
|
+
regions: stage.regions || [],
|
|
14
|
+
...cloneDeep(stage),
|
|
15
|
+
};
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FormikStageConfig
|
|
20
|
+
application={application}
|
|
21
|
+
onChange={updateStage}
|
|
22
|
+
pipeline={pipeline}
|
|
23
|
+
stage={stageWithDefaults}
|
|
24
|
+
render={(props) => <DisableClusterStageForm {...props} />}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { IAccount, IFormikStageConfigInjectedProps } from '@spinnaker/core';
|
|
4
|
+
import { AccountService, FormikFormField, NgReact, NumberInput, SelectInput, StageConfigField } from '@spinnaker/core';
|
|
5
|
+
|
|
6
|
+
const { useEffect, useState } = React;
|
|
7
|
+
const { AccountRegionClusterSelector } = NgReact;
|
|
8
|
+
|
|
9
|
+
export function DisableClusterStageForm({ application, formik, pipeline }: IFormikStageConfigInjectedProps) {
|
|
10
|
+
const stage = formik.values;
|
|
11
|
+
const { setFieldValue } = formik;
|
|
12
|
+
const [accounts, setAccounts] = useState([]);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
AccountService.listAccounts('tencentcloud').then((accounts: IAccount[]) => {
|
|
16
|
+
setAccounts(accounts);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
stage.isNew &&
|
|
21
|
+
application?.attributes?.platformHealthOnlyShowOverride &&
|
|
22
|
+
application?.attributes?.platformHealthOnly
|
|
23
|
+
) {
|
|
24
|
+
setFieldValue('interestingHealthProviderNames', ['Tencentcloud']);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!stage.credentials && application?.defaultCredentials?.tencentcloud) {
|
|
28
|
+
setFieldValue('credentials', application?.defaultCredentials?.tencentcloud);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!stage?.regions?.length && application?.defaultRegions?.tencentcloud) {
|
|
32
|
+
setFieldValue('regions', [...stage.regions, application?.defaultRegions?.tencentcloud]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (stage.remainingEnabledServerGroups === undefined) {
|
|
36
|
+
setFieldValue('remainingEnabledServerGroups', 1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (stage.preferLargerOverNewer === undefined) {
|
|
40
|
+
setFieldValue('preferLargerOverNewer', 'false');
|
|
41
|
+
}
|
|
42
|
+
}, []);
|
|
43
|
+
|
|
44
|
+
const pluralize = function (str: string, val: string | number) {
|
|
45
|
+
if (val === 1) {
|
|
46
|
+
return str;
|
|
47
|
+
}
|
|
48
|
+
return str + 's';
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className="form-horizontal">
|
|
53
|
+
{!pipeline.strategy && (
|
|
54
|
+
<AccountRegionClusterSelector
|
|
55
|
+
application={application}
|
|
56
|
+
clusterField="cluster"
|
|
57
|
+
component={stage}
|
|
58
|
+
accounts={accounts}
|
|
59
|
+
/>
|
|
60
|
+
)}
|
|
61
|
+
<StageConfigField label="Disable Options">
|
|
62
|
+
<div className="form-inline">
|
|
63
|
+
Keep the
|
|
64
|
+
<FormikFormField
|
|
65
|
+
name="remainingEnabledServerGroups"
|
|
66
|
+
required
|
|
67
|
+
input={(props) => <NumberInput {...props} min={0} />}
|
|
68
|
+
/>
|
|
69
|
+
<FormikFormField
|
|
70
|
+
name="preferLargerOverNewer"
|
|
71
|
+
required
|
|
72
|
+
input={(props) => (
|
|
73
|
+
<SelectInput
|
|
74
|
+
options={[
|
|
75
|
+
{ label: 'largest', value: 'true' },
|
|
76
|
+
{ label: 'newest', value: 'false' },
|
|
77
|
+
]}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
)}
|
|
81
|
+
/>
|
|
82
|
+
{pluralize('server group', stage.remainingEnabledServerGroups)} enabled.
|
|
83
|
+
</div>
|
|
84
|
+
</StageConfigField>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Registry } from '@spinnaker/core';
|
|
2
|
+
|
|
3
|
+
import { DisableClusterConfig } from './DisableClusterConfig';
|
|
4
|
+
import { validate } from './disableClusterValidators';
|
|
5
|
+
|
|
6
|
+
Registry.pipeline.registerStage({
|
|
7
|
+
provides: 'disableCluster',
|
|
8
|
+
key: 'disableCluster',
|
|
9
|
+
cloudProvider: 'tencentcloud',
|
|
10
|
+
component: DisableClusterConfig,
|
|
11
|
+
validateFn: validate,
|
|
12
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IContextualValidator, IStage } from '@spinnaker/core';
|
|
2
|
+
import { FormValidator } from '@spinnaker/core';
|
|
3
|
+
|
|
4
|
+
export const validate: IContextualValidator = (stage: IStage) => {
|
|
5
|
+
const formValidator = new FormValidator(stage);
|
|
6
|
+
formValidator.field('credentials', 'Account').required();
|
|
7
|
+
formValidator.field('regions', 'Regions').required();
|
|
8
|
+
formValidator.field('cluster', 'Cluster').required();
|
|
9
|
+
return formValidator.validateForm();
|
|
10
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cloneDeep } from 'lodash';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import type { IStageConfigProps } from '@spinnaker/core';
|
|
5
|
+
import { FormikStageConfig } from '@spinnaker/core';
|
|
6
|
+
|
|
7
|
+
import { RollbackClusterStageForm } from './RollbackClusterStageForm';
|
|
8
|
+
|
|
9
|
+
export function RollbackClusterConfig({ application, pipeline, stage, updateStage }: IStageConfigProps) {
|
|
10
|
+
const stageWithDefaults = React.useMemo(() => {
|
|
11
|
+
return {
|
|
12
|
+
cloudProvider: 'tencentcloud',
|
|
13
|
+
regions: stage.regions || [],
|
|
14
|
+
...cloneDeep(stage),
|
|
15
|
+
};
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FormikStageConfig
|
|
20
|
+
application={application}
|
|
21
|
+
onChange={updateStage}
|
|
22
|
+
pipeline={pipeline}
|
|
23
|
+
stage={stageWithDefaults}
|
|
24
|
+
render={(props) => <RollbackClusterStageForm {...props} />}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { IAccount, IFormikStageConfigInjectedProps } from '@spinnaker/core';
|
|
4
|
+
import { AccountService, FormikFormField, NgReact, NumberInput, StageConfigField } from '@spinnaker/core';
|
|
5
|
+
|
|
6
|
+
const { useEffect, useState } = React;
|
|
7
|
+
const { AccountRegionClusterSelector } = NgReact;
|
|
8
|
+
|
|
9
|
+
export function RollbackClusterStageForm({ application, formik, pipeline }: IFormikStageConfigInjectedProps) {
|
|
10
|
+
const stage = formik.values;
|
|
11
|
+
const { setFieldValue } = formik;
|
|
12
|
+
const [accounts, setAccounts] = useState([]);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
AccountService.listAccounts('tencentcloud').then((accounts: IAccount[]) => {
|
|
16
|
+
setAccounts(accounts);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
stage.isNew &&
|
|
21
|
+
application?.attributes?.platformHealthOnlyShowOverride &&
|
|
22
|
+
application?.attributes?.platformHealthOnly
|
|
23
|
+
) {
|
|
24
|
+
setFieldValue('interestingHealthProviderNames', ['Tencentcloud']);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!stage.credentials && application?.defaultCredentials?.tencentcloud) {
|
|
28
|
+
setFieldValue('credentials', application?.defaultCredentials?.tencentcloud);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!stage?.regions?.length && application?.defaultRegions?.tencentcloud) {
|
|
32
|
+
setFieldValue('regions', [...stage.regions, application?.defaultRegions?.tencentcloud]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (stage.remainingEnabledServerGroups === undefined) {
|
|
36
|
+
setFieldValue('remainingEnabledServerGroups', 1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (stage.preferLargerOverNewer === undefined) {
|
|
40
|
+
setFieldValue('preferLargerOverNewer', 'false');
|
|
41
|
+
}
|
|
42
|
+
}, []);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div className="form-horizontal">
|
|
46
|
+
{!pipeline.strategy && (
|
|
47
|
+
<AccountRegionClusterSelector
|
|
48
|
+
application={application}
|
|
49
|
+
clusterField="cluster"
|
|
50
|
+
component={stage}
|
|
51
|
+
accounts={accounts}
|
|
52
|
+
/>
|
|
53
|
+
)}
|
|
54
|
+
<StageConfigField label="Rollback Options">
|
|
55
|
+
<div className="row">
|
|
56
|
+
<div className="col-sm-10 col-sm-offset-2">
|
|
57
|
+
Wait
|
|
58
|
+
<FormikFormField name="wait" required input={(props) => <NumberInput {...props} min={0} />} />
|
|
59
|
+
seconds between regional rollbacks.
|
|
60
|
+
</div>
|
|
61
|
+
<div className="col-sm-10 col-sm-offset-2">
|
|
62
|
+
Consider rollback successful when
|
|
63
|
+
<FormikFormField
|
|
64
|
+
name="remainingEnabledServerGroups"
|
|
65
|
+
required
|
|
66
|
+
input={(props) => <NumberInput {...props} min={0} max={100} />}
|
|
67
|
+
/>
|
|
68
|
+
percent of instances are healthy.
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</StageConfigField>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Registry } from '@spinnaker/core';
|
|
2
|
+
|
|
3
|
+
import { RollbackClusterConfig } from './RollbackClusterConfig';
|
|
4
|
+
import { validate } from './rollbackClusterValidators';
|
|
5
|
+
|
|
6
|
+
Registry.pipeline.registerStage({
|
|
7
|
+
provides: 'rollbackCluster',
|
|
8
|
+
key: 'rollbackCluster',
|
|
9
|
+
cloudProvider: 'tencentcloud',
|
|
10
|
+
component: RollbackClusterConfig,
|
|
11
|
+
validateFn: validate,
|
|
12
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IContextualValidator, IStage } from '@spinnaker/core';
|
|
2
|
+
import { FormValidator } from '@spinnaker/core';
|
|
3
|
+
|
|
4
|
+
export const validate: IContextualValidator = (stage: IStage) => {
|
|
5
|
+
const formValidator = new FormValidator(stage);
|
|
6
|
+
formValidator.field('credentials', 'Account').required();
|
|
7
|
+
formValidator.field('regions', 'Regions').required();
|
|
8
|
+
formValidator.field('cluster', 'Cluster').required();
|
|
9
|
+
return formValidator.validateForm();
|
|
10
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cloneDeep } from 'lodash';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import type { IStageConfigProps } from '@spinnaker/core';
|
|
5
|
+
import { FormikStageConfig } from '@spinnaker/core';
|
|
6
|
+
|
|
7
|
+
import { ScaleDownClusterStageForm } from './ScaleDownClusterStageForm';
|
|
8
|
+
|
|
9
|
+
export function ScaleDownClusterConfig({ application, pipeline, stage, updateStage }: IStageConfigProps) {
|
|
10
|
+
const stageWithDefaults = React.useMemo(() => {
|
|
11
|
+
return {
|
|
12
|
+
cloudProvider: 'tencentcloud',
|
|
13
|
+
regions: stage.regions || [],
|
|
14
|
+
...cloneDeep(stage),
|
|
15
|
+
};
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FormikStageConfig
|
|
20
|
+
application={application}
|
|
21
|
+
onChange={updateStage}
|
|
22
|
+
pipeline={pipeline}
|
|
23
|
+
stage={stageWithDefaults}
|
|
24
|
+
render={(props) => <ScaleDownClusterStageForm {...props} />}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { IAccount, IFormikStageConfigInjectedProps } from '@spinnaker/core';
|
|
4
|
+
import {
|
|
5
|
+
AccountService,
|
|
6
|
+
CheckboxInput,
|
|
7
|
+
FormikFormField,
|
|
8
|
+
NgReact,
|
|
9
|
+
NumberInput,
|
|
10
|
+
SelectInput,
|
|
11
|
+
StageConfigField,
|
|
12
|
+
} from '@spinnaker/core';
|
|
13
|
+
|
|
14
|
+
const { useEffect, useState } = React;
|
|
15
|
+
const { AccountRegionClusterSelector } = NgReact;
|
|
16
|
+
|
|
17
|
+
export function ScaleDownClusterStageForm({ application, formik, pipeline }: IFormikStageConfigInjectedProps) {
|
|
18
|
+
const stage = formik.values;
|
|
19
|
+
const { setFieldValue } = formik;
|
|
20
|
+
const [accounts, setAccounts] = useState([]);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
AccountService.listAccounts('tencentcloud').then((accounts: IAccount[]) => {
|
|
24
|
+
setAccounts(accounts);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (
|
|
28
|
+
stage.isNew &&
|
|
29
|
+
application?.attributes?.platformHealthOnlyShowOverride &&
|
|
30
|
+
application?.attributes?.platformHealthOnly
|
|
31
|
+
) {
|
|
32
|
+
setFieldValue('interestingHealthProviderNames', ['Tencentcloud']);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!stage.credentials && application?.defaultCredentials?.tencentcloud) {
|
|
36
|
+
setFieldValue('credentials', application?.defaultCredentials?.tencentcloud);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!stage?.regions?.length && application?.defaultRegions?.tencentcloud) {
|
|
40
|
+
setFieldValue('regions', [...stage.regions, application?.defaultRegions?.tencentcloud]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (stage.remainingEnabledServerGroups === undefined) {
|
|
44
|
+
setFieldValue('remainingEnabledServerGroups', 1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (stage.preferLargerOverNewer === undefined) {
|
|
48
|
+
setFieldValue('preferLargerOverNewer', 'false');
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const pluralize = function (str: string, val: string | number) {
|
|
53
|
+
if (val === 1) {
|
|
54
|
+
return str;
|
|
55
|
+
}
|
|
56
|
+
return str + 's';
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div className="form-horizontal">
|
|
61
|
+
{!pipeline.strategy && (
|
|
62
|
+
<AccountRegionClusterSelector
|
|
63
|
+
application={application}
|
|
64
|
+
clusterField="cluster"
|
|
65
|
+
component={stage}
|
|
66
|
+
accounts={accounts}
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
69
|
+
<StageConfigField label="ScaleDown Options">
|
|
70
|
+
<div className="form-inline">
|
|
71
|
+
Keep the
|
|
72
|
+
<FormikFormField
|
|
73
|
+
name="remainingEnabledServerGroups"
|
|
74
|
+
required
|
|
75
|
+
input={(props) => <NumberInput {...props} min={0} />}
|
|
76
|
+
/>
|
|
77
|
+
<FormikFormField
|
|
78
|
+
name="preferLargerOverNewer"
|
|
79
|
+
required
|
|
80
|
+
input={(props) => (
|
|
81
|
+
<SelectInput
|
|
82
|
+
options={[
|
|
83
|
+
{ label: 'largest', value: 'true' },
|
|
84
|
+
{ label: 'newest', value: 'false' },
|
|
85
|
+
]}
|
|
86
|
+
{...props}
|
|
87
|
+
/>
|
|
88
|
+
)}
|
|
89
|
+
/>
|
|
90
|
+
{pluralize('server group', stage.remainingFullSizeServerGroups)} at current size.
|
|
91
|
+
<p>The remaining server groups will be scaled down to zero instances.</p>
|
|
92
|
+
</div>
|
|
93
|
+
</StageConfigField>
|
|
94
|
+
<div className="form-group">
|
|
95
|
+
<FormikFormField
|
|
96
|
+
name="allowScaleDownActive"
|
|
97
|
+
input={(props) => <CheckboxInput {...props} text="Allow scale down of active server groups" />}
|
|
98
|
+
/>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Registry } from '@spinnaker/core';
|
|
2
|
+
|
|
3
|
+
import { ScaleDownClusterConfig } from './ScaleDownClusterConfig';
|
|
4
|
+
import { validate } from './scaledownClusterValidators';
|
|
5
|
+
|
|
6
|
+
Registry.pipeline.registerStage({
|
|
7
|
+
provides: 'scaleDownCluster',
|
|
8
|
+
key: 'scaleDownCluster',
|
|
9
|
+
cloudProvider: 'tencentcloud',
|
|
10
|
+
component: ScaleDownClusterConfig,
|
|
11
|
+
validateFn: validate,
|
|
12
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IContextualValidator, IStage } from '@spinnaker/core';
|
|
2
|
+
import { FormValidator } from '@spinnaker/core';
|
|
3
|
+
|
|
4
|
+
export const validate: IContextualValidator = (stage: IStage) => {
|
|
5
|
+
const formValidator = new FormValidator(stage);
|
|
6
|
+
formValidator.field('credentials', 'Account').required();
|
|
7
|
+
formValidator.field('regions', 'Regions').required();
|
|
8
|
+
formValidator.field('cluster', 'Cluster').required();
|
|
9
|
+
return formValidator.validateForm();
|
|
10
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cloneDeep } from 'lodash';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import type { IStageConfigProps } from '@spinnaker/core';
|
|
5
|
+
import { FormikStageConfig } from '@spinnaker/core';
|
|
6
|
+
|
|
7
|
+
import { ShrinkClusterStageForm } from './ShrinkClusterStageForm';
|
|
8
|
+
|
|
9
|
+
export function ShrinkClusterConfig({ application, pipeline, stage, updateStage }: IStageConfigProps) {
|
|
10
|
+
const stageWithDefaults = React.useMemo(() => {
|
|
11
|
+
return {
|
|
12
|
+
cloudProvider: 'tencentcloud',
|
|
13
|
+
regions: stage.regions || [],
|
|
14
|
+
...cloneDeep(stage),
|
|
15
|
+
};
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FormikStageConfig
|
|
20
|
+
application={application}
|
|
21
|
+
onChange={updateStage}
|
|
22
|
+
pipeline={pipeline}
|
|
23
|
+
stage={stageWithDefaults}
|
|
24
|
+
render={(props) => <ShrinkClusterStageForm {...props} />}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { IAccount, IFormikStageConfigInjectedProps } from '@spinnaker/core';
|
|
4
|
+
import {
|
|
5
|
+
AccountService,
|
|
6
|
+
CheckboxInput,
|
|
7
|
+
FormikFormField,
|
|
8
|
+
NgReact,
|
|
9
|
+
NumberInput,
|
|
10
|
+
SelectInput,
|
|
11
|
+
StageConfigField,
|
|
12
|
+
} from '@spinnaker/core';
|
|
13
|
+
|
|
14
|
+
const { useEffect, useState } = React;
|
|
15
|
+
const { AccountRegionClusterSelector } = NgReact;
|
|
16
|
+
|
|
17
|
+
export function ShrinkClusterStageForm({ application, formik, pipeline }: IFormikStageConfigInjectedProps) {
|
|
18
|
+
const stage = formik.values;
|
|
19
|
+
const { setFieldValue } = formik;
|
|
20
|
+
const [accounts, setAccounts] = useState([]);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
AccountService.listAccounts('tencentcloud').then((accounts: IAccount[]) => {
|
|
24
|
+
setAccounts(accounts);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (
|
|
28
|
+
stage.isNew &&
|
|
29
|
+
application?.attributes?.platformHealthOnlyShowOverride &&
|
|
30
|
+
application?.attributes?.platformHealthOnly
|
|
31
|
+
) {
|
|
32
|
+
setFieldValue('interestingHealthProviderNames', ['Tencentcloud']);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!stage.credentials && application?.defaultCredentials?.tencentcloud) {
|
|
36
|
+
setFieldValue('credentials', application?.defaultCredentials?.tencentcloud);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!stage?.regions?.length && application?.defaultRegions?.tencentcloud) {
|
|
40
|
+
setFieldValue('regions', [...stage.regions, application?.defaultRegions?.tencentcloud]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (stage.remainingEnabledServerGroups === undefined) {
|
|
44
|
+
setFieldValue('remainingEnabledServerGroups', 1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (stage.preferLargerOverNewer === undefined) {
|
|
48
|
+
setFieldValue('preferLargerOverNewer', 'false');
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const pluralize = function (str: string, val: string | number) {
|
|
53
|
+
if (val === 1) {
|
|
54
|
+
return str;
|
|
55
|
+
}
|
|
56
|
+
return str + 's';
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div className="form-horizontal">
|
|
61
|
+
{!pipeline.strategy && (
|
|
62
|
+
<AccountRegionClusterSelector
|
|
63
|
+
application={application}
|
|
64
|
+
clusterField="cluster"
|
|
65
|
+
component={stage}
|
|
66
|
+
accounts={accounts}
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
69
|
+
<StageConfigField label="Shrink Options">
|
|
70
|
+
<div className="form-inline">
|
|
71
|
+
Shrink to
|
|
72
|
+
<FormikFormField
|
|
73
|
+
name="remainingEnabledServerGroups"
|
|
74
|
+
required
|
|
75
|
+
input={(props) => <NumberInput {...props} min={0} />}
|
|
76
|
+
/>
|
|
77
|
+
{pluralize('server group', stage.shrinkToSize)}, keeping the
|
|
78
|
+
<FormikFormField
|
|
79
|
+
name="retainLargerOverNewer"
|
|
80
|
+
required
|
|
81
|
+
input={(props) => (
|
|
82
|
+
<SelectInput
|
|
83
|
+
options={[
|
|
84
|
+
{ label: 'largest', value: 'true' },
|
|
85
|
+
{ label: 'newest', value: 'false' },
|
|
86
|
+
]}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
/>
|
|
91
|
+
{pluralize('server group', stage.remainingEnabledServerGroups)} enabled.
|
|
92
|
+
</div>
|
|
93
|
+
</StageConfigField>
|
|
94
|
+
<div className="form-group">
|
|
95
|
+
<div className="col-md-offset-3 col-md-6 checkbox">
|
|
96
|
+
<FormikFormField
|
|
97
|
+
name="allowDeleteActive"
|
|
98
|
+
input={(props) => <CheckboxInput {...props} text="Allow deletion of active server groups" />}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Registry } from '@spinnaker/core';
|
|
2
|
+
|
|
3
|
+
import { ShrinkClusterConfig } from './ShrinkClusterConfig';
|
|
4
|
+
import { validate } from './shrinkClusterValidators';
|
|
5
|
+
|
|
6
|
+
Registry.pipeline.registerStage({
|
|
7
|
+
provides: 'shrinkCluster',
|
|
8
|
+
key: 'shrinkCluster',
|
|
9
|
+
cloudProvider: 'tencentcloud',
|
|
10
|
+
component: ShrinkClusterConfig,
|
|
11
|
+
validateFn: validate,
|
|
12
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IContextualValidator, IStage } from '@spinnaker/core';
|
|
2
|
+
import { FormValidator } from '@spinnaker/core';
|
|
3
|
+
|
|
4
|
+
export const validate: IContextualValidator = (stage: IStage) => {
|
|
5
|
+
const formValidator = new FormValidator(stage);
|
|
6
|
+
formValidator.field('credentials', 'Account').required();
|
|
7
|
+
formValidator.field('regions', 'Regions').required();
|
|
8
|
+
formValidator.field('cluster', 'Cluster').required();
|
|
9
|
+
return formValidator.validateForm();
|
|
10
|
+
};
|