@spinnaker/titus 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 +2661 -0
- package/LICENSE.txt +203 -0
- package/dist/domain/IJobDisruptionBudget.d.ts +35 -0
- package/dist/domain/ITitusCredentials.d.ts +5 -0
- package/dist/domain/ITitusInstance.d.ts +28 -0
- package/dist/domain/ITitusScalingPolicy.d.ts +4 -0
- package/dist/domain/ITitusServerGroup.d.ts +52 -0
- package/dist/domain/ITitusServiceJobProcesses.d.ts +3 -0
- package/dist/domain/index.d.ts +5 -0
- package/dist/help/titus.help.d.ts +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +12828 -0
- package/dist/index.js.map +1 -0
- package/dist/instance/details/TitusInstanceDetails.d.ts +25 -0
- package/dist/instance/details/TitusInstanceDns.d.ts +8 -0
- package/dist/instance/details/TitusInstanceInformation.d.ts +7 -0
- package/dist/instance/details/index.d.ts +4 -0
- package/dist/instance/details/titusInstanceDetailsUtils.d.ts +14 -0
- package/dist/pipeline/stages/cloneServerGroup/cloneServerGroupExecutionDetails.controller.d.ts +2 -0
- package/dist/pipeline/stages/cloneServerGroup/titusCloneServerGroupStage.d.ts +2 -0
- package/dist/pipeline/stages/destroyAsg/titusDestroyAsgStage.d.ts +2 -0
- package/dist/pipeline/stages/disableAsg/titusDisableAsgStage.d.ts +2 -0
- package/dist/pipeline/stages/disableCluster/titusDisableClusterStage.d.ts +2 -0
- package/dist/pipeline/stages/enableAsg/titusEnableAsgStage.d.ts +2 -0
- package/dist/pipeline/stages/findAmi/titusFindAmiStage.d.ts +2 -0
- package/dist/pipeline/stages/resizeAsg/titusResizeAsgStage.d.ts +2 -0
- package/dist/pipeline/stages/runJob/RunJobExecutionDetails.d.ts +16 -0
- package/dist/pipeline/stages/runJob/TitusRunJobStageConfig.d.ts +25 -0
- package/dist/pipeline/stages/runJob/TitusSecurityGroupPicker.d.ts +34 -0
- package/dist/pipeline/stages/runJob/titusRunJobStage.d.ts +1 -0
- package/dist/pipeline/stages/scaleDownCluster/titusScaleDownClusterStage.d.ts +2 -0
- package/dist/pipeline/stages/shrinkCluster/titusShrinkClusterStage.d.ts +2 -0
- package/dist/reactShims/index.d.ts +1 -0
- package/dist/reactShims/titus.react.injector.d.ts +11 -0
- package/dist/reactShims/titus.react.module.d.ts +1 -0
- package/dist/securityGroup/securityGroup.read.service.d.ts +2 -0
- package/dist/serverGroup/configure/ServerGroupCommandBuilder.d.ts +2 -0
- package/dist/serverGroup/configure/serverGroup.configure.titus.module.d.ts +2 -0
- package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +89 -0
- package/dist/serverGroup/configure/wizard/TitusCloneServerGroupModal.d.ts +31 -0
- package/dist/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.d.ts +28 -0
- package/dist/serverGroup/configure/wizard/pages/ServerGroupParameters.d.ts +15 -0
- package/dist/serverGroup/configure/wizard/pages/ServerGroupResources.d.ts +11 -0
- package/dist/serverGroup/configure/wizard/pages/TitusMapLayout.d.ts +4 -0
- package/dist/serverGroup/configure/wizard/pages/disruptionBudget/JobDisruptionBudget.d.ts +40 -0
- package/dist/serverGroup/configure/wizard/pages/disruptionBudget/PolicyOptions.d.ts +2 -0
- package/dist/serverGroup/configure/wizard/pages/disruptionBudget/RateOptions.d.ts +2 -0
- package/dist/serverGroup/configure/wizard/pages/disruptionBudget/WindowPicker.d.ts +23 -0
- package/dist/serverGroup/configure/wizard/pages/index.d.ts +4 -0
- package/dist/serverGroup/details/TitusCapacityDetailsSection.d.ts +11 -0
- package/dist/serverGroup/details/TitusLaunchConfigSection.d.ts +9 -0
- package/dist/serverGroup/details/TitusPackageDetailsSection.d.ts +6 -0
- package/dist/serverGroup/details/TitusSecurityGroups.d.ts +17 -0
- package/dist/serverGroup/details/capacityDetailsSection.component.d.ts +1 -0
- package/dist/serverGroup/details/disruptionBudget/DisruptionBudgetSection.d.ts +19 -0
- package/dist/serverGroup/details/disruptionBudget/EditDisruptionBudgetModal.d.ts +14 -0
- package/dist/serverGroup/details/index.d.ts +5 -0
- package/dist/serverGroup/details/launchConfigSection.component.d.ts +1 -0
- package/dist/serverGroup/details/resize/TitusResizeServerGroupModal.d.ts +8 -0
- package/dist/serverGroup/details/resize/useTaskMonitor.d.ts +25 -0
- package/dist/serverGroup/details/rollback/rollbackServerGroup.controller.d.ts +2 -0
- package/dist/serverGroup/details/scalingActivity/TitusScalingActivitiesModal.d.ts +7 -0
- package/dist/serverGroup/details/scalingPolicy/CreateScalingPolicyButton.d.ts +21 -0
- package/dist/serverGroup/details/scalingPolicy/TitusCustomScalingPolicy.d.ts +7 -0
- package/dist/serverGroup/details/scalingPolicy/createScalingPolicyButton.component.d.ts +1 -0
- package/dist/serverGroup/details/scalingPolicy/index.d.ts +3 -0
- package/dist/serverGroup/details/scalingPolicy/scalingPolicy.module.d.ts +1 -0
- package/dist/serverGroup/details/scalingPolicy/targetTracking/TitusTargetTrackingChart.d.ts +9 -0
- package/dist/serverGroup/details/scalingPolicy/targetTracking/UpsertTargetTrackingModal.d.ts +10 -0
- package/dist/serverGroup/details/scalingPolicy/titusCustomScalingPolicy.component.d.ts +1 -0
- package/dist/serverGroup/details/scalingPolicy/upsert/TitusScalingPolicyCommandBuilderService.d.ts +10 -0
- package/dist/serverGroup/details/scalingPolicy/upsert/UpsertScalingPolicyModal.d.ts +10 -0
- package/dist/serverGroup/details/sections/ITitusServerGroupDetailsSectionProps.d.ts +5 -0
- package/dist/serverGroup/details/serverGroupDetails.titus.controller.d.ts +2 -0
- package/dist/serverGroup/details/serviceJobProcesses/ServiceJobProcesses.d.ts +3 -0
- package/dist/serverGroup/details/serviceJobProcesses/ServiceJobProcessesSection.d.ts +7 -0
- package/dist/serverGroup/details/titusPackageDetailsSection.component.d.ts +1 -0
- package/dist/serverGroup/details/titusSecurityGroups.component.d.ts +1 -0
- package/dist/serverGroup/serverGroup.transformer.d.ts +2 -0
- package/dist/titus.module.d.ts +5 -0
- package/dist/titus.settings.d.ts +14 -0
- package/dist/validation/ApplicationNameValidator.d.ts +1 -0
- package/package.json +52 -0
- package/src/domain/IJobDisruptionBudget.ts +19 -0
- package/src/domain/ITitusCredentials.ts +6 -0
- package/src/domain/ITitusInstance.ts +30 -0
- package/src/domain/ITitusScalingPolicy.ts +5 -0
- package/src/domain/ITitusServerGroup.ts +56 -0
- package/src/domain/ITitusServiceJobProcesses.ts +3 -0
- package/src/domain/index.ts +5 -0
- package/src/help/titus.help.ts +99 -0
- package/src/index.ts +6 -0
- package/src/instance/details/TitusInstanceDetails.tsx +234 -0
- package/src/instance/details/TitusInstanceDns.tsx +40 -0
- package/src/instance/details/TitusInstanceInformation.tsx +42 -0
- package/src/instance/details/index.ts +4 -0
- package/src/instance/details/titusInstanceDetailsUtils.spec.ts +124 -0
- package/src/instance/details/titusInstanceDetailsUtils.ts +181 -0
- package/src/logo/titus.logo.less +5 -0
- package/src/logo/titus.logo.png +0 -0
- package/src/logo/titus.logo.svg +7 -0
- package/src/pipeline/stages/cloneServerGroup/cloneServerGroupExecutionDetails.controller.js +66 -0
- package/src/pipeline/stages/cloneServerGroup/cloneServerGroupExecutionDetails.html +46 -0
- package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStage.html +106 -0
- package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStepLabel.html +1 -0
- package/src/pipeline/stages/cloneServerGroup/titusCloneServerGroupStage.js +104 -0
- package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +9 -0
- package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +1 -0
- package/src/pipeline/stages/destroyAsg/titusDestroyAsgStage.js +65 -0
- package/src/pipeline/stages/disableAsg/disableAsgStage.html +11 -0
- package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +1 -0
- package/src/pipeline/stages/disableAsg/titusDisableAsgStage.js +69 -0
- package/src/pipeline/stages/disableCluster/disableClusterStage.html +26 -0
- package/src/pipeline/stages/disableCluster/titusDisableClusterStage.js +85 -0
- package/src/pipeline/stages/enableAsg/enableAsgStage.html +11 -0
- package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +1 -0
- package/src/pipeline/stages/enableAsg/titusEnableAsgStage.js +73 -0
- package/src/pipeline/stages/findAmi/findAmiStage.html +24 -0
- package/src/pipeline/stages/findAmi/titusFindAmiStage.js +79 -0
- package/src/pipeline/stages/resizeAsg/resizeAsgStage.html +99 -0
- package/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html +1 -0
- package/src/pipeline/stages/resizeAsg/titusResizeAsgStage.js +125 -0
- package/src/pipeline/stages/runJob/RunJobExecutionDetails.tsx +165 -0
- package/src/pipeline/stages/runJob/TitusRunJobStageConfig.tsx +466 -0
- package/src/pipeline/stages/runJob/TitusSecurityGroupPicker.tsx +170 -0
- package/src/pipeline/stages/runJob/titusRunJobStage.ts +30 -0
- package/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html +35 -0
- package/src/pipeline/stages/scaleDownCluster/titusScaleDownClusterStage.js +79 -0
- package/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html +34 -0
- package/src/pipeline/stages/shrinkCluster/titusShrinkClusterStage.js +73 -0
- package/src/reactShims/index.ts +1 -0
- package/src/reactShims/titus.react.injector.ts +17 -0
- package/src/reactShims/titus.react.module.ts +10 -0
- package/src/securityGroup/securityGroup.read.service.js +15 -0
- package/src/serverGroup/configure/ServerGroupCommandBuilder.js +247 -0
- package/src/serverGroup/configure/serverGroup.configure.titus.module.js +9 -0
- package/src/serverGroup/configure/serverGroupCommandBuilder.spec.js +63 -0
- package/src/serverGroup/configure/serverGroupConfiguration.service.ts +410 -0
- package/src/serverGroup/configure/wizard/TitusCloneServerGroupModal.tsx +293 -0
- package/src/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.tsx +339 -0
- package/src/serverGroup/configure/wizard/pages/ServerGroupParameters.less +5 -0
- package/src/serverGroup/configure/wizard/pages/ServerGroupParameters.tsx +217 -0
- package/src/serverGroup/configure/wizard/pages/ServerGroupResources.tsx +200 -0
- package/src/serverGroup/configure/wizard/pages/TitusMapLayout.less +3 -0
- package/src/serverGroup/configure/wizard/pages/TitusMapLayout.tsx +29 -0
- package/src/serverGroup/configure/wizard/pages/disruptionBudget/JobDisruptionBudget.tsx +285 -0
- package/src/serverGroup/configure/wizard/pages/disruptionBudget/PolicyOptions.tsx +112 -0
- package/src/serverGroup/configure/wizard/pages/disruptionBudget/RateOptions.tsx +89 -0
- package/src/serverGroup/configure/wizard/pages/disruptionBudget/WindowPicker.tsx +202 -0
- package/src/serverGroup/configure/wizard/pages/index.ts +4 -0
- package/src/serverGroup/details/TitusCapacityDetailsSection.tsx +66 -0
- package/src/serverGroup/details/TitusLaunchConfigSection.tsx +35 -0
- package/src/serverGroup/details/TitusPackageDetailsSection.tsx +40 -0
- package/src/serverGroup/details/TitusSecurityGroups.tsx +107 -0
- package/src/serverGroup/details/capacityDetailsSection.component.ts +12 -0
- package/src/serverGroup/details/disruptionBudget/DisruptionBudgetSection.tsx +226 -0
- package/src/serverGroup/details/disruptionBudget/EditDisruptionBudgetModal.tsx +92 -0
- package/src/serverGroup/details/index.ts +5 -0
- package/src/serverGroup/details/launchConfigSection.component.ts +12 -0
- package/src/serverGroup/details/resize/TitusResizeServerGroupModal.tsx +302 -0
- package/src/serverGroup/details/resize/useTaskMonitor.ts +30 -0
- package/src/serverGroup/details/rollback/rollbackServerGroup.controller.js +149 -0
- package/src/serverGroup/details/rollback/rollbackServerGroup.html +133 -0
- package/src/serverGroup/details/scalingActivity/TitusScalingActivitiesModal.tsx +81 -0
- package/src/serverGroup/details/scalingPolicy/CreateScalingPolicyButton.tsx +102 -0
- package/src/serverGroup/details/scalingPolicy/TitusCustomScalingPolicy.tsx +13 -0
- package/src/serverGroup/details/scalingPolicy/createScalingPolicyButton.component.ts +15 -0
- package/src/serverGroup/details/scalingPolicy/index.js +3 -0
- package/src/serverGroup/details/scalingPolicy/scalingPolicy.module.ts +7 -0
- package/src/serverGroup/details/scalingPolicy/targetTracking/TitusTargetTrackingChart.tsx +57 -0
- package/src/serverGroup/details/scalingPolicy/targetTracking/UpsertTargetTrackingModal.tsx +82 -0
- package/src/serverGroup/details/scalingPolicy/titusCustomScalingPolicy.component.ts +17 -0
- package/src/serverGroup/details/scalingPolicy/upsert/TitusScalingPolicyCommandBuilderService.ts +115 -0
- package/src/serverGroup/details/scalingPolicy/upsert/UpsertScalingPolicyModal.tsx +157 -0
- package/src/serverGroup/details/sections/ITitusServerGroupDetailsSectionProps.ts +6 -0
- package/src/serverGroup/details/serverGroupDetails.html +191 -0
- package/src/serverGroup/details/serverGroupDetails.titus.controller.js +457 -0
- package/src/serverGroup/details/serviceJobProcesses/ServiceJobProcesses.ts +12 -0
- package/src/serverGroup/details/serviceJobProcesses/ServiceJobProcessesSection.tsx +136 -0
- package/src/serverGroup/details/titusPackageDetailsSection.component.ts +12 -0
- package/src/serverGroup/details/titusSecurityGroups.component.ts +12 -0
- package/src/serverGroup/serverGroup.transformer.js +90 -0
- package/src/titus.module.ts +95 -0
- package/src/titus.settings.ts +22 -0
- package/src/validation/ApplicationNameValidator.ts +43 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import type { FormikErrors, FormikProps } from 'formik';
|
|
2
|
+
import { Field } from 'formik';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { AWSProviderSettings, SubnetSelectField } from '@spinnaker/amazon';
|
|
6
|
+
import type { Application, IServerGroup, IWizardPageComponent } from '@spinnaker/core';
|
|
7
|
+
import {
|
|
8
|
+
AccountSelectInput,
|
|
9
|
+
AccountTag,
|
|
10
|
+
DeployingIntoManagedClusterWarning,
|
|
11
|
+
DeploymentStrategySelector,
|
|
12
|
+
HelpField,
|
|
13
|
+
NameUtils,
|
|
14
|
+
ReactInjector,
|
|
15
|
+
RegionSelectField,
|
|
16
|
+
ServerGroupDetailsField,
|
|
17
|
+
ServerGroupNamePreview,
|
|
18
|
+
} from '@spinnaker/core';
|
|
19
|
+
import { DockerImageAndTagSelector, DockerImageUtils } from '@spinnaker/docker';
|
|
20
|
+
|
|
21
|
+
import type { ITitusServerGroupCommand } from '../../../configure/serverGroupConfiguration.service';
|
|
22
|
+
import { TitusProviderSettings } from '../../../../titus.settings';
|
|
23
|
+
|
|
24
|
+
const isNotExpressionLanguage = (field: string) => field && !field.includes('${');
|
|
25
|
+
|
|
26
|
+
// Allow dot, underscore, and spel
|
|
27
|
+
const isStackPattern = (stack: string) => (isNotExpressionLanguage(stack) ? /^([\w.]+|\${[^}]+})*$/.test(stack) : true);
|
|
28
|
+
|
|
29
|
+
// Allow dot, underscore, caret, tilde, dash and spel
|
|
30
|
+
const isDetailPattern = (detail: string) =>
|
|
31
|
+
isNotExpressionLanguage(detail) ? /^([\w.^~-]+|\${[^}]+})*$/.test(detail) : true;
|
|
32
|
+
|
|
33
|
+
export interface IServerGroupBasicSettingsProps {
|
|
34
|
+
app: Application;
|
|
35
|
+
formik: FormikProps<ITitusServerGroupCommand>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface IServerGroupBasicSettingsState {
|
|
39
|
+
namePreview: string;
|
|
40
|
+
createsNewCluster: boolean;
|
|
41
|
+
latestServerGroup: IServerGroup;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class ServerGroupBasicSettings
|
|
45
|
+
extends React.Component<IServerGroupBasicSettingsProps, IServerGroupBasicSettingsState>
|
|
46
|
+
implements IWizardPageComponent<ITitusServerGroupCommand> {
|
|
47
|
+
constructor(props: IServerGroupBasicSettingsProps) {
|
|
48
|
+
super(props);
|
|
49
|
+
|
|
50
|
+
const { values, setFieldValue } = this.props.formik;
|
|
51
|
+
if (values.imageId && !values.imageId.includes('${')) {
|
|
52
|
+
const { digest, organization, repository, tag } = DockerImageUtils.splitImageId(values.imageId);
|
|
53
|
+
setFieldValue('digest', digest);
|
|
54
|
+
setFieldValue('organization', organization);
|
|
55
|
+
setFieldValue('repository', repository);
|
|
56
|
+
setFieldValue('tag', tag);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this.state = {
|
|
60
|
+
...this.getStateFromProps(props),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private getStateFromProps(props: IServerGroupBasicSettingsProps) {
|
|
65
|
+
const { app } = props;
|
|
66
|
+
const { values } = props.formik;
|
|
67
|
+
const namePreview = NameUtils.getClusterName(app.name, values.stack, values.freeFormDetails);
|
|
68
|
+
const createsNewCluster = !app.clusters.find((c) => c.name === namePreview);
|
|
69
|
+
|
|
70
|
+
const inCluster = (app.serverGroups.data as IServerGroup[])
|
|
71
|
+
.filter((serverGroup) => {
|
|
72
|
+
return (
|
|
73
|
+
serverGroup.cluster === namePreview &&
|
|
74
|
+
serverGroup.account === values.credentials &&
|
|
75
|
+
serverGroup.region === values.region
|
|
76
|
+
);
|
|
77
|
+
})
|
|
78
|
+
.sort((a, b) => a.createdTime - b.createdTime);
|
|
79
|
+
const latestServerGroup = inCluster.length ? inCluster.pop() : null;
|
|
80
|
+
|
|
81
|
+
return { namePreview, createsNewCluster, latestServerGroup };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private accountUpdated = (account: string): void => {
|
|
85
|
+
const { setFieldValue, values } = this.props.formik;
|
|
86
|
+
values.credentials = account;
|
|
87
|
+
values.credentialsChanged(values);
|
|
88
|
+
setFieldValue('account', account);
|
|
89
|
+
setFieldValue('credentials', account);
|
|
90
|
+
|
|
91
|
+
const accountDetails = values.backingData.credentialsKeyedByAccount[account];
|
|
92
|
+
|
|
93
|
+
const newAttr = {
|
|
94
|
+
...values.containerAttributes,
|
|
95
|
+
'titusParameter.agent.assignIPv6Address': accountDetails.environment === 'test' ? 'true' : 'false',
|
|
96
|
+
};
|
|
97
|
+
setFieldValue('containerAttributes', newAttr);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
private regionUpdated = (region: string): void => {
|
|
101
|
+
const { values, setFieldValue } = this.props.formik;
|
|
102
|
+
values.region = region;
|
|
103
|
+
values.regionChanged(values);
|
|
104
|
+
setFieldValue('region', region);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
public validate(values: ITitusServerGroupCommand) {
|
|
108
|
+
const errors: FormikErrors<ITitusServerGroupCommand> = {};
|
|
109
|
+
|
|
110
|
+
if (!isStackPattern(values.stack)) {
|
|
111
|
+
errors.stack = 'Only dot(.) and underscore(_) special characters are allowed in the Stack field.';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!isDetailPattern(values.freeFormDetails)) {
|
|
115
|
+
errors.freeFormDetails =
|
|
116
|
+
'Only dot(.), underscore(_), caret (^), tilde (~), and dash(-) special characters are allowed in the Detail field.';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!values.viewState.disableImageSelection) {
|
|
120
|
+
if (!values.imageId) {
|
|
121
|
+
errors.imageId = 'Image is required.';
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// this error is added exclusively to disable the "create/clone" button - it is not visible aside from the warning
|
|
126
|
+
// rendered by the DeployingIntoManagedClusterWarning component
|
|
127
|
+
if (values.resourceSummary) {
|
|
128
|
+
errors.resourceSummary = { id: 'Cluster is managed' };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return errors;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private navigateToLatestServerGroup = () => {
|
|
135
|
+
const { values } = this.props.formik;
|
|
136
|
+
const { latestServerGroup } = this.state;
|
|
137
|
+
|
|
138
|
+
const params = {
|
|
139
|
+
provider: values.selectedProvider,
|
|
140
|
+
accountId: latestServerGroup.account,
|
|
141
|
+
region: latestServerGroup.region,
|
|
142
|
+
serverGroup: latestServerGroup.name,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const { $state } = ReactInjector;
|
|
146
|
+
if ($state.is('home.applications.application.insight.clusters')) {
|
|
147
|
+
$state.go('.serverGroup', params);
|
|
148
|
+
} else {
|
|
149
|
+
$state.go('^.serverGroup', params);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
private stackChanged = (stack: string) => {
|
|
154
|
+
const { formik } = this.props;
|
|
155
|
+
formik.setFieldValue('stack', stack);
|
|
156
|
+
formik.values.clusterChanged(formik.values);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
public componentWillReceiveProps(nextProps: IServerGroupBasicSettingsProps) {
|
|
160
|
+
this.setState(this.getStateFromProps(nextProps));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private strategyChanged = (values: ITitusServerGroupCommand, strategy: any) => {
|
|
164
|
+
values.onStrategyChange(values, strategy);
|
|
165
|
+
this.props.formik.setFieldValue('strategy', strategy.key);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
private dockerValuesChanged = (dockerValues: any) => {
|
|
169
|
+
Object.keys(dockerValues).forEach((key) => {
|
|
170
|
+
this.props.formik.setFieldValue(key, dockerValues[key]);
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
private onStrategyFieldChange = (key: string, value: any) => {
|
|
175
|
+
this.props.formik.setFieldValue(key, value);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
private onSubnetChange = () => {
|
|
179
|
+
const { setFieldValue, values } = this.props.formik;
|
|
180
|
+
values.subnetChanged(values);
|
|
181
|
+
setFieldValue('subnetType', values.subnetType);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
public render() {
|
|
185
|
+
const { app, formik } = this.props;
|
|
186
|
+
const { errors, setFieldValue, values } = formik;
|
|
187
|
+
const { createsNewCluster, latestServerGroup, namePreview } = this.state;
|
|
188
|
+
|
|
189
|
+
const accounts = values.backingData.accounts;
|
|
190
|
+
const readOnlyFields = values.viewState.readOnlyFields || {};
|
|
191
|
+
|
|
192
|
+
const customImage = values.imageId && values.imageId !== '${trigger.properties.imageName}';
|
|
193
|
+
|
|
194
|
+
const defaultSubnetTypes = []
|
|
195
|
+
.concat(TitusProviderSettings.defaults?.subnetType)
|
|
196
|
+
.concat(AWSProviderSettings.defaults?.subnetType)
|
|
197
|
+
.filter((x) => !!x);
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div className="container-fluid form-horizontal">
|
|
201
|
+
<DeployingIntoManagedClusterWarning app={app} formik={formik} />
|
|
202
|
+
<div className="form-group">
|
|
203
|
+
<div className="col-md-3 sm-label-right">Account</div>
|
|
204
|
+
<div className="col-md-7">
|
|
205
|
+
<AccountSelectInput
|
|
206
|
+
value={values.credentials}
|
|
207
|
+
onChange={(evt: any) => this.accountUpdated(evt.target.value)}
|
|
208
|
+
readOnly={readOnlyFields.credentials}
|
|
209
|
+
accounts={accounts}
|
|
210
|
+
provider="titus"
|
|
211
|
+
/>
|
|
212
|
+
{values.credentials !== undefined && (
|
|
213
|
+
<div className="small">
|
|
214
|
+
Uses resources from the Amazon account{' '}
|
|
215
|
+
<AccountTag
|
|
216
|
+
account={
|
|
217
|
+
values.backingData.credentialsKeyedByAccount[values.credentials] &&
|
|
218
|
+
values.backingData.credentialsKeyedByAccount[values.credentials].awsAccount
|
|
219
|
+
}
|
|
220
|
+
/>
|
|
221
|
+
</div>
|
|
222
|
+
)}
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
<RegionSelectField
|
|
226
|
+
readOnly={readOnlyFields.region}
|
|
227
|
+
labelColumns={3}
|
|
228
|
+
component={values}
|
|
229
|
+
field="region"
|
|
230
|
+
account={values.credentials}
|
|
231
|
+
regions={values.backingData.filtered.regions}
|
|
232
|
+
onChange={this.regionUpdated}
|
|
233
|
+
/>
|
|
234
|
+
<SubnetSelectField
|
|
235
|
+
application={app}
|
|
236
|
+
component={values}
|
|
237
|
+
field="subnetType"
|
|
238
|
+
helpKey="titus.serverGroup.subnet"
|
|
239
|
+
labelColumns={3}
|
|
240
|
+
onChange={this.onSubnetChange}
|
|
241
|
+
region={values.region}
|
|
242
|
+
subnets={values.backingData.filtered.subnetPurposes}
|
|
243
|
+
defaultSubnetTypes={defaultSubnetTypes}
|
|
244
|
+
recommendedSubnetTypes={TitusProviderSettings.serverGroups?.recommendedSubnets}
|
|
245
|
+
showSubnetWarning={true}
|
|
246
|
+
/>
|
|
247
|
+
<div className="form-group">
|
|
248
|
+
<div className="col-md-3 sm-label-right">
|
|
249
|
+
Stack <HelpField id="aws.serverGroup.stack" />
|
|
250
|
+
</div>
|
|
251
|
+
<div className="col-md-7">
|
|
252
|
+
<input
|
|
253
|
+
type="text"
|
|
254
|
+
className="form-control input-sm no-spel"
|
|
255
|
+
value={values.stack || ''}
|
|
256
|
+
onChange={(e) => this.stackChanged(e.target.value)}
|
|
257
|
+
/>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
{errors.stack && (
|
|
261
|
+
<div className="form-group row slide-in">
|
|
262
|
+
<div className="col-sm-9 col-sm-offset-2 error-message">
|
|
263
|
+
<span>{errors.stack}</span>
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
)}
|
|
267
|
+
|
|
268
|
+
<ServerGroupDetailsField app={app} formik={formik} />
|
|
269
|
+
|
|
270
|
+
{!values.viewState.disableImageSelection && (
|
|
271
|
+
<DockerImageAndTagSelector
|
|
272
|
+
specifyTagByRegex={false}
|
|
273
|
+
account={values.credentials}
|
|
274
|
+
digest={values.digest}
|
|
275
|
+
imageId={values.imageId}
|
|
276
|
+
organization={values.organization}
|
|
277
|
+
registry={values.registry}
|
|
278
|
+
repository={values.repository}
|
|
279
|
+
tag={values.tag}
|
|
280
|
+
showRegistry={false}
|
|
281
|
+
deferInitialization={values.deferredInitialization}
|
|
282
|
+
onChange={this.dockerValuesChanged}
|
|
283
|
+
/>
|
|
284
|
+
)}
|
|
285
|
+
{values.viewState.disableImageSelection && customImage && (
|
|
286
|
+
<div className="form-group">
|
|
287
|
+
<div className="col-md-3 sm-label-right">
|
|
288
|
+
<b>Image</b> <HelpField id="titus.deploy.imageId" />
|
|
289
|
+
</div>
|
|
290
|
+
<div className="col-md-7 sp-padding-xs-yaxis">{values.imageId}</div>
|
|
291
|
+
</div>
|
|
292
|
+
)}
|
|
293
|
+
<div className="form-group">
|
|
294
|
+
<div className="col-md-3 sm-label-right">
|
|
295
|
+
<b>Entrypoint</b>
|
|
296
|
+
</div>
|
|
297
|
+
<div className="col-md-7">
|
|
298
|
+
<Field type="text" className="form-control input-sm no-spel" name="entryPoint" />
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<div className="form-group">
|
|
303
|
+
<div className="col-md-3 sm-label-right">
|
|
304
|
+
Traffic <HelpField id="titus.serverGroup.traffic" />
|
|
305
|
+
</div>
|
|
306
|
+
<div className="col-md-7">
|
|
307
|
+
<div className="checkbox">
|
|
308
|
+
<label>
|
|
309
|
+
<input
|
|
310
|
+
type="checkbox"
|
|
311
|
+
checked={values.inService}
|
|
312
|
+
onChange={(e) => setFieldValue('inService', e.target.checked)}
|
|
313
|
+
disabled={values.strategy !== '' && values.strategy !== 'custom'}
|
|
314
|
+
/>{' '}
|
|
315
|
+
Send client requests to new instances
|
|
316
|
+
</label>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
{!values.viewState.disableStrategySelection && values.selectedProvider && (
|
|
321
|
+
<DeploymentStrategySelector
|
|
322
|
+
command={values}
|
|
323
|
+
onFieldChange={this.onStrategyFieldChange}
|
|
324
|
+
onStrategyChange={this.strategyChanged}
|
|
325
|
+
/>
|
|
326
|
+
)}
|
|
327
|
+
{!values.viewState.hideClusterNamePreview && (
|
|
328
|
+
<ServerGroupNamePreview
|
|
329
|
+
createsNewCluster={createsNewCluster}
|
|
330
|
+
latestServerGroupName={latestServerGroup?.name}
|
|
331
|
+
mode={values.viewState.mode}
|
|
332
|
+
namePreview={namePreview}
|
|
333
|
+
navigateToLatestServerGroup={this.navigateToLatestServerGroup}
|
|
334
|
+
/>
|
|
335
|
+
)}
|
|
336
|
+
</div>
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import type { FormikProps } from 'formik';
|
|
2
|
+
import { intersection, set, union } from 'lodash';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import type { Application, IFormInputProps, IWizardPageComponent } from '@spinnaker/core';
|
|
6
|
+
import {
|
|
7
|
+
AccountTag,
|
|
8
|
+
CheckboxInput,
|
|
9
|
+
ChecklistInput,
|
|
10
|
+
FormikFormField,
|
|
11
|
+
FormValidator,
|
|
12
|
+
HelpField,
|
|
13
|
+
LayoutProvider,
|
|
14
|
+
MapEditorInput,
|
|
15
|
+
PlatformHealthOverrideInput,
|
|
16
|
+
robotToHuman,
|
|
17
|
+
SelectInput,
|
|
18
|
+
TextInput,
|
|
19
|
+
useFormInputValueMapper,
|
|
20
|
+
} from '@spinnaker/core';
|
|
21
|
+
|
|
22
|
+
import { TitusMapLayout } from './TitusMapLayout';
|
|
23
|
+
import type { ITitusServerGroupCommand } from '../../../configure/serverGroupConfiguration.service';
|
|
24
|
+
import { processesList } from '../../../details/serviceJobProcesses/ServiceJobProcesses';
|
|
25
|
+
|
|
26
|
+
import './ServerGroupParameters.less';
|
|
27
|
+
|
|
28
|
+
export interface IServerGroupParametersProps {
|
|
29
|
+
app: Application;
|
|
30
|
+
formik: FormikProps<ITitusServerGroupCommand>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const migrationPolicyOptions = [
|
|
34
|
+
{ label: 'System Default', value: 'systemDefault' },
|
|
35
|
+
{ label: 'Self Managed', value: 'selfManaged' },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
function ServiceJobProcessesInput(props: IFormInputProps) {
|
|
39
|
+
const allProcesses = union(processesList, Object.keys(props.value));
|
|
40
|
+
// Map to a list of strings (formik -> input)
|
|
41
|
+
const mapToInputValue = (value: Record<string, boolean>) =>
|
|
42
|
+
Object.entries(value)
|
|
43
|
+
.filter(([_key, val]) => val === true)
|
|
44
|
+
.map(([key, _val]) => key);
|
|
45
|
+
|
|
46
|
+
// Map to an Object, but include all known processes (input -> formik)
|
|
47
|
+
const mapFromInputValue = (value: string[]): Record<string, boolean> =>
|
|
48
|
+
allProcesses.reduce((acc, process) => {
|
|
49
|
+
acc[process] = value.includes(process);
|
|
50
|
+
return acc;
|
|
51
|
+
}, {} as Record<string, boolean>);
|
|
52
|
+
|
|
53
|
+
const mappedProps = useFormInputValueMapper(props, mapToInputValue, mapFromInputValue);
|
|
54
|
+
|
|
55
|
+
const options = allProcesses.map((process) => {
|
|
56
|
+
return { label: robotToHuman(process), value: process };
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return <ChecklistInput {...mappedProps} options={options} />;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function IPv6CheckboxInput(props: IFormInputProps) {
|
|
63
|
+
const mappedProps = useFormInputValueMapper(
|
|
64
|
+
props,
|
|
65
|
+
(val: string) => val === 'true', // formik -> checkbox
|
|
66
|
+
(_val, e) => (e.target.checked ? 'true' : 'false'), // checkbox -> formik
|
|
67
|
+
);
|
|
68
|
+
return <CheckboxInput {...mappedProps} />;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const IamInstanceProfileInput = (props: IFormInputProps & { awsAccount: string; setDefaultIamProfile: () => void }) => {
|
|
72
|
+
const { awsAccount, setDefaultIamProfile, ...inputProps } = props;
|
|
73
|
+
return (
|
|
74
|
+
<div className="flex-container-h baseline margin-between-md">
|
|
75
|
+
<TextInput {...inputProps} />
|
|
76
|
+
{props.value ? (
|
|
77
|
+
<>
|
|
78
|
+
<span>in</span>
|
|
79
|
+
<AccountTag account={awsAccount} />
|
|
80
|
+
</>
|
|
81
|
+
) : (
|
|
82
|
+
<button className="link" style={{ whiteSpace: 'nowrap' }} onClick={setDefaultIamProfile}>
|
|
83
|
+
Apply default value
|
|
84
|
+
</button>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export class ServerGroupParameters
|
|
91
|
+
extends React.Component<IServerGroupParametersProps>
|
|
92
|
+
implements IWizardPageComponent<ITitusServerGroupCommand> {
|
|
93
|
+
constructor(props: IServerGroupParametersProps) {
|
|
94
|
+
super(props);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public validate(_values: ITitusServerGroupCommand) {
|
|
98
|
+
const validator = new FormValidator(_values);
|
|
99
|
+
validator.field('iamProfile', 'IAM Instance Profile').required();
|
|
100
|
+
|
|
101
|
+
const errors = validator.validateForm();
|
|
102
|
+
|
|
103
|
+
const duplicates = intersection(Object.keys(_values.constraints.soft), Object.keys(_values.constraints.hard));
|
|
104
|
+
duplicates.forEach((key) => {
|
|
105
|
+
set(errors, `constraints.soft.${key}`, `Constraint '${key}' must be either soft or hard, not both.`);
|
|
106
|
+
set(errors, `constraints.hard.${key}`, `Constraint '${key}' must be either soft or hard, not both.`);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
Object.keys(_values.env || {})
|
|
110
|
+
.filter((key) => !key.startsWith('__MapEditorDuplicateKey'))
|
|
111
|
+
.forEach((key) => {
|
|
112
|
+
if (!key.match(/^[A-Za-z_].*/)) {
|
|
113
|
+
set(errors, `env.${key}`, 'Environment variable names must start with a letter or underscore');
|
|
114
|
+
} else if (!key.match(/[A-Za-z_][a-zA-Z0-9_]*$/)) {
|
|
115
|
+
set(errors, `env.${key}`, 'Environment variable names must contain only letter, numbers, or underscores');
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return errors;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public render() {
|
|
123
|
+
const { app } = this.props;
|
|
124
|
+
const { setFieldValue, values } = this.props.formik;
|
|
125
|
+
|
|
126
|
+
const setDefaultIamProfile = () => setFieldValue('iamProfile', values.viewState.defaultIamProfile);
|
|
127
|
+
return (
|
|
128
|
+
<div className="ServerGroupParameters">
|
|
129
|
+
<FormikFormField
|
|
130
|
+
name="iamProfile"
|
|
131
|
+
label="IAM Instance Profile"
|
|
132
|
+
help={<HelpField id="titus.deploy.iamProfile" />}
|
|
133
|
+
input={(props) => (
|
|
134
|
+
<IamInstanceProfileInput
|
|
135
|
+
{...props}
|
|
136
|
+
awsAccount={values.backingData.credentialsKeyedByAccount[values.credentials]?.awsAccount}
|
|
137
|
+
setDefaultIamProfile={setDefaultIamProfile}
|
|
138
|
+
/>
|
|
139
|
+
)}
|
|
140
|
+
/>
|
|
141
|
+
|
|
142
|
+
<FormikFormField
|
|
143
|
+
name="capacityGroup"
|
|
144
|
+
label="Capacity Group"
|
|
145
|
+
help={<HelpField id="titus.deploy.capacityGroup" />}
|
|
146
|
+
input={(props) => <TextInput {...props} />}
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
<FormikFormField
|
|
150
|
+
name="migrationPolicy.type"
|
|
151
|
+
label="Migration Policy"
|
|
152
|
+
help={<HelpField id="titus.deploy.migrationPolicy" />}
|
|
153
|
+
input={(props) => <SelectInput options={migrationPolicyOptions} {...props} />}
|
|
154
|
+
/>
|
|
155
|
+
|
|
156
|
+
<FormikFormField
|
|
157
|
+
name="serviceJobProcesses"
|
|
158
|
+
label="Service Job Processes"
|
|
159
|
+
input={(props) => <ServiceJobProcessesInput {...props} />}
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
<FormikFormField
|
|
163
|
+
name="containerAttributes['titusParameter.agent.assignIPv6Address']"
|
|
164
|
+
label="Associate IPv6 Address (Recommended)"
|
|
165
|
+
help={<HelpField id="serverGroup.ipv6" />}
|
|
166
|
+
input={(props) => <IPv6CheckboxInput {...props} />}
|
|
167
|
+
/>
|
|
168
|
+
|
|
169
|
+
<hr />
|
|
170
|
+
|
|
171
|
+
<LayoutProvider value={TitusMapLayout}>
|
|
172
|
+
<FormikFormField
|
|
173
|
+
name="constraints.soft"
|
|
174
|
+
label="Soft Constraints "
|
|
175
|
+
help={<HelpField id="titus.deploy.softConstraints" />}
|
|
176
|
+
input={(props) => <MapEditorInput allowEmptyValues={true} {...props} />}
|
|
177
|
+
/>
|
|
178
|
+
|
|
179
|
+
<FormikFormField
|
|
180
|
+
name="constraints.hard"
|
|
181
|
+
label="Hard Constraints"
|
|
182
|
+
help={<HelpField id="titus.deploy.hardConstraints" />}
|
|
183
|
+
input={(props) => <MapEditorInput allowEmptyValues={true} {...props} />}
|
|
184
|
+
/>
|
|
185
|
+
|
|
186
|
+
<hr />
|
|
187
|
+
|
|
188
|
+
<FormikFormField
|
|
189
|
+
name="labels"
|
|
190
|
+
label="Job Attributes"
|
|
191
|
+
input={(props) => <MapEditorInput allowEmptyValues={true} {...props} />}
|
|
192
|
+
/>
|
|
193
|
+
|
|
194
|
+
<FormikFormField
|
|
195
|
+
name="containerAttributes"
|
|
196
|
+
label="Container Attributes"
|
|
197
|
+
input={(props) => <MapEditorInput allowEmptyValues={true} {...props} />}
|
|
198
|
+
/>
|
|
199
|
+
|
|
200
|
+
<FormikFormField
|
|
201
|
+
name="env"
|
|
202
|
+
label="Environment Variables"
|
|
203
|
+
input={(props) => <MapEditorInput allowEmptyValues={true} {...props} />}
|
|
204
|
+
/>
|
|
205
|
+
</LayoutProvider>
|
|
206
|
+
|
|
207
|
+
{app.attributes.platformHealthOnlyShowOverride && (
|
|
208
|
+
<FormikFormField
|
|
209
|
+
name="interestingHealthProviderNames"
|
|
210
|
+
label="Task Completion"
|
|
211
|
+
input={(props) => <PlatformHealthOverrideInput {...props} platformHealthType="Titus" />}
|
|
212
|
+
/>
|
|
213
|
+
)}
|
|
214
|
+
</div>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
}
|