@spinnaker/kubernetes 2026.2.2 → 2026.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/index.d.ts +1 -2
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/instance/details/KubernetesInstanceDetails.d.ts +54 -0
  5. package/dist/instance/details/kubernetesInstanceDetails.utils.d.ts +13 -0
  6. package/dist/instance/index.d.ts +1 -1
  7. package/dist/kubernetes.module.d.ts +5 -1
  8. package/dist/loadBalancer/transformer.d.ts +1 -1
  9. package/dist/manifest/AnnotationCustomSections.d.ts +3 -2
  10. package/dist/manifest/ManifestKindSearch.d.ts +1 -1
  11. package/dist/manifest/delete/Delete.d.ts +0 -1
  12. package/dist/manifest/delete/DeleteModal.d.ts +1 -1
  13. package/dist/manifest/delete/delete.types.d.ts +4 -0
  14. package/dist/manifest/index.d.ts +3 -6
  15. package/dist/manifest/manifest.service.d.ts +5 -0
  16. package/dist/manifest/manifestCommandBuilder.service.d.ts +1 -1
  17. package/dist/manifest/rollout/PauseRollout.d.ts +0 -1
  18. package/dist/manifest/rollout/ResumeRollout.d.ts +0 -1
  19. package/dist/manifest/rollout/RollingRestart.d.ts +4 -4
  20. package/dist/manifest/rollout/UndoRollout.d.ts +0 -1
  21. package/dist/manifest/scale/Scale.d.ts +1 -2
  22. package/dist/manifest/scale/ScaleModal.d.ts +3 -3
  23. package/dist/manifest/scale/ScaleSettingsForm.d.ts +7 -1
  24. package/dist/manifest/selector/ManifestSelector.d.ts +1 -1
  25. package/dist/manifest/traffic/ManifestTrafficService.d.ts +2 -2
  26. package/dist/pipelines/stages/deleteManifest/DeleteManifestOptionsForm.d.ts +1 -1
  27. package/dist/pipelines/stages/deployManifest/manifestStatus/DeployStatus.d.ts +1 -0
  28. package/dist/pipelines/stages/deployManifest/manifestStatus/ManifestDetailsLink.d.ts +6 -3
  29. package/dist/pipelines/stages/traffic/disableManifest.stage.d.ts +2 -1
  30. package/dist/pipelines/stages/traffic/enableManifest.stage.d.ts +2 -1
  31. package/dist/rawResource/index.d.ts +3 -1
  32. package/dist/rawResource/rawResource.dataSource.d.ts +1 -1
  33. package/dist/rawResource/rawResource.states.d.ts +4 -1
  34. package/dist/resources/resources.state.d.ts +2 -1
  35. package/dist/securityGroup/details/KubernetesSecurityGroupDetails.d.ts +49 -0
  36. package/dist/securityGroup/index.d.ts +3 -1
  37. package/dist/securityGroup/transformer.d.ts +4 -1
  38. package/dist/serverGroup/serverGroupCommandBuilder.d.ts +1 -1
  39. package/dist/serverGroup/serverGroupTransformer.d.ts +1 -1
  40. package/dist/serverGroupManager/details/ServerGroupManagerDetails.d.ts +7 -3
  41. package/package.json +3 -12
  42. package/src/help/kubernetes.help.ts +2 -0
  43. package/src/index.ts +2 -2
  44. package/src/instance/details/KubernetesInstanceDetails.spec.tsx +451 -0
  45. package/src/instance/details/KubernetesInstanceDetails.tsx +342 -0
  46. package/src/instance/details/kubernetesInstanceDetails.utils.ts +77 -0
  47. package/src/instance/index.ts +1 -1
  48. package/src/kubernetes.module.spec.ts +25 -0
  49. package/src/kubernetes.module.ts +23 -87
  50. package/src/loadBalancer/details/KubernetesLoadBalancerActions.tsx +30 -35
  51. package/src/loadBalancer/details/sections/LoadBalancerAnnotationCustomSection.tsx +2 -3
  52. package/src/loadBalancer/transformer.ts +1 -1
  53. package/src/manifest/AnnotationCustomSections.spec.tsx +178 -0
  54. package/src/manifest/AnnotationCustomSections.tsx +179 -2
  55. package/src/manifest/ManifestKindSearch.tsx +1 -1
  56. package/src/manifest/delete/Delete.tsx +0 -9
  57. package/src/manifest/delete/DeleteModal.tsx +69 -72
  58. package/src/manifest/delete/delete.types.ts +4 -0
  59. package/src/manifest/index.ts +3 -6
  60. package/src/manifest/manifest.service.ts +18 -1
  61. package/src/manifest/manifestCommandBuilder.service.spec.ts +41 -0
  62. package/src/manifest/manifestCommandBuilder.service.ts +45 -59
  63. package/src/manifest/rollout/PauseRollout.tsx +1 -9
  64. package/src/manifest/rollout/ResumeRollout.tsx +2 -10
  65. package/src/manifest/rollout/RollingRestart.tsx +16 -22
  66. package/src/manifest/rollout/UndoRollout.tsx +1 -10
  67. package/src/manifest/rollout/UndoRolloutModal.tsx +5 -1
  68. package/src/manifest/scale/Scale.tsx +12 -11
  69. package/src/manifest/scale/ScaleModal.tsx +43 -31
  70. package/src/manifest/scale/ScaleSettingsForm.tsx +8 -1
  71. package/src/manifest/selector/ManifestSelector.spec.tsx +89 -46
  72. package/src/manifest/selector/ManifestSelector.tsx +4 -5
  73. package/src/manifest/traffic/ManifestTrafficService.ts +2 -2
  74. package/src/manifest/wizard/ManifestWizard.tsx +1 -1
  75. package/src/pipelines/stages/deleteManifest/DeleteManifestOptionsForm.tsx +1 -1
  76. package/src/pipelines/stages/deleteManifest/DeleteManifestStageConfig.tsx +1 -1
  77. package/src/pipelines/stages/deployManifest/DeployManifestStageForm.tsx +16 -0
  78. package/src/pipelines/stages/deployManifest/ManifestCopier.spec.ts +52 -77
  79. package/src/pipelines/stages/deployManifest/ManifestDeploymentOptions.spec.tsx +2 -0
  80. package/src/pipelines/stages/deployManifest/manifestStatus/DeployStatus.tsx +39 -4
  81. package/src/pipelines/stages/deployManifest/manifestStatus/ManifestDetailsLink.spec.tsx +35 -0
  82. package/src/pipelines/stages/deployManifest/manifestStatus/ManifestDetailsLink.tsx +10 -5
  83. package/src/pipelines/stages/traffic/ManifestTrafficStageRegistration.spec.ts +34 -0
  84. package/src/pipelines/stages/traffic/disableManifest.stage.ts +17 -19
  85. package/src/pipelines/stages/traffic/enableManifest.stage.ts +17 -19
  86. package/src/rawResource/index.ts +18 -1
  87. package/src/rawResource/rawResource.dataSource.ts +5 -8
  88. package/src/rawResource/rawResource.states.ts +50 -51
  89. package/src/resources/resources.state.spec.ts +138 -0
  90. package/src/resources/resources.state.ts +30 -35
  91. package/src/securityGroup/details/KubernetesSecurityGroupDetails.spec.tsx +292 -0
  92. package/src/securityGroup/details/KubernetesSecurityGroupDetails.tsx +304 -0
  93. package/src/securityGroup/index.ts +3 -1
  94. package/src/securityGroup/transformer.ts +2 -10
  95. package/src/serverGroup/details/KubernetesServerGroupActions.tsx +31 -61
  96. package/src/serverGroup/details/kubernetesServerGroupDetailsGetter.ts +1 -1
  97. package/src/serverGroup/details/sections/ServerGroupAnnotationCustomSection.tsx +2 -3
  98. package/src/serverGroup/serverGroupCommandBuilder.ts +1 -1
  99. package/src/serverGroup/serverGroupTransformer.ts +1 -1
  100. package/src/serverGroupManager/details/ServerGroupManagerActions.tsx +48 -128
  101. package/src/serverGroupManager/details/ServerGroupManagerDetails.spec.ts +12 -0
  102. package/src/serverGroupManager/details/ServerGroupManagerDetails.tsx +19 -8
  103. package/src/serverGroupManager/details/sections/ServerGroupManagerAnnotationCustomSection.tsx +2 -3
  104. package/src/serverGroupManager/details/useKubernetesServerGroupManagerDetails.spec.tsx +112 -0
  105. package/src/serverGroupManager/details/useKubernetesServerGroupManagerDetails.tsx +50 -29
  106. package/dist/instance/details/details.controller.d.ts +0 -1
  107. package/dist/manifest/annotationCustomSections.component.d.ts +0 -3
  108. package/dist/manifest/delete/delete.controller.d.ts +0 -12
  109. package/dist/manifest/delete/deleteOptionsForm.component.d.ts +0 -1
  110. package/dist/manifest/editor/json/jsonEditor.component.d.ts +0 -1
  111. package/dist/manifest/manifestEvents.component.d.ts +0 -1
  112. package/dist/manifest/manifestImageDetails.component.d.ts +0 -1
  113. package/dist/manifest/manifestLabels.component.d.ts +0 -1
  114. package/dist/manifest/manifestQos.component.d.ts +0 -1
  115. package/dist/manifest/manifestResources.component.d.ts +0 -1
  116. package/dist/manifest/rollout/pause.controller.d.ts +0 -1
  117. package/dist/manifest/rollout/resume.controller.d.ts +0 -1
  118. package/dist/manifest/rollout/undo.controller.d.ts +0 -5
  119. package/dist/manifest/scale/scale.controller.d.ts +0 -8
  120. package/dist/manifest/scale/scaleSettingsForm.component.d.ts +0 -1
  121. package/dist/manifest/selector/selector.component.d.ts +0 -1
  122. package/dist/manifest/status/condition.component.d.ts +0 -1
  123. package/dist/manifest/status/status.component.d.ts +0 -1
  124. package/dist/rawResource/rawResource.module.d.ts +0 -1
  125. package/dist/reactShims/index.d.ts +0 -1
  126. package/dist/reactShims/kubernetes.react.injector.d.ts +0 -11
  127. package/dist/reactShims/kubernetes.react.module.d.ts +0 -1
  128. package/dist/securityGroup/details/details.controller.d.ts +0 -1
  129. package/src/instance/details/details.controller.ts +0 -186
  130. package/src/instance/details/details.html +0 -80
  131. package/src/manifest/annotationCustomSections.component.ts +0 -114
  132. package/src/manifest/delete/delete.controller.ts +0 -80
  133. package/src/manifest/delete/delete.html +0 -42
  134. package/src/manifest/delete/deleteOptionsForm.component.ts +0 -52
  135. package/src/manifest/editor/json/jsonEditor.component.ts +0 -12
  136. package/src/manifest/manifestEvents.component.ts +0 -12
  137. package/src/manifest/manifestImageDetails.component.ts +0 -12
  138. package/src/manifest/manifestLabels.component.ts +0 -12
  139. package/src/manifest/manifestQos.component.ts +0 -12
  140. package/src/manifest/manifestResources.component.ts +0 -12
  141. package/src/manifest/rollout/pause.controller.ts +0 -66
  142. package/src/manifest/rollout/pause.html +0 -28
  143. package/src/manifest/rollout/resume.controller.ts +0 -66
  144. package/src/manifest/rollout/resume.html +0 -28
  145. package/src/manifest/rollout/undo.controller.ts +0 -74
  146. package/src/manifest/rollout/undo.html +0 -44
  147. package/src/manifest/scale/scale.controller.ts +0 -75
  148. package/src/manifest/scale/scale.html +0 -32
  149. package/src/manifest/scale/scaleSettingsForm.component.ts +0 -11
  150. package/src/manifest/selector/selector.component.ts +0 -17
  151. package/src/manifest/status/condition.component.ts +0 -12
  152. package/src/manifest/status/status.component.ts +0 -11
  153. package/src/rawResource/rawResource.module.ts +0 -8
  154. package/src/reactShims/index.ts +0 -1
  155. package/src/reactShims/kubernetes.react.injector.ts +0 -30
  156. package/src/reactShims/kubernetes.react.module.ts +0 -12
  157. package/src/securityGroup/details/details.controller.ts +0 -118
  158. package/src/securityGroup/details/details.html +0 -91
