@spinnaker/kubernetes 0.0.0-main-2
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 +1663 -0
- package/LICENSE.txt +203 -0
- package/dist/help/kubernetes.help.d.ts +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6024 -0
- package/dist/index.js.map +1 -0
- package/dist/instance/details/details.controller.d.ts +1 -0
- package/dist/instance/index.d.ts +1 -0
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/infrastructure.types.d.ts +24 -0
- package/dist/kubernetes.module.d.ts +6 -0
- package/dist/loadBalancer/details/details.controller.d.ts +1 -0
- package/dist/loadBalancer/index.d.ts +1 -0
- package/dist/loadBalancer/transformer.d.ts +1 -0
- package/dist/manifest/IManifestCoordinates.d.ts +5 -0
- package/dist/manifest/ManifestImageDetails.d.ts +18 -0
- package/dist/manifest/ManifestKindSearch.d.ts +13 -0
- package/dist/manifest/ManifestLabels.d.ts +15 -0
- package/dist/manifest/ManifestQos.d.ts +15 -0
- package/dist/manifest/ManifestResources.d.ts +35 -0
- package/dist/manifest/ManifestSource.d.ts +4 -0
- package/dist/manifest/annotationCustomSections.component.d.ts +1 -0
- package/dist/manifest/artifact/artifact.component.d.ts +1 -0
- package/dist/manifest/delete/delete.controller.d.ts +12 -0
- package/dist/manifest/delete/deleteOptionsForm.component.d.ts +1 -0
- package/dist/manifest/editor/json/JsonEditor.d.ts +12 -0
- package/dist/manifest/editor/json/jsonEditor.component.d.ts +1 -0
- package/dist/manifest/index.d.ts +10 -0
- package/dist/manifest/manifest.service.d.ts +25 -0
- package/dist/manifest/manifestCommandBuilder.service.d.ts +30 -0
- package/dist/manifest/manifestEvents.component.d.ts +1 -0
- package/dist/manifest/manifestImageDetails.component.d.ts +1 -0
- package/dist/manifest/manifestLabels.component.d.ts +1 -0
- package/dist/manifest/manifestQos.component.d.ts +1 -0
- package/dist/manifest/manifestResources.component.d.ts +1 -0
- package/dist/manifest/rollout/RollingRestart.d.ts +1 -0
- package/dist/manifest/rollout/pause.controller.d.ts +1 -0
- package/dist/manifest/rollout/resume.controller.d.ts +1 -0
- package/dist/manifest/rollout/undo.controller.d.ts +1 -0
- package/dist/manifest/scale/ScaleSettingsForm.d.ts +10 -0
- package/dist/manifest/scale/scale.controller.d.ts +8 -0
- package/dist/manifest/scale/scaleSettingsForm.component.d.ts +1 -0
- package/dist/manifest/selector/IManifestLabelSelector.d.ts +9 -0
- package/dist/manifest/selector/IManifestSelector.d.ts +30 -0
- package/dist/manifest/selector/ManifestSelector.d.ts +46 -0
- package/dist/manifest/selector/labelEditor/LabelEditor.d.ts +15 -0
- package/dist/manifest/selector/selector.component.d.ts +1 -0
- package/dist/manifest/status/ManifestCondition.d.ts +13 -0
- package/dist/manifest/status/condition.component.d.ts +1 -0
- package/dist/manifest/status/status.component.d.ts +1 -0
- package/dist/manifest/traffic/ManifestTrafficService.d.ts +12 -0
- package/dist/manifest/wizard/BasicSettings.d.ts +17 -0
- package/dist/manifest/wizard/ManifestEntry.d.ts +16 -0
- package/dist/manifest/wizard/ManifestWizard.d.ts +22 -0
- package/dist/pipelines/stages/ManifestCoordinates.d.ts +31 -0
- package/dist/pipelines/stages/ManifestExecutionDetails.d.ts +69 -0
- package/dist/pipelines/stages/deleteManifest/DeleteManifestOptionsForm.d.ts +18 -0
- package/dist/pipelines/stages/deleteManifest/DeleteManifestStageConfig.d.ts +14 -0
- package/dist/pipelines/stages/deleteManifest/deleteManifestStage.d.ts +1 -0
- package/dist/pipelines/stages/deployManifest/CopyFromTemplateButton.d.ts +15 -0
- package/dist/pipelines/stages/deployManifest/DeployManifestStageConfig.d.ts +15 -0
- package/dist/pipelines/stages/deployManifest/DeployManifestStageForm.d.ts +31 -0
- package/dist/pipelines/stages/deployManifest/ManifestBindArtifactsSelector.d.ts +17 -0
- package/dist/pipelines/stages/deployManifest/ManifestCopier.d.ts +36 -0
- package/dist/pipelines/stages/deployManifest/ManifestDeploymentOptions.d.ts +34 -0
- package/dist/pipelines/stages/deployManifest/NamespaceSelector.d.ts +16 -0
- package/dist/pipelines/stages/deployManifest/deployManifest.validator.d.ts +2 -0
- package/dist/pipelines/stages/deployManifest/deployManifestStage.d.ts +1 -0
- package/dist/pipelines/stages/deployManifest/manifestStatus/DeployStatus.d.ts +23 -0
- package/dist/pipelines/stages/deployManifest/manifestStatus/DeployStatusPills.d.ts +8 -0
- package/dist/pipelines/stages/deployManifest/manifestStatus/ManifestDetailsLink.d.ts +20 -0
- package/dist/pipelines/stages/deployManifest/manifestStatus/ManifestEvents.d.ts +9 -0
- package/dist/pipelines/stages/deployManifest/manifestStatus/ManifestStatus.d.ts +8 -0
- package/dist/pipelines/stages/findArtifactsFromResource/FindArtifactsFromResourceConfig.d.ts +3 -0
- package/dist/pipelines/stages/findArtifactsFromResource/FindArtifactsFromResourceStageForm.d.ts +7 -0
- package/dist/pipelines/stages/findArtifactsFromResource/findArtifactsFromResourceStage.d.ts +1 -0
- package/dist/pipelines/stages/index.d.ts +8 -0
- package/dist/pipelines/stages/patchManifest/PatchManifestOptionsForm.d.ts +8 -0
- package/dist/pipelines/stages/patchManifest/PatchManifestStageConfig.d.ts +7 -0
- package/dist/pipelines/stages/patchManifest/PatchManifestStageForm.d.ts +21 -0
- package/dist/pipelines/stages/patchManifest/patchManifestStage.d.ts +4 -0
- package/dist/pipelines/stages/rolloutRestartManifest/RolloutRestartManifestStageConfig.d.ts +13 -0
- package/dist/pipelines/stages/rolloutRestartManifest/rolloutRestartManifestStage.d.ts +4 -0
- package/dist/pipelines/stages/runJob/KubernetesV2RunJobStageConfig.d.ts +31 -0
- package/dist/pipelines/stages/runJob/RunJobExecutionDetails.d.ts +7 -0
- package/dist/pipelines/stages/runJob/runJobStage.d.ts +1 -0
- package/dist/pipelines/stages/scaleManifest/ScaleManifestConfig.d.ts +3 -0
- package/dist/pipelines/stages/scaleManifest/ScaleManifestStageForm.d.ts +7 -0
- package/dist/pipelines/stages/scaleManifest/scaleManifestStage.d.ts +1 -0
- package/dist/pipelines/stages/traffic/ManifestTrafficStageConfig.d.ts +11 -0
- package/dist/pipelines/stages/traffic/disableManifest.stage.d.ts +1 -0
- package/dist/pipelines/stages/traffic/enableManifest.stage.d.ts +1 -0
- package/dist/pipelines/stages/undoRolloutManifest/UndoRolloutManifestConfig.d.ts +3 -0
- package/dist/pipelines/stages/undoRolloutManifest/UndoRolloutManifestStageForm.d.ts +7 -0
- package/dist/pipelines/stages/undoRolloutManifest/undoRolloutManifestStage.d.ts +1 -0
- package/dist/pipelines/stages/validators/manifestSelectorValidators.d.ts +2 -0
- package/dist/pipelines/validation/manifestSelector.validator.d.ts +8 -0
- package/dist/rawResource/component/K8sResources.d.ts +25 -0
- package/dist/rawResource/component/K8sResourcesFilters.d.ts +20 -0
- package/dist/rawResource/component/RawResourceUtils.d.ts +5 -0
- package/dist/rawResource/component/group/RawResouceGroup.d.ts +15 -0
- package/dist/rawResource/component/group/RawResource.d.ts +12 -0
- package/dist/rawResource/component/group/RawResourceDetails.d.ts +32 -0
- package/dist/rawResource/component/group/RawResourceGroups.d.ts +14 -0
- package/dist/rawResource/controller/FiltersPubSub.d.ts +12 -0
- package/dist/rawResource/index.d.ts +1 -0
- package/dist/rawResource/model/resource.d.ts +17 -0
- package/dist/rawResource/rawResource.dataSource.d.ts +2 -0
- package/dist/rawResource/rawResource.module.d.ts +1 -0
- package/dist/rawResource/rawResource.states.d.ts +6 -0
- package/dist/resources/ResourceDetails.d.ts +17 -0
- package/dist/resources/resources.state.d.ts +7 -0
- package/dist/rolloutStrategy/bluegreen.strategy.d.ts +2 -0
- package/dist/rolloutStrategy/highlander.strategy.d.ts +2 -0
- package/dist/rolloutStrategy/index.d.ts +1 -0
- package/dist/rolloutStrategy/none.strategy.d.ts +2 -0
- package/dist/rolloutStrategy/redblack.strategy.d.ts +2 -0
- package/dist/securityGroup/details/details.controller.d.ts +1 -0
- package/dist/securityGroup/index.d.ts +1 -0
- package/dist/securityGroup/securityGroup.reader.d.ts +4 -0
- package/dist/securityGroup/transformer.d.ts +1 -0
- package/dist/serverGroup/details/details.controller.d.ts +1 -0
- package/dist/serverGroup/details/resize/resize.controller.d.ts +1 -0
- package/dist/serverGroup/index.d.ts +4 -0
- package/dist/serverGroup/serverGroupCommandBuilder.service.d.ts +6 -0
- package/dist/serverGroup/serverGroupTransformer.service.d.ts +6 -0
- package/dist/serverGroupManager/details/details.controller.d.ts +1 -0
- package/dist/serverGroupManager/index.d.ts +1 -0
- package/dist/validation/applicationName.validator.d.ts +9 -0
- package/package.json +58 -0
- package/src/help/kubernetes.help.ts +236 -0
- package/src/index.ts +7 -0
- package/src/instance/details/details.controller.ts +186 -0
- package/src/instance/details/details.html +80 -0
- package/src/instance/index.ts +1 -0
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/infrastructure.types.ts +35 -0
- package/src/kubernetes.module.ts +144 -0
- package/src/loadBalancer/details/details.controller.ts +101 -0
- package/src/loadBalancer/details/details.html +187 -0
- package/src/loadBalancer/index.ts +1 -0
- package/src/loadBalancer/transformer.ts +60 -0
- package/src/logo/kubernetes.icon.svg +102 -0
- package/src/logo/kubernetes.logo.less +6 -0
- package/src/logo/kubernetes.logo.svg +1 -0
- package/src/manifest/IManifestCoordinates.ts +5 -0
- package/src/manifest/ManifestImageDetails.spec.tsx +76 -0
- package/src/manifest/ManifestImageDetails.tsx +64 -0
- package/src/manifest/ManifestKindSearch.tsx +31 -0
- package/src/manifest/ManifestLabels.tsx +31 -0
- package/src/manifest/ManifestQos.tsx +68 -0
- package/src/manifest/ManifestResources.tsx +69 -0
- package/src/manifest/ManifestSource.ts +4 -0
- package/src/manifest/annotationCustomSections.component.ts +114 -0
- package/src/manifest/artifact/artifact.component.ts +23 -0
- package/src/manifest/delete/delete.controller.ts +80 -0
- package/src/manifest/delete/delete.html +42 -0
- package/src/manifest/delete/deleteOptionsForm.component.ts +52 -0
- package/src/manifest/editor/json/JsonEditor.tsx +56 -0
- package/src/manifest/editor/json/jsonEditor.component.ts +12 -0
- package/src/manifest/index.ts +10 -0
- package/src/manifest/manifest.service.ts +90 -0
- package/src/manifest/manifestCommandBuilder.service.ts +126 -0
- package/src/manifest/manifestEvents.component.ts +12 -0
- package/src/manifest/manifestImageDetails.component.ts +12 -0
- package/src/manifest/manifestLabels.component.ts +12 -0
- package/src/manifest/manifestLabels.less +3 -0
- package/src/manifest/manifestQos.component.ts +12 -0
- package/src/manifest/manifestResources.component.ts +12 -0
- package/src/manifest/rollout/RollingRestart.tsx +54 -0
- package/src/manifest/rollout/pause.controller.ts +66 -0
- package/src/manifest/rollout/pause.html +28 -0
- package/src/manifest/rollout/resume.controller.ts +66 -0
- package/src/manifest/rollout/resume.html +28 -0
- package/src/manifest/rollout/undo.controller.ts +74 -0
- package/src/manifest/rollout/undo.html +44 -0
- package/src/manifest/scale/ScaleSettingsForm.tsx +43 -0
- package/src/manifest/scale/scale.controller.ts +75 -0
- package/src/manifest/scale/scale.html +32 -0
- package/src/manifest/scale/scaleSettingsForm.component.ts +11 -0
- package/src/manifest/selector/IManifestLabelSelector.ts +19 -0
- package/src/manifest/selector/IManifestSelector.ts +64 -0
- package/src/manifest/selector/ManifestSelector.spec.tsx +414 -0
- package/src/manifest/selector/ManifestSelector.tsx +424 -0
- package/src/manifest/selector/labelEditor/LabelEditor.spec.tsx +81 -0
- package/src/manifest/selector/labelEditor/LabelEditor.tsx +126 -0
- package/src/manifest/selector/labelEditor/labelEditor.less +3 -0
- package/src/manifest/selector/selector.component.ts +17 -0
- package/src/manifest/status/ManifestCondition.tsx +32 -0
- package/src/manifest/status/condition.component.ts +12 -0
- package/src/manifest/status/status.component.ts +36 -0
- package/src/manifest/traffic/ManifestTrafficService.spec.ts +30 -0
- package/src/manifest/traffic/ManifestTrafficService.ts +67 -0
- package/src/manifest/wizard/BasicSettings.tsx +57 -0
- package/src/manifest/wizard/ManifestEntry.tsx +46 -0
- package/src/manifest/wizard/ManifestWizard.tsx +94 -0
- package/src/pipelines/stages/ManifestCoordinates.spec.tsx +90 -0
- package/src/pipelines/stages/ManifestCoordinates.tsx +128 -0
- package/src/pipelines/stages/ManifestExecutionDetails.tsx +58 -0
- package/src/pipelines/stages/deleteManifest/DeleteManifestOptionsForm.spec.tsx +85 -0
- package/src/pipelines/stages/deleteManifest/DeleteManifestOptionsForm.tsx +87 -0
- package/src/pipelines/stages/deleteManifest/DeleteManifestStageConfig.tsx +62 -0
- package/src/pipelines/stages/deleteManifest/deleteManifestOptionsForm.less +9 -0
- package/src/pipelines/stages/deleteManifest/deleteManifestStage.ts +21 -0
- package/src/pipelines/stages/deployManifest/CopyFromTemplateButton.tsx +45 -0
- package/src/pipelines/stages/deployManifest/DeployManifestStageConfig.tsx +77 -0
- package/src/pipelines/stages/deployManifest/DeployManifestStageForm.tsx +265 -0
- package/src/pipelines/stages/deployManifest/ManifestBindArtifactsSelector.tsx +69 -0
- package/src/pipelines/stages/deployManifest/ManifestCopier.spec.ts +110 -0
- package/src/pipelines/stages/deployManifest/ManifestCopier.tsx +222 -0
- package/src/pipelines/stages/deployManifest/ManifestDeploymentOptions.spec.tsx +75 -0
- package/src/pipelines/stages/deployManifest/ManifestDeploymentOptions.tsx +203 -0
- package/src/pipelines/stages/deployManifest/NamespaceSelector.tsx +40 -0
- package/src/pipelines/stages/deployManifest/deployManifest.validator.ts +38 -0
- package/src/pipelines/stages/deployManifest/deployManifestStage.ts +28 -0
- package/src/pipelines/stages/deployManifest/manifestStatus/DeployStatus.less +11 -0
- package/src/pipelines/stages/deployManifest/manifestStatus/DeployStatus.tsx +120 -0
- package/src/pipelines/stages/deployManifest/manifestStatus/DeployStatusPills.tsx +47 -0
- package/src/pipelines/stages/deployManifest/manifestStatus/ManifestDetailsLink.tsx +92 -0
- package/src/pipelines/stages/deployManifest/manifestStatus/ManifestEvents.tsx +87 -0
- package/src/pipelines/stages/deployManifest/manifestStatus/ManifestStatus.less +24 -0
- package/src/pipelines/stages/deployManifest/manifestStatus/ManifestStatus.tsx +46 -0
- package/src/pipelines/stages/findArtifactsFromResource/FindArtifactsFromResourceConfig.tsx +35 -0
- package/src/pipelines/stages/findArtifactsFromResource/FindArtifactsFromResourceStageForm.tsx +37 -0
- package/src/pipelines/stages/findArtifactsFromResource/findArtifactsFromResourceStage.ts +21 -0
- package/src/pipelines/stages/index.ts +8 -0
- package/src/pipelines/stages/patchManifest/PatchManifestOptionsForm.tsx +35 -0
- package/src/pipelines/stages/patchManifest/PatchManifestStageConfig.tsx +57 -0
- package/src/pipelines/stages/patchManifest/PatchManifestStageForm.tsx +157 -0
- package/src/pipelines/stages/patchManifest/patchManifestStage.ts +30 -0
- package/src/pipelines/stages/rolloutRestartManifest/RolloutRestartManifestStageConfig.tsx +46 -0
- package/src/pipelines/stages/rolloutRestartManifest/rolloutRestartManifestStage.ts +20 -0
- package/src/pipelines/stages/runJob/KubernetesV2RunJobStageConfig.tsx +242 -0
- package/src/pipelines/stages/runJob/RunJobExecutionDetails.tsx +67 -0
- package/src/pipelines/stages/runJob/runJobStage.ts +39 -0
- package/src/pipelines/stages/scaleManifest/ScaleManifestConfig.tsx +38 -0
- package/src/pipelines/stages/scaleManifest/ScaleManifestStageForm.tsx +46 -0
- package/src/pipelines/stages/scaleManifest/scaleManifestStage.ts +24 -0
- package/src/pipelines/stages/traffic/ManifestTrafficStageConfig.tsx +44 -0
- package/src/pipelines/stages/traffic/disableManifest.stage.ts +26 -0
- package/src/pipelines/stages/traffic/enableManifest.stage.ts +26 -0
- package/src/pipelines/stages/undoRolloutManifest/UndoRolloutManifestConfig.tsx +37 -0
- package/src/pipelines/stages/undoRolloutManifest/UndoRolloutManifestStageForm.tsx +60 -0
- package/src/pipelines/stages/undoRolloutManifest/undoRolloutManifestStage.ts +21 -0
- package/src/pipelines/stages/validators/manifestSelectorValidators.ts +43 -0
- package/src/pipelines/validation/manifestSelector.validator.ts +36 -0
- package/src/rawResource/component/K8sResources.less +9 -0
- package/src/rawResource/component/K8sResources.tsx +112 -0
- package/src/rawResource/component/K8sResourcesFilters.tsx +112 -0
- package/src/rawResource/component/RawResourceUtils.ts +19 -0
- package/src/rawResource/component/group/RawResouceGroup.tsx +41 -0
- package/src/rawResource/component/group/RawResource.less +79 -0
- package/src/rawResource/component/group/RawResource.tsx +51 -0
- package/src/rawResource/component/group/RawResourceDetails.tsx +236 -0
- package/src/rawResource/component/group/RawResourceGroups.tsx +53 -0
- package/src/rawResource/controller/FiltersPubSub.ts +35 -0
- package/src/rawResource/index.ts +1 -0
- package/src/rawResource/model/resource.ts +18 -0
- package/src/rawResource/rawResource.dataSource.ts +39 -0
- package/src/rawResource/rawResource.module.ts +8 -0
- package/src/rawResource/rawResource.states.ts +64 -0
- package/src/resources/ResourceDetails.tsx +121 -0
- package/src/resources/resources.state.ts +45 -0
- package/src/rolloutStrategy/bluegreen.strategy.ts +7 -0
- package/src/rolloutStrategy/highlander.strategy.ts +7 -0
- package/src/rolloutStrategy/index.ts +6 -0
- package/src/rolloutStrategy/none.strategy.ts +8 -0
- package/src/rolloutStrategy/redblack.strategy.ts +7 -0
- package/src/securityGroup/details/details.controller.ts +118 -0
- package/src/securityGroup/details/details.html +91 -0
- package/src/securityGroup/index.ts +1 -0
- package/src/securityGroup/securityGroup.reader.ts +11 -0
- package/src/securityGroup/transformer.ts +19 -0
- package/src/serverGroup/details/details.controller.ts +207 -0
- package/src/serverGroup/details/details.html +153 -0
- package/src/serverGroup/details/resize/resize.controller.ts +73 -0
- package/src/serverGroup/details/resize/resize.html +57 -0
- package/src/serverGroup/index.ts +4 -0
- package/src/serverGroup/serverGroupCommandBuilder.service.ts +18 -0
- package/src/serverGroup/serverGroupTransformer.service.spec.ts +67 -0
- package/src/serverGroup/serverGroupTransformer.service.ts +34 -0
- package/src/serverGroupManager/details/details.controller.ts +191 -0
- package/src/serverGroupManager/details/details.html +136 -0
- package/src/serverGroupManager/index.ts +1 -0
- package/src/validation/applicationName.validator.spec.ts +19 -0
- package/src/validation/applicationName.validator.ts +44 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { IArtifact, IExpectedArtifact, IPipeline, IStage } from '@spinnaker/core';
|
|
4
|
+
import { ArtifactTypePatterns, StageArtifactSelector } from '@spinnaker/core';
|
|
5
|
+
|
|
6
|
+
export interface IManifestBindArtifact {
|
|
7
|
+
expectedArtifactId?: string;
|
|
8
|
+
artifact?: IArtifact;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface IManifestBindArtifactsSelectorProps {
|
|
12
|
+
pipeline: IPipeline;
|
|
13
|
+
stage: IStage;
|
|
14
|
+
bindings?: IManifestBindArtifact[];
|
|
15
|
+
onChangeBindings: (_: IManifestBindArtifact[]) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ManifestBindArtifactsSelector extends React.Component<IManifestBindArtifactsSelectorProps> {
|
|
19
|
+
private onChangeBinding = (index: number, binding: IManifestBindArtifact) => {
|
|
20
|
+
const bindings = (this.props.bindings || []).slice(0);
|
|
21
|
+
bindings[index] = binding;
|
|
22
|
+
this.props.onChangeBindings(bindings);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
private onRemoveBinding = (index: number) => {
|
|
26
|
+
const bindings = (this.props.bindings || []).slice(0);
|
|
27
|
+
bindings.splice(index, 1);
|
|
28
|
+
this.props.onChangeBindings(bindings);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
public render() {
|
|
32
|
+
const { stage, pipeline, bindings } = this.props;
|
|
33
|
+
|
|
34
|
+
const renderSelect = (i: number, binding?: IManifestBindArtifact) => {
|
|
35
|
+
const key = (!binding && 'new') || binding.expectedArtifactId || (binding.artifact && binding.artifact.id);
|
|
36
|
+
return (
|
|
37
|
+
<div className="row" key={key}>
|
|
38
|
+
<div className="col-md-10">
|
|
39
|
+
<StageArtifactSelector
|
|
40
|
+
pipeline={pipeline}
|
|
41
|
+
stage={stage}
|
|
42
|
+
expectedArtifactId={binding && binding.expectedArtifactId}
|
|
43
|
+
artifact={!!binding && binding.artifact}
|
|
44
|
+
onArtifactEdited={(artifact: IArtifact) => this.onChangeBinding(i, { artifact: artifact })}
|
|
45
|
+
onExpectedArtifactSelected={(expectedArtifact: IExpectedArtifact) =>
|
|
46
|
+
this.onChangeBinding(i, { expectedArtifactId: expectedArtifact.id })
|
|
47
|
+
}
|
|
48
|
+
excludedArtifactIds={bindings.map((b) => b.expectedArtifactId)}
|
|
49
|
+
excludedArtifactTypePatterns={[ArtifactTypePatterns.FRONT50_PIPELINE_TEMPLATE]}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
{binding && (
|
|
53
|
+
<div className="col-md-2">
|
|
54
|
+
<a className="glyphicon glyphicon-trash" onClick={() => this.onRemoveBinding(i)} />
|
|
55
|
+
</div>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
const renderSelectEditable = (binding: IManifestBindArtifact, i: number) => renderSelect(i, binding);
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<>
|
|
64
|
+
{bindings.map(renderSelectEditable)}
|
|
65
|
+
{renderSelect(bindings.length)}
|
|
66
|
+
</>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { IQService, IScope } from 'angular';
|
|
2
|
+
import { mock } from 'angular';
|
|
3
|
+
|
|
4
|
+
import type { Application } from '@spinnaker/core';
|
|
5
|
+
import { ApplicationModelBuilder, noop } from '@spinnaker/core';
|
|
6
|
+
import { ManifestCopier } from './ManifestCopier';
|
|
7
|
+
|
|
8
|
+
describe('<ManifestCopier />', () => {
|
|
9
|
+
let application: Application;
|
|
10
|
+
|
|
11
|
+
beforeEach(
|
|
12
|
+
mock.inject(($q: IQService, $rootScope: IScope) => {
|
|
13
|
+
const $scope = $rootScope.$new();
|
|
14
|
+
// The application model implicitly depends on a bunch of Angular things, which is why
|
|
15
|
+
// we need the Angular mock environment (even though we're testing a React component).
|
|
16
|
+
application = ApplicationModelBuilder.createApplicationForTests(
|
|
17
|
+
'app',
|
|
18
|
+
{
|
|
19
|
+
key: 'serverGroups',
|
|
20
|
+
loader: () =>
|
|
21
|
+
$q.resolve([
|
|
22
|
+
// Replica sets in same cluster, no manager.
|
|
23
|
+
{
|
|
24
|
+
name: 'replicaSet my-replicaSet-v002',
|
|
25
|
+
region: 'default',
|
|
26
|
+
category: 'serverGroup',
|
|
27
|
+
account: 'my-k8s-account',
|
|
28
|
+
cloudProvider: 'kubernetes',
|
|
29
|
+
cluster: 'replicaSet my-replicaSet',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'replicaSet my-replicaSet-v001',
|
|
33
|
+
region: 'default',
|
|
34
|
+
category: 'serverGroup',
|
|
35
|
+
account: 'my-k8s-account',
|
|
36
|
+
cloudProvider: 'kubernetes',
|
|
37
|
+
cluster: 'replicaSet my-replicaSet',
|
|
38
|
+
},
|
|
39
|
+
// Replica set managed by deployment.
|
|
40
|
+
{
|
|
41
|
+
name: 'replicaSet my-managed-replicaSet-v001',
|
|
42
|
+
region: 'default',
|
|
43
|
+
category: 'serverGroup',
|
|
44
|
+
account: 'my-k8s-account',
|
|
45
|
+
cloudProvider: 'kubernetes',
|
|
46
|
+
cluster: 'deployment my-deployment',
|
|
47
|
+
serverGroupManagers: [{ name: 'deployment my-deployment' }],
|
|
48
|
+
},
|
|
49
|
+
]),
|
|
50
|
+
onLoad: (_app: Application, data: any) => $q.resolve(data),
|
|
51
|
+
defaultData: [],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
key: 'serverGroupManagers',
|
|
55
|
+
loader: () =>
|
|
56
|
+
$q.resolve([
|
|
57
|
+
{
|
|
58
|
+
name: 'deployment my-deployment',
|
|
59
|
+
region: 'default',
|
|
60
|
+
account: 'my-k8s-account',
|
|
61
|
+
cloudProvider: 'kubernetes',
|
|
62
|
+
},
|
|
63
|
+
]),
|
|
64
|
+
onLoad: (_app: Application, data: any) => $q.resolve(data),
|
|
65
|
+
defaultData: [],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
key: 'securityGroups',
|
|
69
|
+
loader: () => $q.resolve([]),
|
|
70
|
+
onLoad: (_app: Application, data: any) => $q.resolve(data),
|
|
71
|
+
defaultData: [],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
key: 'loadBalancers',
|
|
75
|
+
loader: () => $q.resolve([]),
|
|
76
|
+
onLoad: (_app: Application, data: any) => $q.resolve(data),
|
|
77
|
+
defaultData: [],
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
application.refresh();
|
|
81
|
+
$scope.$digest();
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
describe('dropdown grouping & ordering', () => {
|
|
86
|
+
it('sorts deployments to the top of the list', () => {
|
|
87
|
+
const state = ManifestCopier.getState(buildProps(application));
|
|
88
|
+
expect(state.manifests.map((manifest) => manifest.name)[0]).toEqual('my-deployment');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('only includes the most recent versioned resource', () => {
|
|
92
|
+
const state = ManifestCopier.getState(buildProps(application));
|
|
93
|
+
expect(state.manifests.map((manifest) => manifest.name)).toContain('my-replicaSet-v002');
|
|
94
|
+
expect(state.manifests.map((manifest) => manifest.name)).not.toContain('my-replicaSet-v001');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('does not include managed server groups', () => {
|
|
98
|
+
const state = ManifestCopier.getState(buildProps(application));
|
|
99
|
+
expect(state.manifests.map((manifest) => manifest.name)).not.toContain('my-managed-replicaSet-v001');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const buildProps = (application: Application) => ({
|
|
105
|
+
application,
|
|
106
|
+
cloudProvider: 'kubernetes',
|
|
107
|
+
onDismiss: noop,
|
|
108
|
+
onManifestSelected: noop,
|
|
109
|
+
show: true,
|
|
110
|
+
});
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { groupBy, sortBy } from 'lodash';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Modal } from 'react-bootstrap';
|
|
4
|
+
import type { Option } from 'react-select';
|
|
5
|
+
import { from as observableFrom, Subject } from 'rxjs';
|
|
6
|
+
import { takeUntil } from 'rxjs/operators';
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
Application,
|
|
10
|
+
ILoadBalancer,
|
|
11
|
+
IManifest,
|
|
12
|
+
ISecurityGroup,
|
|
13
|
+
IServerGroup,
|
|
14
|
+
IServerGroupManager,
|
|
15
|
+
} from '@spinnaker/core';
|
|
16
|
+
import { AccountTag, ManifestReader, ModalClose, noop, robotToHuman, TetheredSelect } from '@spinnaker/core';
|
|
17
|
+
|
|
18
|
+
export interface IManifestCopierProps {
|
|
19
|
+
application: Application;
|
|
20
|
+
cloudProvider: string;
|
|
21
|
+
show: boolean;
|
|
22
|
+
onDismiss: () => void;
|
|
23
|
+
onManifestSelected: (manifest: IManifest) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface IManifestCopierState {
|
|
27
|
+
selectedManifest: IManifestOption;
|
|
28
|
+
manifests: IManifestOption[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface IManifestOption {
|
|
32
|
+
account: string;
|
|
33
|
+
location: string;
|
|
34
|
+
name: string;
|
|
35
|
+
kind: string;
|
|
36
|
+
data: any;
|
|
37
|
+
key: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const LAST_APPLIED_CONFIGURATION = 'kubectl.kubernetes.io/last-applied-configuration';
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* A modal that allows a user to copy a running Kubernetes resource.
|
|
44
|
+
**/
|
|
45
|
+
export class ManifestCopier extends React.Component<IManifestCopierProps, IManifestCopierState> {
|
|
46
|
+
private destroy$ = new Subject();
|
|
47
|
+
|
|
48
|
+
public static getState = (props: IManifestCopierProps) => {
|
|
49
|
+
let manifests: IManifestOption[] = [];
|
|
50
|
+
|
|
51
|
+
const serverGroups: IServerGroup[] = props.application.getDataSource('serverGroups').data.filter(
|
|
52
|
+
(s: IServerGroup) =>
|
|
53
|
+
s.cloudProvider === props.cloudProvider &&
|
|
54
|
+
s.category === 'serverGroup' &&
|
|
55
|
+
// Don't include managed server groups - just the manager (see below).
|
|
56
|
+
!(s.serverGroupManagers || []).length,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const grouped = groupBy(serverGroups, (serverGroup) =>
|
|
60
|
+
[serverGroup.cluster, serverGroup.account, serverGroup.region].join(':'),
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
Object.keys(grouped).forEach((key) => {
|
|
64
|
+
// Only include the most recent server group in a cluster (e.g., if v001 and v002 exist, only include v002).
|
|
65
|
+
const latest = sortBy(grouped[key], 'name').pop();
|
|
66
|
+
const [kind, name] = latest.name.split(' ');
|
|
67
|
+
manifests.push({
|
|
68
|
+
account: latest.account,
|
|
69
|
+
location: latest.region,
|
|
70
|
+
name: name,
|
|
71
|
+
kind: kind,
|
|
72
|
+
data: latest,
|
|
73
|
+
key: [latest.account, latest.region, latest.name].join(':'),
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const serverGroupManagers: IServerGroupManager[] = props.application.getDataSource('serverGroupManagers').data;
|
|
78
|
+
const loadBalancers: ILoadBalancer[] = props.application.getDataSource('loadBalancers').data;
|
|
79
|
+
const firewalls: ISecurityGroup[] = props.application.getDataSource('securityGroups').data;
|
|
80
|
+
|
|
81
|
+
[...serverGroupManagers, ...loadBalancers, ...firewalls]
|
|
82
|
+
.filter(
|
|
83
|
+
(manifest: IServerGroupManager | ILoadBalancer | ISecurityGroup) =>
|
|
84
|
+
manifest.cloudProvider === props.cloudProvider,
|
|
85
|
+
)
|
|
86
|
+
.forEach((manifest: IServerGroupManager | ILoadBalancer | ISecurityGroup) => {
|
|
87
|
+
const [kind, name] = manifest.name.split(' ');
|
|
88
|
+
manifests.push({
|
|
89
|
+
account: manifest.account,
|
|
90
|
+
location: manifest.region,
|
|
91
|
+
name,
|
|
92
|
+
kind,
|
|
93
|
+
data: manifest,
|
|
94
|
+
key: [manifest.account, manifest.region, manifest.name].join(':'),
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
manifests = sortBy(
|
|
99
|
+
manifests,
|
|
100
|
+
(manifest) => {
|
|
101
|
+
// TODO(dpeach): Could load an account here, then use the spinnakerKind -> kubernetesKind map to
|
|
102
|
+
// construct a more maintainable ordering.
|
|
103
|
+
const order = [
|
|
104
|
+
// server group manager
|
|
105
|
+
'deployment',
|
|
106
|
+
// server group
|
|
107
|
+
'replicaSet',
|
|
108
|
+
'statefulSet',
|
|
109
|
+
'daemonSet',
|
|
110
|
+
'jobs',
|
|
111
|
+
'cronJob',
|
|
112
|
+
// load balancer
|
|
113
|
+
'service',
|
|
114
|
+
'ingress',
|
|
115
|
+
// firewall
|
|
116
|
+
'networkPolicy',
|
|
117
|
+
];
|
|
118
|
+
return order.includes(manifest.kind) ? order.indexOf(manifest.kind) : Number.MAX_SAFE_INTEGER;
|
|
119
|
+
},
|
|
120
|
+
['kind', 'name', 'location'],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
selectedManifest: manifests.length ? manifests[0] : null,
|
|
125
|
+
manifests,
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
constructor(props: IManifestCopierProps) {
|
|
130
|
+
super(props);
|
|
131
|
+
this.state = ManifestCopier.getState(props);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public useManifest = (): void => {
|
|
135
|
+
const {
|
|
136
|
+
data: { account, region, name },
|
|
137
|
+
} = this.state.selectedManifest;
|
|
138
|
+
observableFrom(ManifestReader.getManifest(account, region, name))
|
|
139
|
+
.pipe(takeUntil(this.destroy$))
|
|
140
|
+
.subscribe((manifest: IManifest) => {
|
|
141
|
+
this.props.onManifestSelected(JSON.parse(manifest.manifest.metadata.annotations[LAST_APPLIED_CONFIGURATION]));
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
public manifestChanged = (option: Option) => {
|
|
146
|
+
this.setState({ selectedManifest: option as IManifestOption });
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
public componentWillUnmount() {
|
|
150
|
+
this.destroy$.next();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public render() {
|
|
154
|
+
const { selectedManifest, manifests } = this.state;
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<Modal show={this.props.show} onHide={noop}>
|
|
158
|
+
<ModalClose dismiss={this.props.onDismiss} />
|
|
159
|
+
<div>
|
|
160
|
+
<Modal.Header>
|
|
161
|
+
<Modal.Title>Copy Manifest</Modal.Title>
|
|
162
|
+
</Modal.Header>
|
|
163
|
+
<Modal.Body>
|
|
164
|
+
<form className="form-horizontal">
|
|
165
|
+
<div className="form-group">
|
|
166
|
+
<div className="col-md-4 col-md-offset-1 sm-label-left">
|
|
167
|
+
<b>Copy manifest from</b>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
<div className="form-group">
|
|
171
|
+
<div className="col-md-10 col-md-offset-1">
|
|
172
|
+
<TetheredSelect
|
|
173
|
+
value={selectedManifest ? selectedManifest.key : null}
|
|
174
|
+
placeholder="Select..."
|
|
175
|
+
valueRenderer={this.manifestValueRenderer}
|
|
176
|
+
optionRenderer={this.manifestOptionRenderer}
|
|
177
|
+
options={manifests}
|
|
178
|
+
valueKey="key"
|
|
179
|
+
onChange={this.manifestChanged}
|
|
180
|
+
clearable={false}
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</form>
|
|
185
|
+
</Modal.Body>
|
|
186
|
+
<div className="modal-footer">
|
|
187
|
+
{selectedManifest && (
|
|
188
|
+
<button className="btn btn-primary" onClick={this.useManifest}>
|
|
189
|
+
<span>Use this manifest</span>
|
|
190
|
+
<span className="glyphicon glyphicon-chevron-right" />
|
|
191
|
+
</button>
|
|
192
|
+
)}
|
|
193
|
+
{!selectedManifest && (
|
|
194
|
+
<button className="btn" onClick={this.props.onDismiss}>
|
|
195
|
+
<span>Cancel</span>
|
|
196
|
+
</button>
|
|
197
|
+
)}
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</Modal>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private manifestValueRenderer = (option: Option) => {
|
|
205
|
+
const kindLabel = robotToHuman(option.kind).trim();
|
|
206
|
+
return (
|
|
207
|
+
<span>
|
|
208
|
+
<AccountTag account={option.account} />
|
|
209
|
+
{option.data && <span> {option.name}</span>} ({kindLabel} in {option.location})
|
|
210
|
+
</span>
|
|
211
|
+
);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
private manifestOptionRenderer = (option: Option) => {
|
|
215
|
+
const kindLabel = robotToHuman(option.kind).trim();
|
|
216
|
+
return (
|
|
217
|
+
<h5>
|
|
218
|
+
<AccountTag account={option.account} /> {option.name} ({kindLabel} in {option.location})
|
|
219
|
+
</h5>
|
|
220
|
+
);
|
|
221
|
+
};
|
|
222
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { StageConfigField } from '@spinnaker/core';
|
|
5
|
+
|
|
6
|
+
import type { IManifestDeploymentOptionsProps } from './ManifestDeploymentOptions';
|
|
7
|
+
import { defaultTrafficManagementConfig, ManifestDeploymentOptions } from './ManifestDeploymentOptions';
|
|
8
|
+
|
|
9
|
+
describe('<ManifestDeploymentOptions />', () => {
|
|
10
|
+
const onConfigChangeSpy = jasmine.createSpy('onConfigChangeSpy');
|
|
11
|
+
let wrapper: any;
|
|
12
|
+
let props: IManifestDeploymentOptionsProps;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
props = {
|
|
16
|
+
accounts: [],
|
|
17
|
+
config: defaultTrafficManagementConfig,
|
|
18
|
+
onConfigChange: onConfigChangeSpy,
|
|
19
|
+
selectedAccount: null,
|
|
20
|
+
};
|
|
21
|
+
wrapper = shallow(<ManifestDeploymentOptions {...props} />);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('view', () => {
|
|
25
|
+
it('renders only the enable checkbox when config is disabled', () => {
|
|
26
|
+
expect(wrapper.find(StageConfigField).length).toEqual(1);
|
|
27
|
+
expect(wrapper.find('input[type="checkbox"]').length).toEqual(1);
|
|
28
|
+
});
|
|
29
|
+
it('renders config fields for `namespace`, `services`, `enableTraffic`, and `strategy` when config is enabled', () => {
|
|
30
|
+
props.config.enabled = true;
|
|
31
|
+
wrapper = shallow(<ManifestDeploymentOptions {...props} />);
|
|
32
|
+
expect(wrapper.find(StageConfigField).length).toEqual(5);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('functionality', () => {
|
|
37
|
+
it('updates `config.enabled` when enable checkbox is toggled', () => {
|
|
38
|
+
wrapper
|
|
39
|
+
.find('input[type="checkbox"]')
|
|
40
|
+
.at(0)
|
|
41
|
+
.simulate('change', { target: { checked: true } });
|
|
42
|
+
expect(onConfigChangeSpy).toHaveBeenCalledWith({
|
|
43
|
+
...defaultTrafficManagementConfig,
|
|
44
|
+
enabled: true,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
it('disables the traffic checkbox when a non-None rollout strategy is selected', () => {
|
|
48
|
+
props.config.options.strategy = 'redblack';
|
|
49
|
+
wrapper = shallow(<ManifestDeploymentOptions {...props} />);
|
|
50
|
+
expect(wrapper.find('input[type="checkbox"]').at(1).props().disabled).toEqual(true);
|
|
51
|
+
});
|
|
52
|
+
it('disables the traffic checkbox when blue/green rollout strategy is selected', () => {
|
|
53
|
+
props.config.options.strategy = 'bluegreen';
|
|
54
|
+
wrapper = shallow(<ManifestDeploymentOptions {...props} />);
|
|
55
|
+
expect(wrapper.find('input[type="checkbox"]').at(1).props().disabled).toEqual(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('strategy bluegreen should not display warning label', () => {
|
|
59
|
+
props.config.options.strategy = 'bluegreen';
|
|
60
|
+
wrapper = shallow(<ManifestDeploymentOptions {...props} />);
|
|
61
|
+
expect(wrapper.find('p[id="redBlackWarning"]').exists()).toEqual(false);
|
|
62
|
+
});
|
|
63
|
+
it('strategy highlander should not display warning label', () => {
|
|
64
|
+
props.config.options.strategy = 'highlander';
|
|
65
|
+
wrapper = shallow(<ManifestDeploymentOptions {...props} />);
|
|
66
|
+
expect(wrapper.find('p[id="redBlackWarning"]').exists()).toEqual(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('strategy redblack should display warning label', () => {
|
|
70
|
+
props.config.options.strategy = 'redblack';
|
|
71
|
+
wrapper = shallow(<ManifestDeploymentOptions {...props} />);
|
|
72
|
+
expect(wrapper.find('p[id="redBlackWarning"]').exists()).toEqual(true);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { cloneDeep, map, set, split } from 'lodash';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { Option } from 'react-select';
|
|
4
|
+
import Select, { Creatable } from 'react-select';
|
|
5
|
+
|
|
6
|
+
import type { IAccountDetails, IDeploymentStrategy } from '@spinnaker/core';
|
|
7
|
+
import { Markdown, StageConfigField } from '@spinnaker/core';
|
|
8
|
+
|
|
9
|
+
import { NamespaceSelector } from './NamespaceSelector';
|
|
10
|
+
import { ManifestKindSearchService } from '../../../manifest/ManifestKindSearch';
|
|
11
|
+
import { rolloutStrategies } from '../../../rolloutStrategy';
|
|
12
|
+
|
|
13
|
+
export interface ITrafficManagementConfig {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
options: ITrafficManagementOptions;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ITrafficManagementOptions {
|
|
19
|
+
namespace: string;
|
|
20
|
+
services: string[];
|
|
21
|
+
enableTraffic: boolean;
|
|
22
|
+
strategy: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const defaultTrafficManagementConfig: ITrafficManagementConfig = {
|
|
26
|
+
enabled: false,
|
|
27
|
+
options: {
|
|
28
|
+
namespace: null,
|
|
29
|
+
services: [],
|
|
30
|
+
enableTraffic: false,
|
|
31
|
+
strategy: null,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export interface IManifestDeploymentOptionsProps {
|
|
36
|
+
accounts: IAccountDetails[];
|
|
37
|
+
config: ITrafficManagementConfig;
|
|
38
|
+
onConfigChange: (config: ITrafficManagementConfig) => void;
|
|
39
|
+
selectedAccount: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface IManifestDeploymentOptionsState {
|
|
43
|
+
services: string[];
|
|
44
|
+
showRedBlackWarningMessage: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class ManifestDeploymentOptions extends React.Component<
|
|
48
|
+
IManifestDeploymentOptionsProps,
|
|
49
|
+
IManifestDeploymentOptionsState
|
|
50
|
+
> {
|
|
51
|
+
public state: IManifestDeploymentOptionsState = { services: [], showRedBlackWarningMessage: false };
|
|
52
|
+
|
|
53
|
+
private onConfigChange = (key: string, value: any): void => {
|
|
54
|
+
this.setState({ showRedBlackWarningMessage: false });
|
|
55
|
+
if (value === 'redblack') {
|
|
56
|
+
value = 'bluegreen';
|
|
57
|
+
this.setState({ showRedBlackWarningMessage: true });
|
|
58
|
+
}
|
|
59
|
+
this.updateProps(key, value);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
private updateProps(key: string, value: any) {
|
|
63
|
+
const updatedConfig = cloneDeep(this.props.config);
|
|
64
|
+
set(updatedConfig, key, value);
|
|
65
|
+
this.props.onConfigChange(updatedConfig);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private fetchServices = (): void => {
|
|
69
|
+
const namespace = this.props.config.options.namespace;
|
|
70
|
+
const account = this.props.selectedAccount;
|
|
71
|
+
if (!namespace || !account) {
|
|
72
|
+
this.setState({
|
|
73
|
+
services: [],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
ManifestKindSearchService.search('service', namespace, account).then((services) => {
|
|
77
|
+
this.setState({ services: map(services, 'name') });
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
private getServiceOptions = (): Array<Option<string>> => {
|
|
82
|
+
const options = this.state.services.map((service) => ({ label: split(service, ' ')[1], value: service }));
|
|
83
|
+
(this.props.config.options.services || []).forEach((service) => {
|
|
84
|
+
if (!this.state.services.includes(service)) {
|
|
85
|
+
options.push({ label: service, value: service });
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return options;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
private strategyOptionRenderer = (option: IDeploymentStrategy) => {
|
|
92
|
+
return (
|
|
93
|
+
<div className="body-regular">
|
|
94
|
+
<strong>
|
|
95
|
+
<Markdown tag="span" message={option.label} />
|
|
96
|
+
</strong>
|
|
97
|
+
<div>
|
|
98
|
+
<Markdown tag="span" message={option.description} />
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
public componentDidMount() {
|
|
105
|
+
this.fetchServices();
|
|
106
|
+
this.setState({ showRedBlackWarningMessage: false });
|
|
107
|
+
if (this.props.config.options.strategy === 'redblack') {
|
|
108
|
+
this.setState({ showRedBlackWarningMessage: true });
|
|
109
|
+
this.updateProps('options.strategy', 'bluegreen');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public componentDidUpdate(prevProps: IManifestDeploymentOptionsProps) {
|
|
114
|
+
if (prevProps.selectedAccount !== this.props.selectedAccount) {
|
|
115
|
+
this.updateProps('options.namespace', null);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (prevProps.config.options.namespace !== this.props.config.options.namespace) {
|
|
119
|
+
this.updateProps('options.services', null);
|
|
120
|
+
this.fetchServices();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!this.props.config.options.enableTraffic && !!this.props.config.options.strategy) {
|
|
124
|
+
this.updateProps('options.enableTraffic', true);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public render() {
|
|
129
|
+
const { config } = this.props;
|
|
130
|
+
const { showRedBlackWarningMessage } = this.state;
|
|
131
|
+
return (
|
|
132
|
+
<>
|
|
133
|
+
<h4>Rollout Strategy Options</h4>
|
|
134
|
+
<StageConfigField helpKey="kubernetes.manifest.rolloutStrategyOptions" fieldColumns={8} label="Enable">
|
|
135
|
+
<div className="checkbox">
|
|
136
|
+
<label>
|
|
137
|
+
<input
|
|
138
|
+
checked={config.enabled}
|
|
139
|
+
onChange={(e) => this.onConfigChange('enabled', e.target.checked)}
|
|
140
|
+
type="checkbox"
|
|
141
|
+
/>
|
|
142
|
+
Spinnaker manages traffic based on your selected strategy
|
|
143
|
+
</label>
|
|
144
|
+
</div>
|
|
145
|
+
</StageConfigField>
|
|
146
|
+
{config.enabled && (
|
|
147
|
+
<>
|
|
148
|
+
<StageConfigField fieldColumns={8} label="Service(s) Namespace">
|
|
149
|
+
<NamespaceSelector
|
|
150
|
+
createable={true}
|
|
151
|
+
onChange={(namespace: string): void => this.onConfigChange('options.namespace', namespace)}
|
|
152
|
+
accounts={this.props.accounts}
|
|
153
|
+
selectedAccount={this.props.selectedAccount}
|
|
154
|
+
selectedNamespace={config.options.namespace || ''}
|
|
155
|
+
/>
|
|
156
|
+
</StageConfigField>
|
|
157
|
+
<StageConfigField fieldColumns={8} label="Service(s)">
|
|
158
|
+
<Creatable
|
|
159
|
+
clearable={false}
|
|
160
|
+
multi={true}
|
|
161
|
+
onChange={(options) => this.onConfigChange('options.services', map(options, 'value'))}
|
|
162
|
+
options={this.getServiceOptions()}
|
|
163
|
+
value={config.options.services}
|
|
164
|
+
/>
|
|
165
|
+
</StageConfigField>
|
|
166
|
+
<StageConfigField fieldColumns={8} label="Traffic">
|
|
167
|
+
<div className="checkbox">
|
|
168
|
+
<label>
|
|
169
|
+
<input
|
|
170
|
+
checked={config.options.enableTraffic}
|
|
171
|
+
disabled={!!config.options.strategy}
|
|
172
|
+
onChange={(e) => this.onConfigChange('options.enableTraffic', e.target.checked)}
|
|
173
|
+
type="checkbox"
|
|
174
|
+
/>
|
|
175
|
+
Send client requests to new pods
|
|
176
|
+
</label>
|
|
177
|
+
</div>
|
|
178
|
+
</StageConfigField>
|
|
179
|
+
<StageConfigField fieldColumns={8} helpKey="kubernetes.manifest.rolloutStrategy" label="Strategy">
|
|
180
|
+
<Select
|
|
181
|
+
id={'strategyDropdown'}
|
|
182
|
+
clearable={false}
|
|
183
|
+
onChange={(option: Option<IDeploymentStrategy>) => this.onConfigChange('options.strategy', option.key)}
|
|
184
|
+
options={rolloutStrategies}
|
|
185
|
+
optionRenderer={this.strategyOptionRenderer}
|
|
186
|
+
placeholder="None"
|
|
187
|
+
value={config.options.strategy}
|
|
188
|
+
valueKey="key"
|
|
189
|
+
valueRenderer={(o) => <>{o.label}</>}
|
|
190
|
+
/>
|
|
191
|
+
{showRedBlackWarningMessage && (
|
|
192
|
+
<p id={'redBlackWarning'} style={{ color: 'orange' }}>
|
|
193
|
+
Warning: Red/black strategy is deprecated and will be removed soon. We automatically selected
|
|
194
|
+
blue/green instead!
|
|
195
|
+
</p>
|
|
196
|
+
)}
|
|
197
|
+
</StageConfigField>
|
|
198
|
+
</>
|
|
199
|
+
)}
|
|
200
|
+
</>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
}
|