@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.
Files changed (185) hide show
  1. package/CHANGELOG.md +2661 -0
  2. package/LICENSE.txt +203 -0
  3. package/dist/domain/IJobDisruptionBudget.d.ts +35 -0
  4. package/dist/domain/ITitusCredentials.d.ts +5 -0
  5. package/dist/domain/ITitusInstance.d.ts +28 -0
  6. package/dist/domain/ITitusScalingPolicy.d.ts +4 -0
  7. package/dist/domain/ITitusServerGroup.d.ts +52 -0
  8. package/dist/domain/ITitusServiceJobProcesses.d.ts +3 -0
  9. package/dist/domain/index.d.ts +5 -0
  10. package/dist/help/titus.help.d.ts +1 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.js +12828 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/instance/details/TitusInstanceDetails.d.ts +25 -0
  15. package/dist/instance/details/TitusInstanceDns.d.ts +8 -0
  16. package/dist/instance/details/TitusInstanceInformation.d.ts +7 -0
  17. package/dist/instance/details/index.d.ts +4 -0
  18. package/dist/instance/details/titusInstanceDetailsUtils.d.ts +14 -0
  19. package/dist/pipeline/stages/cloneServerGroup/cloneServerGroupExecutionDetails.controller.d.ts +2 -0
  20. package/dist/pipeline/stages/cloneServerGroup/titusCloneServerGroupStage.d.ts +2 -0
  21. package/dist/pipeline/stages/destroyAsg/titusDestroyAsgStage.d.ts +2 -0
  22. package/dist/pipeline/stages/disableAsg/titusDisableAsgStage.d.ts +2 -0
  23. package/dist/pipeline/stages/disableCluster/titusDisableClusterStage.d.ts +2 -0
  24. package/dist/pipeline/stages/enableAsg/titusEnableAsgStage.d.ts +2 -0
  25. package/dist/pipeline/stages/findAmi/titusFindAmiStage.d.ts +2 -0
  26. package/dist/pipeline/stages/resizeAsg/titusResizeAsgStage.d.ts +2 -0
  27. package/dist/pipeline/stages/runJob/RunJobExecutionDetails.d.ts +16 -0
  28. package/dist/pipeline/stages/runJob/TitusRunJobStageConfig.d.ts +25 -0
  29. package/dist/pipeline/stages/runJob/TitusSecurityGroupPicker.d.ts +34 -0
  30. package/dist/pipeline/stages/runJob/titusRunJobStage.d.ts +1 -0
  31. package/dist/pipeline/stages/scaleDownCluster/titusScaleDownClusterStage.d.ts +2 -0
  32. package/dist/pipeline/stages/shrinkCluster/titusShrinkClusterStage.d.ts +2 -0
  33. package/dist/reactShims/index.d.ts +1 -0
  34. package/dist/reactShims/titus.react.injector.d.ts +11 -0
  35. package/dist/reactShims/titus.react.module.d.ts +1 -0
  36. package/dist/securityGroup/securityGroup.read.service.d.ts +2 -0
  37. package/dist/serverGroup/configure/ServerGroupCommandBuilder.d.ts +2 -0
  38. package/dist/serverGroup/configure/serverGroup.configure.titus.module.d.ts +2 -0
  39. package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +89 -0
  40. package/dist/serverGroup/configure/wizard/TitusCloneServerGroupModal.d.ts +31 -0
  41. package/dist/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.d.ts +28 -0
  42. package/dist/serverGroup/configure/wizard/pages/ServerGroupParameters.d.ts +15 -0
  43. package/dist/serverGroup/configure/wizard/pages/ServerGroupResources.d.ts +11 -0
  44. package/dist/serverGroup/configure/wizard/pages/TitusMapLayout.d.ts +4 -0
  45. package/dist/serverGroup/configure/wizard/pages/disruptionBudget/JobDisruptionBudget.d.ts +40 -0
  46. package/dist/serverGroup/configure/wizard/pages/disruptionBudget/PolicyOptions.d.ts +2 -0
  47. package/dist/serverGroup/configure/wizard/pages/disruptionBudget/RateOptions.d.ts +2 -0
  48. package/dist/serverGroup/configure/wizard/pages/disruptionBudget/WindowPicker.d.ts +23 -0
  49. package/dist/serverGroup/configure/wizard/pages/index.d.ts +4 -0
  50. package/dist/serverGroup/details/TitusCapacityDetailsSection.d.ts +11 -0
  51. package/dist/serverGroup/details/TitusLaunchConfigSection.d.ts +9 -0
  52. package/dist/serverGroup/details/TitusPackageDetailsSection.d.ts +6 -0
  53. package/dist/serverGroup/details/TitusSecurityGroups.d.ts +17 -0
  54. package/dist/serverGroup/details/capacityDetailsSection.component.d.ts +1 -0
  55. package/dist/serverGroup/details/disruptionBudget/DisruptionBudgetSection.d.ts +19 -0
  56. package/dist/serverGroup/details/disruptionBudget/EditDisruptionBudgetModal.d.ts +14 -0
  57. package/dist/serverGroup/details/index.d.ts +5 -0
  58. package/dist/serverGroup/details/launchConfigSection.component.d.ts +1 -0
  59. package/dist/serverGroup/details/resize/TitusResizeServerGroupModal.d.ts +8 -0
  60. package/dist/serverGroup/details/resize/useTaskMonitor.d.ts +25 -0
  61. package/dist/serverGroup/details/rollback/rollbackServerGroup.controller.d.ts +2 -0
  62. package/dist/serverGroup/details/scalingActivity/TitusScalingActivitiesModal.d.ts +7 -0
  63. package/dist/serverGroup/details/scalingPolicy/CreateScalingPolicyButton.d.ts +21 -0
  64. package/dist/serverGroup/details/scalingPolicy/TitusCustomScalingPolicy.d.ts +7 -0
  65. package/dist/serverGroup/details/scalingPolicy/createScalingPolicyButton.component.d.ts +1 -0
  66. package/dist/serverGroup/details/scalingPolicy/index.d.ts +3 -0
  67. package/dist/serverGroup/details/scalingPolicy/scalingPolicy.module.d.ts +1 -0
  68. package/dist/serverGroup/details/scalingPolicy/targetTracking/TitusTargetTrackingChart.d.ts +9 -0
  69. package/dist/serverGroup/details/scalingPolicy/targetTracking/UpsertTargetTrackingModal.d.ts +10 -0
  70. package/dist/serverGroup/details/scalingPolicy/titusCustomScalingPolicy.component.d.ts +1 -0
  71. package/dist/serverGroup/details/scalingPolicy/upsert/TitusScalingPolicyCommandBuilderService.d.ts +10 -0
  72. package/dist/serverGroup/details/scalingPolicy/upsert/UpsertScalingPolicyModal.d.ts +10 -0
  73. package/dist/serverGroup/details/sections/ITitusServerGroupDetailsSectionProps.d.ts +5 -0
  74. package/dist/serverGroup/details/serverGroupDetails.titus.controller.d.ts +2 -0
  75. package/dist/serverGroup/details/serviceJobProcesses/ServiceJobProcesses.d.ts +3 -0
  76. package/dist/serverGroup/details/serviceJobProcesses/ServiceJobProcessesSection.d.ts +7 -0
  77. package/dist/serverGroup/details/titusPackageDetailsSection.component.d.ts +1 -0
  78. package/dist/serverGroup/details/titusSecurityGroups.component.d.ts +1 -0
  79. package/dist/serverGroup/serverGroup.transformer.d.ts +2 -0
  80. package/dist/titus.module.d.ts +5 -0
  81. package/dist/titus.settings.d.ts +14 -0
  82. package/dist/validation/ApplicationNameValidator.d.ts +1 -0
  83. package/package.json +52 -0
  84. package/src/domain/IJobDisruptionBudget.ts +19 -0
  85. package/src/domain/ITitusCredentials.ts +6 -0
  86. package/src/domain/ITitusInstance.ts +30 -0
  87. package/src/domain/ITitusScalingPolicy.ts +5 -0
  88. package/src/domain/ITitusServerGroup.ts +56 -0
  89. package/src/domain/ITitusServiceJobProcesses.ts +3 -0
  90. package/src/domain/index.ts +5 -0
  91. package/src/help/titus.help.ts +99 -0
  92. package/src/index.ts +6 -0
  93. package/src/instance/details/TitusInstanceDetails.tsx +234 -0
  94. package/src/instance/details/TitusInstanceDns.tsx +40 -0
  95. package/src/instance/details/TitusInstanceInformation.tsx +42 -0
  96. package/src/instance/details/index.ts +4 -0
  97. package/src/instance/details/titusInstanceDetailsUtils.spec.ts +124 -0
  98. package/src/instance/details/titusInstanceDetailsUtils.ts +181 -0
  99. package/src/logo/titus.logo.less +5 -0
  100. package/src/logo/titus.logo.png +0 -0
  101. package/src/logo/titus.logo.svg +7 -0
  102. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupExecutionDetails.controller.js +66 -0
  103. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupExecutionDetails.html +46 -0
  104. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStage.html +106 -0
  105. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStepLabel.html +1 -0
  106. package/src/pipeline/stages/cloneServerGroup/titusCloneServerGroupStage.js +104 -0
  107. package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +9 -0
  108. package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +1 -0
  109. package/src/pipeline/stages/destroyAsg/titusDestroyAsgStage.js +65 -0
  110. package/src/pipeline/stages/disableAsg/disableAsgStage.html +11 -0
  111. package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +1 -0
  112. package/src/pipeline/stages/disableAsg/titusDisableAsgStage.js +69 -0
  113. package/src/pipeline/stages/disableCluster/disableClusterStage.html +26 -0
  114. package/src/pipeline/stages/disableCluster/titusDisableClusterStage.js +85 -0
  115. package/src/pipeline/stages/enableAsg/enableAsgStage.html +11 -0
  116. package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +1 -0
  117. package/src/pipeline/stages/enableAsg/titusEnableAsgStage.js +73 -0
  118. package/src/pipeline/stages/findAmi/findAmiStage.html +24 -0
  119. package/src/pipeline/stages/findAmi/titusFindAmiStage.js +79 -0
  120. package/src/pipeline/stages/resizeAsg/resizeAsgStage.html +99 -0
  121. package/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html +1 -0
  122. package/src/pipeline/stages/resizeAsg/titusResizeAsgStage.js +125 -0
  123. package/src/pipeline/stages/runJob/RunJobExecutionDetails.tsx +165 -0
  124. package/src/pipeline/stages/runJob/TitusRunJobStageConfig.tsx +466 -0
  125. package/src/pipeline/stages/runJob/TitusSecurityGroupPicker.tsx +170 -0
  126. package/src/pipeline/stages/runJob/titusRunJobStage.ts +30 -0
  127. package/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html +35 -0
  128. package/src/pipeline/stages/scaleDownCluster/titusScaleDownClusterStage.js +79 -0
  129. package/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html +34 -0
  130. package/src/pipeline/stages/shrinkCluster/titusShrinkClusterStage.js +73 -0
  131. package/src/reactShims/index.ts +1 -0
  132. package/src/reactShims/titus.react.injector.ts +17 -0
  133. package/src/reactShims/titus.react.module.ts +10 -0
  134. package/src/securityGroup/securityGroup.read.service.js +15 -0
  135. package/src/serverGroup/configure/ServerGroupCommandBuilder.js +247 -0
  136. package/src/serverGroup/configure/serverGroup.configure.titus.module.js +9 -0
  137. package/src/serverGroup/configure/serverGroupCommandBuilder.spec.js +63 -0
  138. package/src/serverGroup/configure/serverGroupConfiguration.service.ts +410 -0
  139. package/src/serverGroup/configure/wizard/TitusCloneServerGroupModal.tsx +293 -0
  140. package/src/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.tsx +339 -0
  141. package/src/serverGroup/configure/wizard/pages/ServerGroupParameters.less +5 -0
  142. package/src/serverGroup/configure/wizard/pages/ServerGroupParameters.tsx +217 -0
  143. package/src/serverGroup/configure/wizard/pages/ServerGroupResources.tsx +200 -0
  144. package/src/serverGroup/configure/wizard/pages/TitusMapLayout.less +3 -0
  145. package/src/serverGroup/configure/wizard/pages/TitusMapLayout.tsx +29 -0
  146. package/src/serverGroup/configure/wizard/pages/disruptionBudget/JobDisruptionBudget.tsx +285 -0
  147. package/src/serverGroup/configure/wizard/pages/disruptionBudget/PolicyOptions.tsx +112 -0
  148. package/src/serverGroup/configure/wizard/pages/disruptionBudget/RateOptions.tsx +89 -0
  149. package/src/serverGroup/configure/wizard/pages/disruptionBudget/WindowPicker.tsx +202 -0
  150. package/src/serverGroup/configure/wizard/pages/index.ts +4 -0
  151. package/src/serverGroup/details/TitusCapacityDetailsSection.tsx +66 -0
  152. package/src/serverGroup/details/TitusLaunchConfigSection.tsx +35 -0
  153. package/src/serverGroup/details/TitusPackageDetailsSection.tsx +40 -0
  154. package/src/serverGroup/details/TitusSecurityGroups.tsx +107 -0
  155. package/src/serverGroup/details/capacityDetailsSection.component.ts +12 -0
  156. package/src/serverGroup/details/disruptionBudget/DisruptionBudgetSection.tsx +226 -0
  157. package/src/serverGroup/details/disruptionBudget/EditDisruptionBudgetModal.tsx +92 -0
  158. package/src/serverGroup/details/index.ts +5 -0
  159. package/src/serverGroup/details/launchConfigSection.component.ts +12 -0
  160. package/src/serverGroup/details/resize/TitusResizeServerGroupModal.tsx +302 -0
  161. package/src/serverGroup/details/resize/useTaskMonitor.ts +30 -0
  162. package/src/serverGroup/details/rollback/rollbackServerGroup.controller.js +149 -0
  163. package/src/serverGroup/details/rollback/rollbackServerGroup.html +133 -0
  164. package/src/serverGroup/details/scalingActivity/TitusScalingActivitiesModal.tsx +81 -0
  165. package/src/serverGroup/details/scalingPolicy/CreateScalingPolicyButton.tsx +102 -0
  166. package/src/serverGroup/details/scalingPolicy/TitusCustomScalingPolicy.tsx +13 -0
  167. package/src/serverGroup/details/scalingPolicy/createScalingPolicyButton.component.ts +15 -0
  168. package/src/serverGroup/details/scalingPolicy/index.js +3 -0
  169. package/src/serverGroup/details/scalingPolicy/scalingPolicy.module.ts +7 -0
  170. package/src/serverGroup/details/scalingPolicy/targetTracking/TitusTargetTrackingChart.tsx +57 -0
  171. package/src/serverGroup/details/scalingPolicy/targetTracking/UpsertTargetTrackingModal.tsx +82 -0
  172. package/src/serverGroup/details/scalingPolicy/titusCustomScalingPolicy.component.ts +17 -0
  173. package/src/serverGroup/details/scalingPolicy/upsert/TitusScalingPolicyCommandBuilderService.ts +115 -0
  174. package/src/serverGroup/details/scalingPolicy/upsert/UpsertScalingPolicyModal.tsx +157 -0
  175. package/src/serverGroup/details/sections/ITitusServerGroupDetailsSectionProps.ts +6 -0
  176. package/src/serverGroup/details/serverGroupDetails.html +191 -0
  177. package/src/serverGroup/details/serverGroupDetails.titus.controller.js +457 -0
  178. package/src/serverGroup/details/serviceJobProcesses/ServiceJobProcesses.ts +12 -0
  179. package/src/serverGroup/details/serviceJobProcesses/ServiceJobProcessesSection.tsx +136 -0
  180. package/src/serverGroup/details/titusPackageDetailsSection.component.ts +12 -0
  181. package/src/serverGroup/details/titusSecurityGroups.component.ts +12 -0
  182. package/src/serverGroup/serverGroup.transformer.js +90 -0
  183. package/src/titus.module.ts +95 -0
  184. package/src/titus.settings.ts +22 -0
  185. package/src/validation/ApplicationNameValidator.ts +43 -0
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+
3
+ import { FormikFormField, HelpField, NumberInput } from '@spinnaker/core';
4
+
5
+ import type { IFieldOption, IFieldOptionComponentProps } from './JobDisruptionBudget';
6
+ import { defaultJobDisruptionBudget } from '../../../serverGroupConfiguration.service';
7
+
8
+ const RatePercentagePerInterval = (componentProps: IFieldOptionComponentProps) => (
9
+ <>
10
+ <FormikFormField
11
+ name="disruptionBudget.ratePercentagePerInterval.intervalMs"
12
+ label="Interval"
13
+ input={(props) => (
14
+ <div>
15
+ <NumberInput {...props} disabled={componentProps.isDisabled} />
16
+ <HelpField expand={true} content="(milliseconds)" />
17
+ </div>
18
+ )}
19
+ />
20
+ <FormikFormField
21
+ name="disruptionBudget.ratePercentagePerInterval.percentageLimitPerInterval"
22
+ label="Percentage Per Interval"
23
+ input={(props) => (
24
+ <div>
25
+ <NumberInput {...props} disabled={componentProps.isDisabled} />
26
+ <HelpField expand={true} content="0.0-100.0 (double)" />
27
+ </div>
28
+ )}
29
+ />
30
+ </>
31
+ );
32
+
33
+ const RatePerInterval = () => (
34
+ <>
35
+ <FormikFormField
36
+ name="disruptionBudget.ratePerInterval.intervalMs"
37
+ label="Interval"
38
+ input={(props) => (
39
+ <div>
40
+ <NumberInput {...props} />
41
+ <HelpField expand={true} content="(milliseconds)" />
42
+ </div>
43
+ )}
44
+ />
45
+ <FormikFormField
46
+ name="disruptionBudget.ratePerInterval.limitPerInterval"
47
+ label="Limit Per Interval"
48
+ input={(props) => (
49
+ <div>
50
+ <NumberInput {...props} />
51
+ <HelpField expand={true} content="(tasks)" />
52
+ </div>
53
+ )}
54
+ />
55
+ </>
56
+ );
57
+
58
+ export const rateOptions: IFieldOption[] = [
59
+ {
60
+ field: 'rateUnlimited',
61
+ label: 'Unlimited',
62
+ value: 0,
63
+ description: `
64
+ No limits on how many containers in a job may be relocated, provided the other disruption budget constraints
65
+ are not violated.
66
+ `,
67
+ defaultValues: true,
68
+ },
69
+ {
70
+ field: 'ratePercentagePerInterval',
71
+ label: 'Rate Percentage Per Interval',
72
+ value: 1,
73
+ description: `
74
+ Percentage of containers that can be relocated within a time interval.
75
+ `,
76
+ defaultValues: defaultJobDisruptionBudget.ratePercentagePerInterval,
77
+ fieldComponent: RatePercentagePerInterval,
78
+ },
79
+ {
80
+ field: 'ratePerInterval',
81
+ label: 'Rate Per Interval',
82
+ value: 2,
83
+ description: `
84
+ Limit number of relocations within a given time interval.
85
+ `,
86
+ defaultValues: { intervalMs: 60000, limitPerInterval: 2 },
87
+ fieldComponent: RatePerInterval,
88
+ },
89
+ ];
@@ -0,0 +1,202 @@
1
+ import type { FormikProps } from 'formik';
2
+ import { get } from 'lodash';
3
+ import React from 'react';
4
+
5
+ import { ChecklistInput, FormikFormField, HelpField, NumberInput, ReactSelectInput, SpinFormik } from '@spinnaker/core';
6
+ import type { IJobTimeWindow } from '../../../../../domain';
7
+
8
+ import type { ITitusServerGroupCommand } from '../../../serverGroupConfiguration.service';
9
+
10
+ export interface IWindowPickerProps {
11
+ formik: FormikProps<ITitusServerGroupCommand>;
12
+ isDisabled: boolean;
13
+ }
14
+
15
+ export interface IWindowPickerState {
16
+ addingNewWindow?: boolean;
17
+ }
18
+
19
+ const DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
20
+
21
+ interface IJobTimeWindowForm {
22
+ days: string[];
23
+ startHour: number;
24
+ endHour: number;
25
+ timeZone: string;
26
+ }
27
+
28
+ export class WindowPicker extends React.Component<IWindowPickerProps, IWindowPickerState> {
29
+ constructor(props: IWindowPickerProps) {
30
+ super(props);
31
+ this.state = {
32
+ addingNewWindow: false,
33
+ };
34
+ }
35
+
36
+ private removeWindow(index: number, subIndex: number) {
37
+ const { values, setFieldValue } = this.props.formik;
38
+ const { timeWindows } = values.disruptionBudget;
39
+ const toRemove = timeWindows[index];
40
+ if (toRemove.hourlyTimeWindows.length === 1) {
41
+ setFieldValue(
42
+ 'disruptionBudget.timeWindows',
43
+ timeWindows.filter((w) => w !== toRemove),
44
+ );
45
+ } else {
46
+ const subWindowToRemove = toRemove.hourlyTimeWindows[subIndex];
47
+ const newWindows = toRemove.hourlyTimeWindows.filter((w) => w !== subWindowToRemove);
48
+ setFieldValue(`disruptionBudget.timeWindows[${index}].hourlyTimeWindows`, newWindows);
49
+ }
50
+ }
51
+
52
+ /**
53
+ * The Budget API allows multiple hourly windows for a set of days; however, the UI is not really supportive of this,
54
+ * so we'll add them as a single window for a single set of days. It's fine!
55
+ */
56
+ private configureNewWindow = () => {
57
+ this.setState({ addingNewWindow: true });
58
+ };
59
+
60
+ private addNewWindow = (form: IJobTimeWindowForm) => {
61
+ const { values, setFieldValue } = this.props.formik;
62
+ const { days, startHour, endHour, timeZone } = form;
63
+ const newWindow: IJobTimeWindow = {
64
+ days,
65
+ hourlyTimeWindows: [{ startHour, endHour }],
66
+ timeZone,
67
+ };
68
+ setFieldValue('disruptionBudget.timeWindows', values.disruptionBudget.timeWindows.concat(newWindow));
69
+ this.setState({ addingNewWindow: false });
70
+ };
71
+
72
+ private CurrentWindows = () => {
73
+ const { disruptionBudget } = this.props.formik.values;
74
+ const { isDisabled } = this.props;
75
+ if (!disruptionBudget) {
76
+ return null;
77
+ }
78
+ const { timeWindows } = disruptionBudget;
79
+ return (
80
+ <div className="sp-formItem">
81
+ <div className="sp-formItem__left" />
82
+ <div className="sp-formItem__right">
83
+ {timeWindows.map((timeWindow, i) => {
84
+ return timeWindow.hourlyTimeWindows.map((w, i2) => (
85
+ <div
86
+ className="sp-margin-l-yaxis sp-margin-m-right"
87
+ style={{ display: 'inline-block' }}
88
+ key={`${i}.${i2}`}
89
+ >
90
+ <div
91
+ key={`${i}.${i2}`}
92
+ className="horizontal center top sp-padding-m-yaxis sp-padding-s-xaxis"
93
+ style={{ backgroundColor: 'var(--color-dovegray)', borderRadius: '4px' }}
94
+ >
95
+ <div className="sp-padding-m-right" style={{ color: 'var(--color-text-on-dark)', fontSize: '12px' }}>
96
+ <div>
97
+ <b>{timeWindow.days.map((d) => d.substr(0, 3)).join(', ')}</b>
98
+ </div>
99
+ <div>
100
+ <em>
101
+ {w.startHour}:00 - {w.endHour}:00 {timeWindow.timeZone}
102
+ </em>
103
+ </div>
104
+ </div>
105
+ {!isDisabled && (
106
+ <a
107
+ className="clickable"
108
+ style={{ color: 'var(--color-text-on-dark)' }}
109
+ onClick={() => this.removeWindow(i, i2)}
110
+ >
111
+ <span className="glyphicon glyphicon-remove" />
112
+ </a>
113
+ )}
114
+ </div>
115
+ </div>
116
+ ));
117
+ })}
118
+ </div>
119
+ </div>
120
+ );
121
+ };
122
+
123
+ private NewWindowComponent = () => {
124
+ if (!this.state.addingNewWindow) {
125
+ return (
126
+ <div className="sp-formItem">
127
+ <div className="sp-formItem__left" />
128
+ <div className="sp-formItem__right sp-margin-l-bottom">
129
+ <a className="button primary" onClick={this.configureNewWindow}>
130
+ <i className="fas fa-plus-circle" /> Define New Window
131
+ </a>
132
+ </div>
133
+ </div>
134
+ );
135
+ }
136
+ return (
137
+ <SpinFormik<IJobTimeWindowForm>
138
+ initialValues={{
139
+ days: [],
140
+ startHour: 10,
141
+ endHour: 16,
142
+ timeZone: get(this.props.formik.values.disruptionBudget, 'timeWindows[0].timeZone', 'PST'),
143
+ }}
144
+ onSubmit={this.addNewWindow}
145
+ render={(formik) => (
146
+ <>
147
+ <FormikFormField
148
+ name="days"
149
+ label="Define a New Window"
150
+ input={(props) => <ChecklistInput {...props} stringOptions={DAYS} />}
151
+ />
152
+ <FormikFormField
153
+ name="startHour"
154
+ label="Start"
155
+ input={(props) => (
156
+ <div>
157
+ <NumberInput {...props} min={0} max={formik.values.endHour} />
158
+ <HelpField expand={true} content="hour (0-24)" />
159
+ </div>
160
+ )}
161
+ />
162
+ <FormikFormField
163
+ name="endHour"
164
+ label="End"
165
+ input={(props) => (
166
+ <div>
167
+ <NumberInput {...props} min={formik.values.startHour} max={23} />
168
+ <HelpField expand={true} content="hour (0-24)" />
169
+ </div>
170
+ )}
171
+ />
172
+ <FormikFormField
173
+ name="timeZone"
174
+ label="Timezone"
175
+ input={(props) => <ReactSelectInput {...props} clearable={false} stringOptions={['PST', 'UTC']} />}
176
+ />
177
+ <div className="sp-formItem">
178
+ <div className="sp-formItem__left" />
179
+ <div className="sp-formItem__right sp-margin-l-bottom">
180
+ <button className="primary" type="submit" onClick={() => this.addNewWindow(formik.values)}>
181
+ {' '}
182
+ Add Window
183
+ </button>
184
+ </div>
185
+ </div>
186
+ </>
187
+ )}
188
+ />
189
+ );
190
+ };
191
+
192
+ public render() {
193
+ const { CurrentWindows, NewWindowComponent } = this;
194
+ const { isDisabled } = this.props;
195
+ return (
196
+ <>
197
+ <CurrentWindows />
198
+ {!isDisabled && <NewWindowComponent />}
199
+ </>
200
+ );
201
+ }
202
+ }
@@ -0,0 +1,4 @@
1
+ export * from './ServerGroupBasicSettings';
2
+ export * from './ServerGroupResources';
3
+ export * from './ServerGroupParameters';
4
+ export * from './disruptionBudget/JobDisruptionBudget';
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+
3
+ import type { Application } from '@spinnaker/core';
4
+ import {
5
+ confirmNotManaged,
6
+ CurrentCapacity,
7
+ DesiredCapacity,
8
+ Overridable,
9
+ ReactModal,
10
+ showModal,
11
+ } from '@spinnaker/core';
12
+
13
+ import type { ITitusServerGroup } from '../../domain';
14
+ import type { ITitusResizeServerGroupModalProps } from './resize/TitusResizeServerGroupModal';
15
+ import { TitusResizeServerGroupModal } from './resize/TitusResizeServerGroupModal';
16
+ import { TitusScalingActivitiesModal } from './scalingActivity/TitusScalingActivitiesModal';
17
+
18
+ interface ICapacityDetailsSectionProps {
19
+ app: Application;
20
+ serverGroup: ITitusServerGroup;
21
+ }
22
+
23
+ @Overridable('titus.serverGroup.CapacityDetailsSection')
24
+ export class TitusCapacityDetailsSection extends React.Component<ICapacityDetailsSectionProps> {
25
+ public render(): JSX.Element {
26
+ const { serverGroup, app: application } = this.props;
27
+ const { capacity } = serverGroup;
28
+ const current = serverGroup.instances.length;
29
+ const simpleMode = capacity.min === capacity.max;
30
+
31
+ const resizeServerGroup = () =>
32
+ confirmNotManaged(serverGroup, application).then((notManaged) => {
33
+ notManaged &&
34
+ ReactModal.show<ITitusResizeServerGroupModalProps>(TitusResizeServerGroupModal, { serverGroup, application });
35
+ });
36
+
37
+ return (
38
+ <>
39
+ <dl className="dl-horizontal dl-narrow">
40
+ <DesiredCapacity capacity={capacity} simpleMode={simpleMode} />
41
+ <CurrentCapacity currentCapacity={current} />
42
+ {serverGroup.capacityGroup && (
43
+ <>
44
+ <dt>Cap. Group</dt>
45
+ <dd>{serverGroup.capacityGroup}</dd>
46
+ </>
47
+ )}
48
+ </dl>
49
+
50
+ <div>
51
+ <a className="clickable" onClick={resizeServerGroup}>
52
+ Resize Server Group
53
+ </a>
54
+ </div>
55
+ <div>
56
+ <a
57
+ className="clickable"
58
+ onClick={() => showModal(TitusScalingActivitiesModal, { serverGroup }, { maxWidth: '1000px' })}
59
+ >
60
+ View Scaling Activities
61
+ </a>
62
+ </div>
63
+ </>
64
+ );
65
+ }
66
+ }
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+
3
+ import { LabeledValue, LabeledValueList, Overridable } from '@spinnaker/core';
4
+ import type { ITitusServerGroup } from '../../domain';
5
+
6
+ interface ILaunchConfigSectionProps {
7
+ serverGroup: ITitusServerGroup;
8
+ }
9
+
10
+ @Overridable('titus.serverGroup.launchConfigSection')
11
+ export class TitusLaunchConfigSection extends React.Component<ILaunchConfigSectionProps> {
12
+ public render() {
13
+ if (!this.props.serverGroup || !this.props.serverGroup.image) {
14
+ return null;
15
+ }
16
+
17
+ const {
18
+ serverGroup: { image, entryPoint, iamProfile, resources },
19
+ } = this.props;
20
+
21
+ return (
22
+ <LabeledValueList className="horizontal-when-filters-collapsed">
23
+ {image.dockerImageName && <LabeledValue label="Image Name" value={image.dockerImageName} />}
24
+ {image.dockerImageVersion && <LabeledValue label="Image Version" value={image.dockerImageVersion} />}
25
+ {entryPoint && <LabeledValue label="Entrypoint" value={entryPoint} />}
26
+ {iamProfile && <LabeledValue label="IAM Profile" value={iamProfile} />}
27
+ <LabeledValue label="CPU(s)" value={resources.cpu} />
28
+ <LabeledValue label="Memory" value={`${resources.memory} MB`} />
29
+ <LabeledValue label="Disk" value={`${resources.disk} MB`} />
30
+ <LabeledValue label="Network" value={`${resources.networkMbps} Mbps`} />
31
+ <LabeledValue label="GPU(s)" value={resources.gpu} />
32
+ </LabeledValueList>
33
+ );
34
+ }
35
+ }
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ import { CollapsibleSection, LabeledValue, LabeledValueList } from '@spinnaker/core';
3
+ import type { ITitusBuildInfo } from '../../domain';
4
+
5
+ export interface ITitusPackageDetailsSectionProps {
6
+ buildInfo: ITitusBuildInfo;
7
+ }
8
+
9
+ export const TitusPackageDetailsSection = ({ buildInfo }: ITitusPackageDetailsSectionProps) => {
10
+ const packageInfo = buildInfo.jenkins || {};
11
+ const hasPackageInfo = Boolean(Object.keys(packageInfo).length);
12
+
13
+ const { commitId, host, name, number, version } = packageInfo;
14
+ const jenkinsLink = `${host}job/${name}/${number}`;
15
+
16
+ return (
17
+ <CollapsibleSection heading="Package">
18
+ {!hasPackageInfo && <div>No package information available.</div>}
19
+ {hasPackageInfo && (
20
+ <LabeledValueList className="horizontal-when-filters-collapsed">
21
+ {name && <LabeledValue label="Job" value={name} />}
22
+ {buildInfo.docker?.image && <LabeledValue label="Image Name" value={buildInfo.docker?.image} />}
23
+ {number && <LabeledValue label="Build" value={number} />}
24
+ {commitId && <LabeledValue label="Commit" value={commitId.substring(0, 8)} />}
25
+ {version && <LabeledValue label="Version" value={version} />}
26
+ {host && (
27
+ <LabeledValue
28
+ label="Build Link"
29
+ value={
30
+ <a target="_blank" href={jenkinsLink}>
31
+ {jenkinsLink}
32
+ </a>
33
+ }
34
+ />
35
+ )}
36
+ </LabeledValueList>
37
+ )}
38
+ </CollapsibleSection>
39
+ );
40
+ };
@@ -0,0 +1,107 @@
1
+ import { UISref } from '@uirouter/react';
2
+ import { UIRouterContextComponent } from '@uirouter/react-hybrid';
3
+ import { sortBy } from 'lodash';
4
+ import React from 'react';
5
+
6
+ import type { Application, ISecurityGroup } from '@spinnaker/core';
7
+ import { AccountService, CollapsibleSection, FirewallLabels, ReactInjector } from '@spinnaker/core';
8
+ import type { ITitusServerGroupView } from '../../domain';
9
+ import { TitusReactInjector } from '../../reactShims';
10
+
11
+ export interface ITitusServerGroupDetailsSectionProps {
12
+ app: Application;
13
+ serverGroup: ITitusServerGroupView;
14
+ }
15
+
16
+ export interface ISecurityGroupsDetailsSectionState {
17
+ securityGroups?: ISecurityGroup[];
18
+ }
19
+
20
+ export class TitusSecurityGroupsDetailsSection extends React.Component<
21
+ ITitusServerGroupDetailsSectionProps,
22
+ ISecurityGroupsDetailsSectionState
23
+ > {
24
+ constructor(props: ITitusServerGroupDetailsSectionProps) {
25
+ super(props);
26
+ this.state = {};
27
+ }
28
+
29
+ public componentDidMount() {
30
+ this.configureSecurityGroups(this.props);
31
+ }
32
+
33
+ private configureSecurityGroups(props: ITitusServerGroupDetailsSectionProps): void {
34
+ const { app, serverGroup } = props;
35
+ const { region } = serverGroup;
36
+ if (app.securityGroupsIndex && serverGroup.accountDetails) {
37
+ const securityGroups = serverGroup.securityGroups.map((sgId) =>
38
+ TitusReactInjector.titusSecurityGroupReader.resolveIndexedSecurityGroup(
39
+ app.securityGroupsIndex,
40
+ { account: serverGroup.accountDetails.awsAccount, region },
41
+ sgId,
42
+ ),
43
+ );
44
+ this.setState({ securityGroups });
45
+ } else {
46
+ AccountService.listAllAccounts('titus').then((accounts) => {
47
+ const titusAccount = accounts.find((a) => a.name === serverGroup.account);
48
+ if (titusAccount && titusAccount.awsAccount) {
49
+ ReactInjector.securityGroupReader.getAllSecurityGroups().then((allSecurityGroups) => {
50
+ const regionalGroups = allSecurityGroups[titusAccount.awsAccount]['aws'][region];
51
+ const securityGroups = serverGroup.securityGroups
52
+ .map((sgId) => regionalGroups.find((rg) => rg.id === sgId))
53
+ .filter((g) => g)
54
+ .map((sg) => ({
55
+ account: titusAccount.awsAccount,
56
+ name: sg.name,
57
+ id: sg.id,
58
+ vpcId: sg.vpcId,
59
+ }));
60
+ this.setState({ securityGroups });
61
+ });
62
+ }
63
+ });
64
+ }
65
+ }
66
+
67
+ public componentWillReceiveProps(nextProps: ITitusServerGroupDetailsSectionProps): void {
68
+ this.configureSecurityGroups(nextProps);
69
+ }
70
+
71
+ public render(): JSX.Element {
72
+ const { serverGroup } = this.props;
73
+ const { securityGroups } = this.state;
74
+ // prevent a reflow of the details panel when the security groups actually load by rendering a placeholder
75
+ const initializing = !securityGroups && (serverGroup.securityGroups || []).length;
76
+
77
+ return (
78
+ <CollapsibleSection heading={FirewallLabels.get('Firewalls')} outerDivClassName="">
79
+ <ul>
80
+ {initializing && serverGroup.securityGroups.map((sgId) => <li key={sgId}>...</li>)}
81
+ <UIRouterContextComponent>
82
+ <>
83
+ {sortBy(securityGroups, 'name').map((securityGroup) => (
84
+ <li key={securityGroup.name}>
85
+ <UISref
86
+ to="^.firewallDetails"
87
+ params={{
88
+ name: securityGroup.name,
89
+ accountId: securityGroup.account,
90
+ region: serverGroup.region,
91
+ vpcId: securityGroup.vpcId,
92
+ provider: 'aws',
93
+ }}
94
+ >
95
+ <a>
96
+ {securityGroup.name} ({securityGroup.id})
97
+ </a>
98
+ </UISref>
99
+ </li>
100
+ ))}
101
+ </>
102
+ </UIRouterContextComponent>
103
+ </ul>
104
+ </CollapsibleSection>
105
+ );
106
+ }
107
+ }
@@ -0,0 +1,12 @@
1
+ import { module } from 'angular';
2
+ import { react2angular } from 'react2angular';
3
+
4
+ import { withErrorBoundary } from '@spinnaker/core';
5
+
6
+ import { TitusCapacityDetailsSection } from './TitusCapacityDetailsSection';
7
+
8
+ export const TITUS_SERVERGROUP_DETAILS_CAPACITYDETAILSSECTION = 'titus.servergroup.details.capacitydetailssection';
9
+ module(TITUS_SERVERGROUP_DETAILS_CAPACITYDETAILSSECTION, []).component(
10
+ 'titusCapacityDetailsSection',
11
+ react2angular(withErrorBoundary(TitusCapacityDetailsSection, 'titusCapacityDetailsSection'), ['serverGroup', 'app']),
12
+ );