@@ -0,0 +1,342 @@
1
+ import React from 'react';
2
+ import { Dropdown, MenuItem } from 'react-bootstrap';
3
+
4
+ import type { Application, IManifest, IMoniker, IRouterInjectedProps } from '@spinnaker/core';
5
+ import {
6
+ AccountTag,
7
+ CollapsibleSection,
8
+ ConsoleOutputLink,
9
+ InstanceDetailsHeader,
10
+ InstanceLinks,
11
+ InstanceReader,
12
+ ManifestReader,
13
+ RecentHistoryService,
14
+ robotToHuman,
15
+ SETTINGS,
16
+ timestamp,
17
+ useModal,
18
+ withRouter,
19
+ } from '@spinnaker/core';
20
+
21
+ import type { IKubernetesInstance } from '../../interfaces';
22
+ import { findKubernetesInstanceIdentifier } from './kubernetesInstanceDetails.utils';
23
+ import { AnnotationCustomSections } from '../../manifest/AnnotationCustomSections';
24
+ import { ManifestLabels } from '../../manifest/ManifestLabels';
25
+ import { ManifestQos } from '../../manifest/ManifestQos';
26
+ import { ManifestResources } from '../../manifest/ManifestResources';
27
+ import { DeleteModal } from '../../manifest/delete/DeleteModal';
28
+ import { KubernetesManifestCommandBuilder } from '../../manifest/manifestCommandBuilder.service';
29
+ import { ManifestCondition } from '../../manifest/status/ManifestCondition';
30
+ import { ManifestWizard } from '../../manifest/wizard/ManifestWizard';
31
+ import { ManifestEvents } from '../../pipelines/stages/deployManifest/manifestStatus/ManifestEvents';
32
+
33
+ interface IInstanceFromStateParams {
34
+ instanceId: string;
35
+ }
36
+
37
+ export interface IKubernetesInstanceDetailsProps {
38
+ $stateParams?: {
39
+ instanceId?: string;
40
+ };
41
+ app: Application;
42
+ autoClose?: () => void;
43
+ environment?: string;
44
+ instance?: IInstanceFromStateParams;
45
+ moniker?: IMoniker;
46
+ }
47
+
48
+ interface IConsoleOutputInstance {
49
+ account: string;
50
+ region: string;
51
+ id: string;
52
+ provider: string;
53
+ }
54
+
55
+ interface IKubernetesInstanceDetailsState {
56
+ instance?: IKubernetesInstance;
57
+ loading: boolean;
58
+ manifest?: IKubernetesInstanceManifest;
59
+ }
60
+
61
+ interface IKubernetesInstanceManifest extends IManifest {
62
+ metrics?: any;
63
+ }
64
+
65
+ export interface IKubernetesInstanceActionsProps {
66
+ app: Application;
67
+ instance: IKubernetesInstance;
68
+ manifest: IManifest;
69
+ }
70
+
71
+ export class KubernetesInstanceDetailsComponent extends React.Component<
72
+ IKubernetesInstanceDetailsProps & IRouterInjectedProps,
73
+ IKubernetesInstanceDetailsState
74
+ > {
75
+ protected readonly renderActions: boolean = true;
76
+ protected readonly instanceLinksPlacement: 'afterInformation' | 'afterSections' = 'afterSections';
77
+
78
+ public state: IKubernetesInstanceDetailsState = {
79
+ loading: true,
80
+ };
81
+
82
+ private isUnmounted = false;
83
+ private appReady = false;
84
+ private loadRequestId = 0;
85
+ private unsubscribeFromRefresh: () => void;
86
+
87
+ public componentDidMount(): void {
88
+ this.props.app
89
+ .ready()
90
+ .then(() => {
91
+ if (this.isUnmounted) {
92
+ return;
93
+ }
94
+
95
+ this.appReady = true;
96
+ this.loadInstance();
97
+ this.unsubscribeFromRefresh = this.props.app.onRefresh(this.loadInstance);
98
+ })
99
+ .catch(this.autoClose);
100
+ }
101
+
102
+ public componentDidUpdate(prevProps: IKubernetesInstanceDetailsProps): void {
103
+ if (this.appReady && this.getInstanceId(prevProps) !== this.getInstanceId(this.props)) {
104
+ this.loadInstance();
105
+ }
106
+ }
107
+
108
+ public componentWillUnmount(): void {
109
+ this.isUnmounted = true;
110
+ if (this.unsubscribeFromRefresh) {
111
+ this.unsubscribeFromRefresh();
112
+ }
113
+ }
114
+
115
+ private getInstanceId = (props: IKubernetesInstanceDetailsProps): string =>
116
+ props.instance?.instanceId || props.$stateParams?.instanceId;
117
+
118
+ private loadInstance = (): void => {
119
+ const { app } = this.props;
120
+ const instanceId = this.getInstanceId(this.props);
121
+ const requestId = ++this.loadRequestId;
122
+ const identifier = findKubernetesInstanceIdentifier(app, instanceId, (extraData) =>
123
+ RecentHistoryService.addExtraDataToLatest('instances', extraData),
124
+ );
125
+
126
+ if (!identifier) {
127
+ this.autoClose();
128
+ return;
129
+ }
130
+
131
+ this.setState({ loading: true });
132
+
133
+ Promise.all([
134
+ InstanceReader.getInstanceDetails(identifier.account, identifier.namespace, identifier.name).then(
135
+ (instanceDetails: IKubernetesInstance) => ({
136
+ ...instanceDetails,
137
+ id: identifier.id,
138
+ name: identifier.name,
139
+ provider: 'kubernetes',
140
+ }),
141
+ ),
142
+ ManifestReader.getManifest(identifier.account, identifier.namespace, identifier.name).then(
143
+ (manifest) => manifest as IKubernetesInstanceManifest,
144
+ ),
145
+ ])
146
+ .then(([instance, manifest]) => {
147
+ if (this.isCurrentLoad(requestId)) {
148
+ this.setState({ instance, manifest, loading: false });
149
+ }
150
+ })
151
+ .catch(() => {
152
+ if (this.isCurrentLoad(requestId)) {
153
+ this.autoClose();
154
+ }
155
+ });
156
+ };
157
+
158
+ private isCurrentLoad(requestId: number): boolean {
159
+ return !this.isUnmounted && requestId === this.loadRequestId;
160
+ }
161
+
162
+ private autoClose = (): void => {
163
+ if (this.isUnmounted) {
164
+ return;
165
+ }
166
+
167
+ if (this.props.autoClose) {
168
+ this.props.autoClose();
169
+ return;
170
+ }
171
+
172
+ this.props.stateService.params.allowModalToStayOpen = true;
173
+ this.props.stateService.go('^', null, { location: 'replace' });
174
+ };
175
+
176
+ private buildConsoleOutputInstance(instance: IKubernetesInstance): IConsoleOutputInstance {
177
+ return {
178
+ account: instance.account,
179
+ region: instance.zone || instance.namespace,
180
+ id: instance.humanReadableName || instance.name,
181
+ provider: instance.provider || instance.cloudProvider || 'kubernetes',
182
+ };
183
+ }
184
+
185
+ public render(): JSX.Element {
186
+ const { app } = this.props;
187
+ const { instance, loading, manifest } = this.state;
188
+
189
+ if (loading || !instance || !manifest) {
190
+ return (
191
+ <div className="details-panel">
192
+ <div className="header">
193
+ <InstanceDetailsHeader
194
+ cloudProvider="kubernetes"
195
+ healthState=""
196
+ instanceId={this.getInstanceId(this.props)}
197
+ loading={true}
198
+ standalone={app.isStandalone}
199
+ />
200
+ </div>
201
+ </div>
202
+ );
203
+ }
204
+
205
+ const manifestBody = manifest.manifest;
206
+ const statusConditions = manifestBody?.status?.conditions || [];
207
+
208
+ return (
209
+ <div className="details-panel">
210
+ <div className="header">
211
+ <InstanceDetailsHeader
212
+ cloudProvider={instance.cloudProvider || instance.provider || 'kubernetes'}
213
+ healthState={instance.healthState}
214
+ instanceId={instance.displayName || instance.humanReadableName || instance.name}
215
+ loading={false}
216
+ standalone={app.isStandalone}
217
+ />
218
+ {this.renderActions && (
219
+ <div className="actions">
220
+ <KubernetesInstanceActions app={app} instance={instance} manifest={manifest} />
221
+ </div>
222
+ )}
223
+ </div>
224
+
225
+ <div className="content">
226
+ {this.renderInformationSection(instance, manifest)}
227
+ {this.renderInstanceLinks('afterInformation', instance)}
228
+ <CollapsibleSection heading="Status" defaultExpanded={true}>
229
+ {statusConditions.map((condition: any, index: number) => (
230
+ <ul key={`${condition.type || 'condition'}-${index}`}>
231
+ <ManifestCondition condition={condition} />
232
+ </ul>
233
+ ))}
234
+ </CollapsibleSection>
235
+ <AnnotationCustomSections manifest={manifestBody} resource={instance} />
236
+ <CollapsibleSection heading="Events" defaultExpanded={true}>
237
+ <ManifestEvents manifest={manifest} />
238
+ </CollapsibleSection>
239
+ <CollapsibleSection heading="Resources" defaultExpanded={true}>
240
+ <ManifestResources manifest={manifestBody} metrics={manifest.metrics as any} />
241
+ </CollapsibleSection>
242
+ <CollapsibleSection heading="Labels" defaultExpanded={true}>
243
+ <ManifestLabels manifest={manifestBody} />
244
+ </CollapsibleSection>
245
+ {this.renderInstanceLinks('afterSections', instance)}
246
+ </div>
247
+ </div>
248
+ );
249
+ }
250
+
251
+ private renderInstanceLinks(
252
+ placement: 'afterInformation' | 'afterSections',
253
+ instance: IKubernetesInstance,
254
+ ): JSX.Element | null {
255
+ const { app, environment } = this.props;
256
+
257
+ if (this.instanceLinksPlacement !== placement) {
258
+ return null;
259
+ }
260
+
261
+ return (
262
+ <InstanceLinks
263
+ address={instance.publicDnsName}
264
+ application={app}
265
+ instance={instance}
266
+ moniker={instance.moniker}
267
+ environment={environment}
268
+ />
269
+ );
270
+ }
271
+
272
+ private renderInformationSection(instance: IKubernetesInstance, manifest: IManifest): JSX.Element {
273
+ const manifestBody = manifest.manifest;
274
+
275
+ return (
276
+ <CollapsibleSection heading="Information" defaultExpanded={true}>
277
+ <dl className="dl-horizontal dl-narrow">
278
+ <dt>Created</dt>
279
+ <dd>{timestamp(instance.createdTime)}</dd>
280
+ <dt>Account</dt>
281
+ <dd>
282
+ <AccountTag account={instance.account} />
283
+ </dd>
284
+ <dt>Namespace</dt>
285
+ <dd>{instance.namespace}</dd>
286
+ <dt>Kind</dt>
287
+ <dd>{instance.kind}</dd>
288
+ <dt>QOS Class</dt>
289
+ <dd>
290
+ <ManifestQos manifest={manifestBody} />
291
+ </dd>
292
+ <dt>Logs</dt>
293
+ <dd>
294
+ <ConsoleOutputLink instance={this.buildConsoleOutputInstance(instance) as any} usesMultiOutput={true} />
295
+ </dd>
296
+ </dl>
297
+ </CollapsibleSection>
298
+ );
299
+ }
300
+ }
301
+
302
+ export const KubernetesInstanceDetails = withRouter(KubernetesInstanceDetailsComponent);
303
+
304
+ export function KubernetesInstanceActions({ app, instance, manifest }: IKubernetesInstanceActionsProps) {
305
+ const deleteModal = useModal();
306
+
307
+ if (!SETTINGS.kubernetesAdHocInfraWritesEnabled) {
308
+ return null;
309
+ }
310
+
311
+ const editInstance = (): void => {
312
+ KubernetesManifestCommandBuilder.buildNewManifestCommand(
313
+ app,
314
+ manifest.manifest,
315
+ instance.moniker,
316
+ instance.account,
317
+ ).then((builtCommand) => {
318
+ ManifestWizard.show({ title: 'Edit Manifest', application: app, command: builtCommand });
319
+ });
320
+ };
321
+
322
+ return (
323
+ <>
324
+ <Dropdown className="dropdown" id="instance-actions-dropdown">
325
+ <Dropdown.Toggle className="btn btn-sm btn-primary dropdown-toggle">
326
+ {robotToHuman(instance.kind)} Actions
327
+ </Dropdown.Toggle>
328
+ <Dropdown.Menu>
329
+ <MenuItem onClick={deleteModal.show}>Delete</MenuItem>
330
+ <MenuItem onClick={editInstance}>Edit</MenuItem>
331
+ </Dropdown.Menu>
332
+ </Dropdown>
333
+ <DeleteModal
334
+ application={app}
335
+ resource={instance}
336
+ manifestController={undefined}
337
+ isOpen={deleteModal.open}
338
+ dismissModal={deleteModal.close}
339
+ />
340
+ </>
341
+ );
342
+ }
@@ -0,0 +1,77 @@
1
+ import { flattenDeep } from 'lodash';
2
+
3
+ import type { Application, ILoadBalancer } from '@spinnaker/core';
4
+
5
+ import type { IKubernetesInstance } from '../../interfaces';
6
+
7
+ export interface IKubernetesInstanceIdentifier {
8
+ account: string;
9
+ id: string;
10
+ name: string;
11
+ namespace: string;
12
+ }
13
+
14
+ export interface IKubernetesInstanceRecentHistoryData {
15
+ account: string;
16
+ region: string;
17
+ serverGroup?: string;
18
+ }
19
+
20
+ interface InstanceManager {
21
+ account: string;
22
+ region: string;
23
+ category: string;
24
+ name: string;
25
+ instances?: IKubernetesInstance[];
26
+ }
27
+
28
+ export function findKubernetesInstanceIdentifier(
29
+ app: Application,
30
+ instanceId: string,
31
+ addRecentHistoryData: (extraData: IKubernetesInstanceRecentHistoryData) => void = () => null,
32
+ ): IKubernetesInstanceIdentifier | null {
33
+ const instanceManager = getInstanceManagers(app).find((dataSource) =>
34
+ (dataSource.instances || []).some((possibleMatch) => possibleMatch.id === instanceId),
35
+ );
36
+
37
+ if (!instanceManager) {
38
+ return null;
39
+ }
40
+
41
+ const instance = (instanceManager.instances || []).find((possibleMatch) => possibleMatch.id === instanceId);
42
+ if (!instance) {
43
+ return null;
44
+ }
45
+
46
+ const recentHistoryExtraData: IKubernetesInstanceRecentHistoryData = {
47
+ region: instanceManager.region,
48
+ account: instanceManager.account,
49
+ };
50
+
51
+ if (instanceManager.category === 'serverGroup') {
52
+ recentHistoryExtraData.serverGroup = instanceManager.name;
53
+ }
54
+
55
+ addRecentHistoryData(recentHistoryExtraData);
56
+
57
+ return {
58
+ id: instance.id,
59
+ name: instance.name,
60
+ namespace: instanceManager.region,
61
+ account: instanceManager.account,
62
+ };
63
+ }
64
+
65
+ function getInstanceManagers(app: Application): InstanceManager[] {
66
+ const loadBalancers = getDataSourceData<ILoadBalancer>(app, 'loadBalancers');
67
+
68
+ return flattenDeep([
69
+ getDataSourceData<InstanceManager>(app, 'serverGroups'),
70
+ loadBalancers,
71
+ loadBalancers.map((loadBalancer) => loadBalancer.serverGroups || []),
72
+ ]).filter(Boolean) as InstanceManager[];
73
+ }
74
+
75
+ function getDataSourceData<T>(app: Application, key: string): T[] {
76
+ return (app.getDataSource(key)?.data || []) as T[];
77
+ }
@@ -1 +1 @@
1
- export * from './details/details.controller';
1
+ export * from './details/KubernetesInstanceDetails';
@@ -0,0 +1,25 @@
1
+ import { CloudProviderRegistry } from '@spinnaker/core';
2
+
3
+ import { KubernetesInstanceDetails } from './instance';
4
+ import { registerKubernetesProvider } from './kubernetes.module';
5
+ import { ManifestWizard } from './manifest/wizard/ManifestWizard';
6
+ import { KubernetesSecurityGroupDetails, KubernetesV2SecurityGroupTransformer } from './securityGroup';
7
+
8
+ describe('Kubernetes provider registration', () => {
9
+ it('registers the provider configuration', () => {
10
+ registerKubernetesProvider();
11
+
12
+ expect(CloudProviderRegistry.getValue('kubernetes', 'instance.details').displayName).toBe(
13
+ KubernetesInstanceDetails.displayName,
14
+ );
15
+ expect(CloudProviderRegistry.getValue('kubernetes', 'securityGroup.CreateSecurityGroupModal')).toBe(ManifestWizard);
16
+ expect(CloudProviderRegistry.getValue('kubernetes', 'securityGroup.details').displayName).toBe(
17
+ KubernetesSecurityGroupDetails.displayName,
18
+ );
19
+ expect(CloudProviderRegistry.getValue('kubernetes', 'securityGroup.transformer')).toBe(
20
+ KubernetesV2SecurityGroupTransformer,
21
+ );
22
+ expect(CloudProviderRegistry.getValue('kubernetes', 'instance.detailsController')).toBeNull();
23
+ expect(CloudProviderRegistry.getValue('kubernetes', 'securityGroup.detailsController')).toBeNull();
24
+ });
25
+ });
@@ -1,14 +1,7 @@
1
- import { module } from 'angular';
2
-
3
- import {
4
- CloudProviderRegistry,
5
- SETTINGS,
6
- STAGE_ARTIFACT_SELECTOR_COMPONENT_REACT,
7
- YAML_EDITOR_COMPONENT,
8
- } from '@spinnaker/core';
1
+ import { CloudProviderRegistry, SETTINGS } from '@spinnaker/core';
9
2
 
10
3
  import './help/kubernetes.help';
11
- import { KUBERNETES_INSTANCE_DETAILS_CTRL } from './instance/details/details.controller';
4
+ import { KubernetesInstanceDetails } from './instance';
12
5
  import {
13
6
  KubernetesLoadBalancerActions,
14
7
  KubernetesLoadBalancerTransformer,
@@ -20,39 +13,18 @@ import {
20
13
  useKubernetesLoadBalancerDetails,
21
14
  } from './loadBalancer';
22
15
  import kubernetesLogo from './logo/kubernetes.logo.svg';
23
- import { KUBERNETES_ANNOTATION_CUSTOM_SECTIONS } from './manifest/annotationCustomSections.component';
24
- import { KUBERNETES_DELETE } from './manifest/delete/Delete';
25
- import { KUBERNETES_MANIFEST_DELETE_CTRL } from './manifest/delete/delete.controller';
26
- import { JSON_EDITOR_COMPONENT } from './manifest/editor/json/jsonEditor.component';
27
- import { KUBERNETES_MANIFEST_EVENTS } from './manifest/manifestEvents.component';
28
- import { KUBERNETES_MANIFEST_IMAGE_DETAILS } from './manifest/manifestImageDetails.component';
29
- import { KUBERNETES_MANIFEST_LABELS } from './manifest/manifestLabels.component';
30
- import { KUBERNETES_MANIFEST_QOS } from './manifest/manifestQos.component';
31
- import { KUBERNETES_MANIFEST_RESOURCES } from './manifest/manifestResources.component';
32
- import { KUBERNETES_PAUSE_ROLLOUT } from './manifest/rollout/PauseRollout';
33
- import { KUBERNETES_RESUME_ROLLOUT } from './manifest/rollout/ResumeRollout';
34
- import { KUBERNETES_UNDO_ROLLOUT } from './manifest/rollout/UndoRollout';
35
- import { KUBERNETES_MANIFEST_PAUSE_ROLLOUT_CTRL } from './manifest/rollout/pause.controller';
36
- import { KUBERNETES_MANIFEST_RESUME_ROLLOUT_CTRL } from './manifest/rollout/resume.controller';
37
- import { KUBERNETES_MANIFEST_UNDO_ROLLOUT_CTRL } from './manifest/rollout/undo.controller';
38
- import { KUBERNETES_SCALE } from './manifest/scale/Scale';
39
- import { KUBERNETES_MANIFEST_SCALE_CTRL } from './manifest/scale/scale.controller';
40
- import { KUBERNETES_MANIFEST_SELECTOR } from './manifest/selector/selector.component';
41
- import { KUBERNETES_MANIFEST_CONDITION } from './manifest/status/condition.component';
42
- import { KUBERNETES_MANIFEST_STATUS } from './manifest/status/status.component';
43
16
  import { ManifestWizard } from './manifest/wizard/ManifestWizard';
44
17
  import './pipelines/stages';
45
- import { KUBERNETES_DISABLE_MANIFEST_STAGE } from './pipelines/stages/traffic/disableManifest.stage';
46
- import { KUBERNETES_ENABLE_MANIFEST_STAGE } from './pipelines/stages/traffic/enableManifest.stage';
18
+ import './pipelines/stages/traffic/disableManifest.stage';
19
+ import './pipelines/stages/traffic/enableManifest.stage';
47
20
  import './pipelines/validation/manifestSelector.validator';
48
- import { KUBERNETS_RAW_RESOURCE_MODULE } from './rawResource';
49
- import { KUBERNETES_REACT_MODULE } from './reactShims/kubernetes.react.module';
50
- import { KUBERNETES_RESOURCE_STATES } from './resources/resources.state';
51
- import { KUBERNETES_SECURITY_GROUP_DETAILS_CTRL } from './securityGroup/details/details.controller';
52
- import { KubernetesSecurityGroupReader } from './securityGroup/securityGroup.reader';
53
- import { KUBERNETES_SECURITY_GROUP_TRANSFORMER } from './securityGroup/transformer';
54
- import { KubernetesServerGroupActions } from './serverGroup/details/KubernetesServerGroupActions';
55
- import { kubernetesServerGroupDetailsGetter } from './serverGroup/details/kubernetesServerGroupDetailsGetter';
21
+ import './rawResource';
22
+ import './resources/resources.state';
23
+ import {
24
+ KubernetesSecurityGroupDetails,
25
+ KubernetesSecurityGroupReader,
26
+ KubernetesV2SecurityGroupTransformer,
27
+ } from './securityGroup';
56
28
  import {
57
29
  ServerGroupAnnotationCustomSection,
58
30
  ServerGroupEventsSection,
@@ -62,53 +34,17 @@ import {
62
34
  ServerGroupLabelsSection,
63
35
  ServerGroupManifestStatusSection,
64
36
  ServerGroupSizeSection,
65
- } from './serverGroup/details/sections';
66
- import { KubernetesV2ServerGroupCommandBuilder } from './serverGroup/serverGroupCommandBuilder';
67
- import { KubernetesV2ServerGroupTransformer } from './serverGroup/serverGroupTransformer';
37
+ } from './serverGroup';
38
+ import { KubernetesV2ServerGroupCommandBuilder } from './serverGroup';
39
+ import { KubernetesV2ServerGroupTransformer } from './serverGroup';
40
+ import { KubernetesServerGroupActions } from './serverGroup/details/KubernetesServerGroupActions';
41
+ import { kubernetesServerGroupDetailsGetter } from './serverGroup/details/kubernetesServerGroupDetailsGetter';
68
42
  import { ServerGroupManagerDetails } from './serverGroupManager/details/ServerGroupManagerDetails';
69
43
  import './validation/applicationName.validator';
70
44
 
71
45
  import './logo/kubernetes.logo.less';
72
46
 
73
- export const KUBERNETES_MODULE = 'spinnaker.kubernetes';
74
-
75
- const requires = [
76
- KUBERNETES_DELETE,
77
- KUBERNETES_PAUSE_ROLLOUT,
78
- KUBERNETES_RESUME_ROLLOUT,
79
- KUBERNETES_UNDO_ROLLOUT,
80
- KUBERNETES_SCALE,
81
- KUBERNETES_REACT_MODULE,
82
- KUBERNETES_INSTANCE_DETAILS_CTRL,
83
- KUBERNETES_SECURITY_GROUP_DETAILS_CTRL,
84
- KUBERNETES_MANIFEST_DELETE_CTRL,
85
- KUBERNETES_MANIFEST_SCALE_CTRL,
86
- KUBERNETES_MANIFEST_UNDO_ROLLOUT_CTRL,
87
- KUBERNETES_MANIFEST_PAUSE_ROLLOUT_CTRL,
88
- KUBERNETES_MANIFEST_RESUME_ROLLOUT_CTRL,
89
- KUBERNETES_MANIFEST_STATUS,
90
- KUBERNETES_MANIFEST_CONDITION,
91
- KUBERNETES_SECURITY_GROUP_TRANSFORMER,
92
- KUBERNETES_MANIFEST_SELECTOR,
93
- KUBERNETES_MANIFEST_LABELS,
94
- KUBERNETES_MANIFEST_EVENTS,
95
- KUBERNETES_MANIFEST_RESOURCES,
96
- KUBERNETES_MANIFEST_QOS,
97
- KUBERNETES_ANNOTATION_CUSTOM_SECTIONS,
98
- KUBERNETES_MANIFEST_IMAGE_DETAILS,
99
- KUBERNETES_RESOURCE_STATES,
100
- YAML_EDITOR_COMPONENT,
101
- JSON_EDITOR_COMPONENT,
102
- KUBERNETES_ENABLE_MANIFEST_STAGE,
103
- KUBERNETES_DISABLE_MANIFEST_STAGE,
104
- STAGE_ARTIFACT_SELECTOR_COMPONENT_REACT,
105
- ];
106
-
107
- if (SETTINGS.feature.kubernetesRawResources) {
108
- requires.push(KUBERNETS_RAW_RESOURCE_MODULE);
109
- }
110
-
111
- module(KUBERNETES_MODULE, requires).config(() => {
47
+ export function registerKubernetesProvider(): void {
112
48
  CloudProviderRegistry.registerProvider('kubernetes', {
113
49
  name: 'Kubernetes',
114
50
  adHocInfrastructureWritesEnabled: SETTINGS.kubernetesAdHocInfraWritesEnabled,
@@ -151,13 +87,11 @@ module(KUBERNETES_MODULE, requires).config(() => {
151
87
  securityGroup: {
152
88
  reader: KubernetesSecurityGroupReader,
153
89
  CreateSecurityGroupModal: ManifestWizard,
154
- detailsController: 'kubernetesV2SecurityGroupDetailsCtrl',
155
- detailsTemplateUrl: require('./securityGroup/details/details.html'),
156
- transformer: 'kubernetesV2SecurityGroupTransformer',
90
+ details: KubernetesSecurityGroupDetails,
91
+ transformer: KubernetesV2SecurityGroupTransformer,
157
92
  },
158
93
  instance: {
159
- detailsController: 'kubernetesV2InstanceDetailsCtrl',
160
- detailsTemplateUrl: require('./instance/details/details.html'),
94
+ details: KubernetesInstanceDetails,
161
95
  },
162
96
  unsupportedStageTypes: [
163
97
  'deploy',
@@ -175,4 +109,6 @@ module(KUBERNETES_MODULE, requires).config(() => {
175
109
  'upsertLoadBalancers',
176
110
  ],
177
111
  });
178
- });
112
+ }
113
+
114
+ registerKubernetesProvider();
@@ -2,10 +2,11 @@ import React from 'react';
2
2
  import { Dropdown, MenuItem } from 'react-bootstrap';
3
3
 
4
4
  import type { ILoadBalancerActionsProps } from '@spinnaker/core';
5
- import { AddEntityTagLinks, ModalInjector, robotToHuman, SETTINGS } from '@spinnaker/core';
5
+ import { AddEntityTagLinks, robotToHuman, SETTINGS, useModal } from '@spinnaker/core';
6
6
 
7
7
  import type { IKubernetesLoadBalancerView } from '../../interfaces';
8
8
  import { KubernetesManifestCommandBuilder } from '../../manifest';
9
+ import { DeleteModal } from '../../manifest/delete/DeleteModal';
9
10
  import { ManifestWizard } from '../../manifest/wizard/ManifestWizard';
10
11
 
11
12
  export interface IKubernetesLoadBalancerActionsProps extends ILoadBalancerActionsProps {
@@ -16,22 +17,7 @@ export function KubernetesLoadBalancerActions({ app, loadBalancer }: IKubernetes
16
17
  const showEntityTags = SETTINGS.feature && SETTINGS.feature.entityTags;
17
18
  const isEnabled = SETTINGS.kubernetesAdHocInfraWritesEnabled;
18
19
  const { manifest } = loadBalancer;
19
-
20
- const deleteLoadBalancer = (): void => {
21
- ModalInjector.modalService.open({
22
- templateUrl: require('../../manifest/delete/delete.html'),
23
- controller: 'kubernetesV2ManifestDeleteCtrl as ctrl',
24
- resolve: {
25
- coordinates: {
26
- name: loadBalancer.name,
27
- namespace: loadBalancer.namespace,
28
- account: loadBalancer.account,
29
- },
30
- application: app,
31
- manifestController: (): string => null,
32
- },
33
- });
34
- };
20
+ const deleteModal = useModal();
35
21
 
36
22
  const editLoadBalancer = (): void => {
37
23
  KubernetesManifestCommandBuilder.buildNewManifestCommand(
@@ -45,24 +31,33 @@ export function KubernetesLoadBalancerActions({ app, loadBalancer }: IKubernetes
45
31
  };
46
32
 
47
33
  return (
48
- <Dropdown className="dropdown" id="load-balancer-actions-dropdown">
49
- {isEnabled && (
50
- <Dropdown.Toggle className="btn btn-sm btn-primary dropdown-toggle">
51
- {robotToHuman(loadBalancer.kind)} Actions
52
- </Dropdown.Toggle>
53
- )}
54
- <Dropdown.Menu>
55
- <MenuItem onClick={deleteLoadBalancer}>Delete</MenuItem>
56
- <MenuItem onClick={editLoadBalancer}>Edit</MenuItem>
57
- {showEntityTags && (
58
- <AddEntityTagLinks
59
- component={loadBalancer}
60
- application={app}
61
- entityType="loadBalancer"
62
- onUpdate={() => app.loadBalancers.refresh()}
63
- />
34
+ <>
35
+ <Dropdown className="dropdown" id="load-balancer-actions-dropdown">
36
+ {isEnabled && (
37
+ <Dropdown.Toggle className="btn btn-sm btn-primary dropdown-toggle">
38
+ {robotToHuman(loadBalancer.kind)} Actions
39
+ </Dropdown.Toggle>
64
40
  )}
65
- </Dropdown.Menu>
66
- </Dropdown>
41
+ <Dropdown.Menu>
42
+ <MenuItem onClick={deleteModal.show}>Delete</MenuItem>
43
+ <MenuItem onClick={editLoadBalancer}>Edit</MenuItem>
44
+ {showEntityTags && (
45
+ <AddEntityTagLinks
46
+ component={loadBalancer}
47
+ application={app}
48
+ entityType="loadBalancer"
49
+ onUpdate={() => app.loadBalancers.refresh()}
50
+ />
51
+ )}
52
+ </Dropdown.Menu>
53
+ </Dropdown>
54
+ <DeleteModal
55
+ application={app}
56
+ resource={loadBalancer}
57
+ manifestController={null}
58
+ isOpen={deleteModal.open}
59
+ dismissModal={deleteModal.close}
60
+ />
61
+ </>
67
62
  );
68
63
  }