@spinnaker/amazon 0.11.0 → 0.12.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 +43 -0
- package/dist/aws.settings.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/instance/awsInstanceType.service.d.ts +10 -2
- package/dist/instance/awsInstanceTypes.d.ts +10 -0
- package/dist/instance/details/CostFactor.d.ts +6 -0
- package/dist/search/searchResultFormatter.d.ts +2 -2
- package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +14 -1
- package/dist/serverGroup/configure/wizard/instanceType/CpuCreditsToggle.d.ts +3 -4
- package/dist/serverGroup/configure/wizard/instanceType/InstanceTypeSelector.d.ts +9 -0
- package/dist/serverGroup/configure/wizard/instanceType/advancedMode/AdvancedModeSelector.d.ts +13 -0
- package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceProfileSelector.d.ts +9 -0
- package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeRow.d.ts +11 -0
- package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTable.d.ts +14 -0
- package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableBody.d.ts +12 -0
- package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableParts.d.ts +15 -0
- package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstancesDistribution.d.ts +8 -0
- package/dist/serverGroup/configure/wizard/instanceType/simpleMode/SimpleModeSelector.d.ts +8 -0
- package/dist/serverGroup/configure/wizard/pages/ServerGroupInstanceType.d.ts +9 -6
- package/dist/serverGroup/details/scalingPolicy/ScalingPolicySummary.d.ts +0 -1
- package/dist/serverGroup/details/scalingPolicy/chart/MetricAlarmChart.d.ts +0 -4
- package/dist/serverGroup/details/scalingPolicy/index.d.ts +0 -1
- package/dist/serverGroup/details/scalingPolicy/targetTracking/TargetTrackingChart.d.ts +1 -3
- package/package.json +5 -5
- package/src/aws.module.ts +3 -3
- package/src/aws.settings.ts +2 -0
- package/src/function/details/FunctionActions.spec.tsx +15 -12
- package/src/function/details/FunctionActions.tsx +2 -1
- package/src/help/amazon.help.ts +9 -6
- package/src/image/image.reader.spec.ts +75 -0
- package/src/instance/awsInstanceType.service.spec.js +37 -71
- package/src/instance/awsInstanceType.service.ts +191 -0
- package/src/instance/awsInstanceTypes.ts +311 -0
- package/src/instance/details/CostFactor.tsx +29 -0
- package/src/instance/details/InstanceInformation.spec.tsx +2 -1
- package/src/instance/details/instance.details.controller.js +472 -473
- package/src/loadBalancer/details/LoadBalancerActions.tsx +2 -1
- package/src/loadBalancer/details/loadBalancerDetails.controller.spec.ts +5 -3
- package/src/search/{searchResultFormatter.js → searchResultFormatter.ts} +5 -4
- package/src/securityGroup/details/securityGroupDetail.controller.js +2 -1
- package/src/serverGroup/configure/AmazonImageSelectInput.spec.tsx +10 -7
- package/src/serverGroup/configure/serverGroupCommandBuilder.aws.service.spec.js +302 -1
- package/src/serverGroup/configure/serverGroupCommandBuilder.service.js +96 -24
- package/src/serverGroup/configure/serverGroupCommandBuilder.spec.js +25 -8
- package/src/serverGroup/configure/serverGroupConfiguration.service.spec.ts +6 -13
- package/src/serverGroup/configure/serverGroupConfiguration.service.ts +26 -1
- package/src/serverGroup/configure/wizard/AmazonCloneServerGroupModal.tsx +1 -1
- package/src/serverGroup/configure/wizard/instanceType/CpuCreditsToggle.tsx +31 -31
- package/src/serverGroup/configure/wizard/instanceType/InstanceTypeSelector.tsx +133 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/AdvancedModeSelector.tsx +99 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceProfileSelector.tsx +36 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeRow.tsx +144 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTable.tsx +137 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableBody.tsx +135 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableParts.tsx +137 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstancesDistribution.less +5 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstancesDistribution.tsx +108 -0
- package/src/serverGroup/configure/wizard/instanceType/advancedMode/advancedMode.less +110 -0
- package/src/serverGroup/configure/wizard/instanceType/simpleMode/SimpleModeSelector.tsx +62 -0
- package/src/serverGroup/configure/wizard/pages/ServerGroupInstanceType.tsx +106 -62
- package/src/serverGroup/configure/wizard/pages/advancedSettings/ServerGroupAdvancedSettingsCommon.tsx +1 -1
- package/src/serverGroup/details/AmazonServerGroupActions.tsx +2 -1
- package/src/serverGroup/details/scalingPolicy/ScalingPolicySummary.tsx +7 -3
- package/src/serverGroup/details/scalingPolicy/StepPolicySummary.tsx +26 -28
- package/src/serverGroup/details/scalingPolicy/chart/MetricAlarmChart.tsx +1 -25
- package/src/serverGroup/details/scalingPolicy/index.ts +0 -1
- package/src/serverGroup/details/scalingPolicy/scalingPolicy.module.ts +1 -9
- package/src/serverGroup/details/scalingPolicy/scalingPolicySummary.component.ts +6 -2
- package/src/serverGroup/details/scalingPolicy/targetTracking/TargetTrackingChart.tsx +2 -17
- package/src/serverGroup/details/scalingPolicy/upsert/alarm/AlarmConfigurer.less +1 -1
- package/src/serverGroup/details/scalingProcesses/AutoScalingProcessService.spec.ts +1 -2
- package/src/serverGroup/details/sections/AdvancedSettingsDetailsSection.tsx +3 -2
- package/src/serverGroup/details/sections/AmazonCapacityDetailsSection.tsx +3 -8
- package/src/serverGroup/details/sections/InstancesDistributionDetailsSection.spec.tsx +8 -5
- package/src/serverGroup/details/sections/LaunchTemplateDetailsSection.spec.tsx +8 -5
- package/src/serverGroup/details/sections/ScalingPoliciesDetailsSection.tsx +3 -3
- package/src/serverGroup/details/sections/ScalingProcessesDetailsSection.tsx +3 -10
- package/src/serverGroup/details/sections/ScheduledActionsDetailsSection.tsx +3 -2
- package/src/serverGroup/details/sections/SecurityGroupsDetailsSection.tsx +3 -2
- package/src/serverGroup/serverGroup.transformer.spec.ts +5 -3
- package/src/subnet/SubnetSelectInput.spec.tsx +7 -4
- package/src/vpc/{VpcReader.spec.js → VpcReader.spec.ts} +2 -10
- package/src/vpc/VpcTag.spec.tsx +37 -0
- package/src/vpc/vpc.module.ts +6 -2
- package/dist/reactShims/aws.ngReact.d.ts +0 -11
- package/dist/serverGroup/details/scalingPolicy/ScalingPolicyTypeRegistry.d.ts +0 -10
- package/dist/serverGroup/details/scalingPolicy/alarmBasedSummary.component.d.ts +0 -2
- package/dist/serverGroup/details/scalingPolicy/detailsSummary.component.d.ts +0 -12
- package/dist/serverGroup/details/scalingPolicy/popover/scalingPolicyPopover.component.d.ts +0 -1
- package/dist/serverGroup/details/scalingPolicy/stepPolicySummary.component.d.ts +0 -1
- package/dist/serverGroup/details/scalingPolicy/targetTracking/TargetTrackingPolicy.config.d.ts +0 -1
- package/dist/serverGroup/details/scalingPolicy/targetTracking/targetTracking.module.d.ts +0 -2
- package/dist/serverGroup/details/scalingPolicy/targetTracking/targetTrackingChart.component.d.ts +0 -1
- package/dist/serverGroup/details/scalingPolicy/targetTracking/targetTrackingSummary.component.d.ts +0 -1
- package/dist/vpc/vpcTag.directive.d.ts +0 -2
- package/src/image/image.reader.spec.js +0 -123
- package/src/instance/awsInstanceType.service.js +0 -437
- package/src/reactShims/aws.ngReact.ts +0 -27
- package/src/serverGroup/details/scalingPolicy/ScalingPolicyTypeRegistry.ts +0 -18
- package/src/serverGroup/details/scalingPolicy/alarmBasedSummary.component.html +0 -35
- package/src/serverGroup/details/scalingPolicy/alarmBasedSummary.component.js +0 -60
- package/src/serverGroup/details/scalingPolicy/alarmBasedSummary.template.html +0 -5
- package/src/serverGroup/details/scalingPolicy/detailsSummary.component.ts +0 -32
- package/src/serverGroup/details/scalingPolicy/popover/scalingPolicyDetails.popover.html +0 -1
- package/src/serverGroup/details/scalingPolicy/popover/scalingPolicyPopover.component.html +0 -107
- package/src/serverGroup/details/scalingPolicy/popover/scalingPolicyPopover.component.ts +0 -31
- package/src/serverGroup/details/scalingPolicy/scalingPolicySummary.component.less +0 -15
- package/src/serverGroup/details/scalingPolicy/stepPolicySummary.component.ts +0 -10
- package/src/serverGroup/details/scalingPolicy/targetTracking/TargetTrackingPolicy.config.ts +0 -6
- package/src/serverGroup/details/scalingPolicy/targetTracking/targetTracking.module.ts +0 -8
- package/src/serverGroup/details/scalingPolicy/targetTracking/targetTrackingChart.component.ts +0 -16
- package/src/serverGroup/details/scalingPolicy/targetTracking/targetTrackingSummary.component.ts +0 -14
- package/src/serverGroup/details/scalingPolicy/targetTracking/targetTrackingSummary.html +0 -5
- package/src/vpc/vpcTag.directive.js +0 -34
- package/src/vpc/vpcTag.directive.spec.js +0 -60
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
.advanced-mode-selector {
|
|
2
|
+
.instance-profile-header {
|
|
3
|
+
display: inline-block;
|
|
4
|
+
button {
|
|
5
|
+
width: 100%;
|
|
6
|
+
}
|
|
7
|
+
h4 {
|
|
8
|
+
min-height: 52px;
|
|
9
|
+
}
|
|
10
|
+
.panel-heading {
|
|
11
|
+
padding: 0 0 0 0;
|
|
12
|
+
}
|
|
13
|
+
&.profile-button {
|
|
14
|
+
width: calc(~'25% - 20px');
|
|
15
|
+
margin: 0 10px 15px 10px;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.sub-section {
|
|
20
|
+
padding: 0 15px;
|
|
21
|
+
margin-bottom: 5px;
|
|
22
|
+
|
|
23
|
+
.description {
|
|
24
|
+
padding: 0 10px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
tr {
|
|
28
|
+
&.unavailable {
|
|
29
|
+
opacity: 0.5;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&.sortable {
|
|
33
|
+
.instance-type-drag-handle {
|
|
34
|
+
display: inline-block;
|
|
35
|
+
opacity: 0.9;
|
|
36
|
+
font-size: 100%;
|
|
37
|
+
padding-top: 8px;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
th {
|
|
43
|
+
font-size: 110%;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.custom-profile {
|
|
49
|
+
.select {
|
|
50
|
+
width: 80%;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.instance-profile {
|
|
55
|
+
vertical-align: top;
|
|
56
|
+
text-align: left;
|
|
57
|
+
min-height: 100px;
|
|
58
|
+
font-size: 90%;
|
|
59
|
+
border: 1px solid var(--color-silver);
|
|
60
|
+
border-radius: 3px;
|
|
61
|
+
color: var(--color-mineshaft);
|
|
62
|
+
background-color: transparent;
|
|
63
|
+
|
|
64
|
+
&:hover,
|
|
65
|
+
&:focus {
|
|
66
|
+
color: var(--color-mineshaft);
|
|
67
|
+
text-decoration: none;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.selected-indicator {
|
|
71
|
+
display: flex;
|
|
72
|
+
width: 100%;
|
|
73
|
+
text-align: right;
|
|
74
|
+
padding-right: 5px;
|
|
75
|
+
font-size: 150%;
|
|
76
|
+
color: var(--color-accent);
|
|
77
|
+
|
|
78
|
+
&.custom {
|
|
79
|
+
margin-top: 5px;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
h4 {
|
|
84
|
+
margin-top: 0;
|
|
85
|
+
text-align: center;
|
|
86
|
+
word-spacing: 300px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
ul {
|
|
90
|
+
font-size: 95%;
|
|
91
|
+
padding-left: 20px;
|
|
92
|
+
}
|
|
93
|
+
.panel-heading {
|
|
94
|
+
padding-top: 0;
|
|
95
|
+
padding-bottom: 0;
|
|
96
|
+
}
|
|
97
|
+
&:hover,
|
|
98
|
+
&:focus,
|
|
99
|
+
&.active {
|
|
100
|
+
outline: 0;
|
|
101
|
+
}
|
|
102
|
+
&.active {
|
|
103
|
+
box-shadow: inset 0 0 3px 2px var(--color-accent);
|
|
104
|
+
border-color: var(--color-accent);
|
|
105
|
+
}
|
|
106
|
+
&:hover,
|
|
107
|
+
&:focus {
|
|
108
|
+
box-shadow: 0 0 8px 2px var(--color-accent);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { NgReact } from '@spinnaker/core';
|
|
4
|
+
|
|
5
|
+
import { CpuCreditsToggle } from '../CpuCreditsToggle';
|
|
6
|
+
import { AWSProviderSettings } from '../../../../../aws.settings';
|
|
7
|
+
import type { IAmazonServerGroupCommand } from '../../../serverGroupConfiguration.service';
|
|
8
|
+
|
|
9
|
+
export interface ISimpleModeSelectorProps {
|
|
10
|
+
command: IAmazonServerGroupCommand;
|
|
11
|
+
setUnlimitedCpuCredits: (unlimitedCpuCredits: boolean | undefined) => void;
|
|
12
|
+
setFieldValue: (field: keyof IAmazonServerGroupCommand, value: any, shouldValidate?: boolean) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function SimpleModeSelector(props: ISimpleModeSelectorProps) {
|
|
16
|
+
const { command } = props;
|
|
17
|
+
const { InstanceArchetypeSelector, InstanceTypeSelector } = NgReact;
|
|
18
|
+
const isLaunchTemplatesEnabled = AWSProviderSettings.serverGroups?.enableLaunchTemplates;
|
|
19
|
+
const isCpuCreditsEnabled = AWSProviderSettings.serverGroups?.enableCpuCredits;
|
|
20
|
+
|
|
21
|
+
const instanceProfileChanged = (newProfile: string) => {
|
|
22
|
+
// Instance profile is already set on values.viewState, so just use that value.
|
|
23
|
+
// Once angular is gone from this component tree, we can move all the viewState stuff
|
|
24
|
+
// into react state
|
|
25
|
+
props.setFieldValue('viewState', {
|
|
26
|
+
...command.viewState,
|
|
27
|
+
instanceProfile: newProfile,
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const instanceTypeChanged = (type: string) => {
|
|
32
|
+
command.instanceTypeChanged(command);
|
|
33
|
+
props.setFieldValue('instanceType', type);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="container-fluid form-horizontal">
|
|
38
|
+
<div className="row">
|
|
39
|
+
<InstanceArchetypeSelector
|
|
40
|
+
command={command}
|
|
41
|
+
onTypeChanged={instanceTypeChanged}
|
|
42
|
+
onProfileChanged={instanceProfileChanged}
|
|
43
|
+
/>
|
|
44
|
+
<div style={{ padding: '0 15px' }}>
|
|
45
|
+
{command.viewState.instanceProfile && command.viewState.instanceProfile !== 'custom' && (
|
|
46
|
+
<InstanceTypeSelector command={command} onTypeChanged={instanceTypeChanged} />
|
|
47
|
+
)}
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
{isLaunchTemplatesEnabled && isCpuCreditsEnabled && (
|
|
51
|
+
<div className="row">
|
|
52
|
+
<CpuCreditsToggle
|
|
53
|
+
unlimitedCpuCredits={command.unlimitedCpuCredits}
|
|
54
|
+
selectedInstanceTypes={[command.instanceType]}
|
|
55
|
+
currentProfile={command.viewState.instanceProfile}
|
|
56
|
+
setUnlimitedCpuCredits={props.setUnlimitedCpuCredits}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { FormikErrors, FormikProps } from 'formik';
|
|
2
|
+
import { some } from 'lodash';
|
|
2
3
|
import React from 'react';
|
|
4
|
+
import { Subject } from 'rxjs';
|
|
3
5
|
|
|
4
6
|
import type { IWizardPageComponent } from '@spinnaker/core';
|
|
5
|
-
import { NgReact } from '@spinnaker/core';
|
|
6
|
-
import { AWSProviderSettings } from '../../../../aws.settings';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import type { IAmazonInstanceTypeCategory } from '../../../../instance/awsInstanceType.service';
|
|
9
|
+
import { InstanceTypeSelector } from '../instanceType/InstanceTypeSelector';
|
|
10
|
+
import { AwsReactInjector } from '../../../../reactShims';
|
|
9
11
|
import type { IAmazonServerGroupCommand } from '../../serverGroupConfiguration.service';
|
|
10
12
|
|
|
11
13
|
export interface IServerGroupInstanceTypeProps {
|
|
@@ -13,88 +15,130 @@ export interface IServerGroupInstanceTypeProps {
|
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export interface IServerGroupInstanceTypeState {
|
|
16
|
-
|
|
17
|
-
newProfileType?: string;
|
|
18
|
+
instanceTypeDetails: IAmazonInstanceTypeCategory[];
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export class ServerGroupInstanceType
|
|
21
22
|
extends React.Component<IServerGroupInstanceTypeProps, IServerGroupInstanceTypeState>
|
|
22
23
|
implements IWizardPageComponent<IAmazonServerGroupCommand> {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
};
|
|
29
|
-
}
|
|
24
|
+
public state: IServerGroupInstanceTypeState = {
|
|
25
|
+
instanceTypeDetails: [],
|
|
26
|
+
};
|
|
27
|
+
private props$ = new Subject<IServerGroupInstanceTypeProps>();
|
|
28
|
+
private destroy$ = new Subject<void>();
|
|
30
29
|
|
|
31
|
-
public validate(values: IAmazonServerGroupCommand) {
|
|
30
|
+
public validate(values: IAmazonServerGroupCommand): FormikErrors<IAmazonServerGroupCommand> {
|
|
32
31
|
const errors: FormikErrors<IAmazonServerGroupCommand> = {};
|
|
33
32
|
|
|
34
|
-
if (
|
|
35
|
-
|
|
33
|
+
if (values.viewState.useSimpleInstanceTypeSelector) {
|
|
34
|
+
if (!values.instanceType) {
|
|
35
|
+
errors.instanceType = 'Instance Type required.';
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
const advancedModeErrors = this.validateAdvancedModeFields(values, errors);
|
|
39
|
+
Object.assign(errors, { ...advancedModeErrors });
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
return errors;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
private validateAdvancedModeFields(
|
|
46
|
+
values: IAmazonServerGroupCommand,
|
|
47
|
+
errors: FormikErrors<IAmazonServerGroupCommand>,
|
|
48
|
+
): FormikErrors<IAmazonServerGroupCommand> {
|
|
49
|
+
if (!values.launchTemplateOverridesForInstanceType.length) {
|
|
50
|
+
errors.instanceType = 'At least one instance type required.';
|
|
51
|
+
}
|
|
52
|
+
if (values.launchTemplateOverridesForInstanceType.length > 40) {
|
|
53
|
+
errors.instanceType = 'Maximum of 40 instance types are allowed.';
|
|
54
|
+
}
|
|
55
|
+
const weightsSpecified = values.launchTemplateOverridesForInstanceType.filter(
|
|
56
|
+
(it) => it.weightedCapacity !== undefined,
|
|
57
|
+
);
|
|
58
|
+
if (
|
|
59
|
+
!(
|
|
60
|
+
weightsSpecified.length === values.launchTemplateOverridesForInstanceType.length ||
|
|
61
|
+
weightsSpecified.length === 0
|
|
62
|
+
)
|
|
63
|
+
) {
|
|
64
|
+
errors.instanceType = 'Weighted capacity must be specified for all instance types selected or none.';
|
|
65
|
+
}
|
|
66
|
+
if (
|
|
67
|
+
some(weightsSpecified, function (instanceType) {
|
|
68
|
+
return instanceType.weightedCapacity < 1 || instanceType.weightedCapacity > 999;
|
|
69
|
+
})
|
|
70
|
+
) {
|
|
71
|
+
errors.instanceType = 'Weighted capacity must be a number between 1 and 999.';
|
|
72
|
+
}
|
|
47
73
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.props.formik.setFieldValue('instanceType', type);
|
|
52
|
-
this.setState({ newInstanceType: type, newProfileType: undefined });
|
|
53
|
-
};
|
|
74
|
+
if (values.onDemandBaseCapacity < 0) {
|
|
75
|
+
errors.onDemandBaseCapacity = 'On-Demand base capacity must be non-negative.';
|
|
76
|
+
}
|
|
54
77
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
if (values.onDemandBaseCapacity > values.capacity.max) {
|
|
79
|
+
errors.onDemandBaseCapacity = 'On-Demand base capacity must be less than or equal to max capacity.';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (values.onDemandPercentageAboveBaseCapacity < 0 || values.onDemandPercentageAboveBaseCapacity > 100) {
|
|
83
|
+
errors.onDemandPercentageAboveBaseCapacity =
|
|
84
|
+
'On-Demand percentage above base capacity must be a number between 0 and 100.';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (values.spotPrice) {
|
|
88
|
+
const spotPriceNum = Number(values.spotPrice);
|
|
89
|
+
if (Number.isNaN(spotPriceNum)) {
|
|
90
|
+
errors.spotPrice = 'Spot Max Price must be a number or empty string, used to unset previous max price.';
|
|
91
|
+
}
|
|
92
|
+
if (spotPriceNum <= 0) {
|
|
93
|
+
errors.spotPrice = 'Spot Max Price must be greater than 0, if specified.';
|
|
94
|
+
}
|
|
59
95
|
}
|
|
60
|
-
|
|
96
|
+
|
|
97
|
+
if (values.spotInstancePools && values.spotAllocationStrategy !== 'lowest-price') {
|
|
98
|
+
errors.spotInstancePools = "Spot Instance Pools is only supported for 'lowest-price' Spot Allocation Strategy.";
|
|
99
|
+
}
|
|
100
|
+
if (values.spotInstancePools <= 0 || values.spotInstancePools > 20) {
|
|
101
|
+
errors.spotInstancePools = 'Spot Instance Pools count must be a number between 1 and 20, when applicable.';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return errors;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public componentDidMount(): void {
|
|
108
|
+
Promise.resolve(AwsReactInjector.awsInstanceTypeService.getCategories()).then(
|
|
109
|
+
(categories: IAmazonInstanceTypeCategory[]) => {
|
|
110
|
+
this.setState({ instanceTypeDetails: categories });
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public componentDidUpdate() {
|
|
116
|
+
this.props$.next(this.props);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public componentWillUnmount() {
|
|
120
|
+
this.destroy$.next();
|
|
121
|
+
}
|
|
61
122
|
|
|
62
123
|
public render() {
|
|
63
124
|
const { values } = this.props.formik;
|
|
64
|
-
|
|
65
|
-
const { InstanceArchetypeSelector, InstanceTypeSelector } = NgReact;
|
|
66
125
|
const showTypeSelector = !!(values.viewState.disableImageSelection || values.amiName);
|
|
67
126
|
|
|
68
|
-
|
|
69
|
-
const
|
|
127
|
+
// mark unavailable instance types for all profiles
|
|
128
|
+
const availableInstanceTypesForConfig: string[] = values.backingData?.filtered?.instanceTypes ?? [];
|
|
129
|
+
const markedInstanceTypeDetails: IAmazonInstanceTypeCategory[] = Array.from(this.state.instanceTypeDetails);
|
|
130
|
+
if (!values.viewState.disableImageSelection && availableInstanceTypesForConfig.length) {
|
|
131
|
+
markedInstanceTypeDetails.forEach((profile) => {
|
|
132
|
+
profile.families.forEach((family) => {
|
|
133
|
+
family.instanceTypes.forEach((instanceType) => {
|
|
134
|
+
instanceType.unavailable = !availableInstanceTypesForConfig.includes(instanceType.name);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
70
139
|
|
|
71
140
|
if (showTypeSelector && values) {
|
|
72
|
-
return
|
|
73
|
-
<div className="container-fluid form-horizontal">
|
|
74
|
-
<div className="row">
|
|
75
|
-
<InstanceArchetypeSelector
|
|
76
|
-
command={values}
|
|
77
|
-
onTypeChanged={this.instanceTypeChanged}
|
|
78
|
-
onProfileChanged={this.instanceProfileChanged}
|
|
79
|
-
/>
|
|
80
|
-
<div style={{ padding: '0 15px' }}>
|
|
81
|
-
{values.viewState.instanceProfile && values.viewState.instanceProfile !== 'custom' && (
|
|
82
|
-
<InstanceTypeSelector command={values} onTypeChanged={this.instanceTypeChanged} />
|
|
83
|
-
)}
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
{isLaunchTemplatesEnabled && isCpuCreditsEnabled && (
|
|
87
|
-
<div className="row">
|
|
88
|
-
<CpuCreditsToggle
|
|
89
|
-
command={values}
|
|
90
|
-
newInstanceType={this.state.newInstanceType}
|
|
91
|
-
newProfileType={this.state.newProfileType}
|
|
92
|
-
setUnlimitedCpuCredits={this.setUnlimitedCpuCredits}
|
|
93
|
-
/>
|
|
94
|
-
</div>
|
|
95
|
-
)}
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
141
|
+
return <InstanceTypeSelector formik={this.props.formik} instanceTypeDetails={markedInstanceTypeDetails} />;
|
|
98
142
|
}
|
|
99
143
|
|
|
100
144
|
return <h5 className="text-center">Please select an image.</h5>;
|
|
@@ -222,7 +222,7 @@ export class ServerGroupAdvancedSettingsCommon extends React.Component<IServerGr
|
|
|
222
222
|
</div>
|
|
223
223
|
</div>
|
|
224
224
|
)}
|
|
225
|
-
{!AWSProviderSettings.disableSpotPricing && (
|
|
225
|
+
{!AWSProviderSettings.disableSpotPricing && values.viewState.useSimpleInstanceTypeSelector && (
|
|
226
226
|
<div className="form-group">
|
|
227
227
|
<div className="col-md-5 sm-label-right">
|
|
228
228
|
<b>Spot Instances Price (optional)</b> <HelpField id="aws.serverGroup.spotMaxPrice" />
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
SETTINGS,
|
|
16
16
|
} from '@spinnaker/core';
|
|
17
17
|
|
|
18
|
+
import { AWSProviderSettings } from '../../aws.settings';
|
|
18
19
|
import type { IAmazonServerGroupCommand } from '../configure';
|
|
19
20
|
import { AmazonCloneServerGroupModal } from '../configure/wizard/AmazonCloneServerGroupModal';
|
|
20
21
|
import type { IAmazonServerGroup, IAmazonServerGroupView } from '../../domain';
|
|
@@ -286,7 +287,7 @@ export class AmazonServerGroupActions extends React.Component<IAmazonServerGroup
|
|
|
286
287
|
|
|
287
288
|
return (
|
|
288
289
|
<>
|
|
289
|
-
{
|
|
290
|
+
{AWSProviderSettings.adHocInfraWritesEnabled && (
|
|
290
291
|
<Dropdown className="dropdown" id="server-group-actions-dropdown">
|
|
291
292
|
<Dropdown.Toggle className="btn btn-sm btn-primary dropdown-toggle">Server Group Actions</Dropdown.Toggle>
|
|
292
293
|
<Dropdown.Menu className="dropdown-menu">
|
|
@@ -6,8 +6,6 @@ import { StepPolicySummary } from './StepPolicySummary';
|
|
|
6
6
|
import type { IScalingPolicyView, ITargetTrackingPolicy } from '../../../domain';
|
|
7
7
|
import { TargetTrackingSummary } from './targetTracking/TargetTrackingSummary';
|
|
8
8
|
|
|
9
|
-
import './scalingPolicySummary.component.less';
|
|
10
|
-
|
|
11
9
|
export interface IScalingPolicySummaryProps {
|
|
12
10
|
application: Application;
|
|
13
11
|
policy: IScalingPolicyView;
|
|
@@ -15,7 +13,13 @@ export interface IScalingPolicySummaryProps {
|
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
export const ScalingPolicySummary = ({ application, policy, serverGroup }: IScalingPolicySummaryProps) => {
|
|
18
|
-
|
|
16
|
+
const scalingPolicyType = policy.policyType
|
|
17
|
+
? policy.policyType
|
|
18
|
+
: policy.targetTrackingConfiguration
|
|
19
|
+
? 'TargetTrackingScaling'
|
|
20
|
+
: 'StepScaling';
|
|
21
|
+
|
|
22
|
+
if (scalingPolicyType === 'TargetTrackingScaling') {
|
|
19
23
|
return (
|
|
20
24
|
<TargetTrackingSummary
|
|
21
25
|
application={application}
|
|
@@ -83,39 +83,37 @@ export const StepPolicySummary = ({ application, policy, serverGroup }: IStepPol
|
|
|
83
83
|
});
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
if (!policy.alarms?.length) {
|
|
87
|
-
return <div>No alarms configured for this policy - it's safe to delete.</div>;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
86
|
return (
|
|
91
87
|
<div className="StepPolicySummary">
|
|
92
88
|
<div>
|
|
93
|
-
{policy.alarms
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<
|
|
89
|
+
{!Boolean(policy.alarms?.length) && <div>No alarms configured for this policy - it's safe to delete.</div>}
|
|
90
|
+
{Boolean(policy.alarms?.length) &&
|
|
91
|
+
policy.alarms.map((a) => (
|
|
92
|
+
<div key={`step-summary-${policy.policyName}`}>
|
|
93
|
+
<HoverablePopover
|
|
94
|
+
Component={() => (
|
|
95
|
+
<StepPolicyPopoverContent policy={policy} serverGroup={serverGroup as IAmazonServerGroup} />
|
|
96
|
+
)}
|
|
97
|
+
placement="left"
|
|
98
|
+
title={policy.policyName}
|
|
99
|
+
>
|
|
100
|
+
<div>
|
|
101
|
+
<div className="label label-default">{robotToHuman(policy.policyType).toUpperCase()}</div>
|
|
102
|
+
<AlarmSummary alarm={a} />
|
|
103
|
+
</div>
|
|
104
|
+
</HoverablePopover>
|
|
105
|
+
<div className="actions">
|
|
106
|
+
<button className="btn btn-xs btn-link" onClick={editPolicy}>
|
|
107
|
+
<span className="glyphicon glyphicon-cog"></span>
|
|
108
|
+
<span className="sr-only">Edit policy</span>
|
|
109
|
+
</button>
|
|
110
|
+
<button className="btn btn-xs btn-link" onClick={deletePolicy}>
|
|
111
|
+
<span className="glyphicon glyphicon-trash"></span>
|
|
112
|
+
<span className="sr-only">Delete policy</span>
|
|
113
|
+
</button>
|
|
105
114
|
</div>
|
|
106
|
-
</HoverablePopover>
|
|
107
|
-
<div className="actions">
|
|
108
|
-
<button className="btn btn-xs btn-link" onClick={editPolicy}>
|
|
109
|
-
<span className="glyphicon glyphicon-cog"></span>
|
|
110
|
-
<span className="sr-only">Edit policy</span>
|
|
111
|
-
</button>
|
|
112
|
-
<button className="btn btn-xs btn-link" onClick={deletePolicy}>
|
|
113
|
-
<span className="glyphicon glyphicon-trash"></span>
|
|
114
|
-
<span className="sr-only">Delete policy</span>
|
|
115
|
-
</button>
|
|
116
115
|
</div>
|
|
117
|
-
|
|
118
|
-
))}
|
|
116
|
+
))}
|
|
119
117
|
</div>
|
|
120
118
|
</div>
|
|
121
119
|
);
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import { module } from 'angular';
|
|
2
1
|
import * as React from 'react';
|
|
3
|
-
import { react2angular } from 'react2angular';
|
|
4
|
-
import type { Observable } from 'rxjs';
|
|
5
2
|
|
|
6
3
|
import type { ICloudMetricStatistics } from '@spinnaker/core';
|
|
7
|
-
import { CloudMetricsReader, Spinner, useData
|
|
8
|
-
import { withErrorBoundary } from '@spinnaker/core';
|
|
4
|
+
import { CloudMetricsReader, Spinner, useData } from '@spinnaker/core';
|
|
9
5
|
|
|
10
6
|
import type { IDateLine } from './DateLineChart';
|
|
11
7
|
import { DateLineChart } from './DateLineChart';
|
|
@@ -14,9 +10,6 @@ import type { IAmazonServerGroup, IScalingPolicyAlarm } from '../../../../domain
|
|
|
14
10
|
interface IMetricAlarmChartProps {
|
|
15
11
|
serverGroup: IAmazonServerGroup;
|
|
16
12
|
alarm: IScalingPolicyAlarm;
|
|
17
|
-
// Allows AngularJS to tell the chart to update
|
|
18
|
-
alarmUpdated?: Observable<any>;
|
|
19
|
-
// Allows the chart data to inform the parent component of the fetched metric units
|
|
20
13
|
onChartLoaded?: (stats: ICloudMetricStatistics) => void;
|
|
21
14
|
}
|
|
22
15
|
|
|
@@ -46,10 +39,6 @@ export function MetricAlarmChartImpl(props: IMetricAlarmChartProps) {
|
|
|
46
39
|
[namespace, statistic, period, type, account, region, metricName],
|
|
47
40
|
);
|
|
48
41
|
|
|
49
|
-
// Used by AngularJS to tell the chart to refresh, delete when all callers are reactified
|
|
50
|
-
const forceUpdate = useForceUpdate();
|
|
51
|
-
useObservable(props.alarmUpdated, () => forceUpdate());
|
|
52
|
-
|
|
53
42
|
if (status === 'PENDING') {
|
|
54
43
|
return (
|
|
55
44
|
<div className="flex-container-v middle center sp-margin-xl">
|
|
@@ -91,16 +80,3 @@ export function MetricAlarmChartImpl(props: IMetricAlarmChartProps) {
|
|
|
91
80
|
};
|
|
92
81
|
return <DateLineChart lines={[line, setline]} />;
|
|
93
82
|
}
|
|
94
|
-
|
|
95
|
-
export const AMAZON_SERVERGROUP_DETAILS_SCALINGPOLICY_CHART_METRICALARMCHART_COMPONENT =
|
|
96
|
-
'spinnaker.amazon.serverGroup.details.scalingPolicy.metricAlarmChart.component';
|
|
97
|
-
export const name = AMAZON_SERVERGROUP_DETAILS_SCALINGPOLICY_CHART_METRICALARMCHART_COMPONENT; // for backwards compatibility
|
|
98
|
-
module(AMAZON_SERVERGROUP_DETAILS_SCALINGPOLICY_CHART_METRICALARMCHART_COMPONENT, []).component(
|
|
99
|
-
'metricAlarmChart',
|
|
100
|
-
react2angular(withErrorBoundary(MetricAlarmChart, 'metricAlarmChart'), [
|
|
101
|
-
'alarm',
|
|
102
|
-
'serverGroup',
|
|
103
|
-
'alarmUpdated',
|
|
104
|
-
'onChartLoaded',
|
|
105
|
-
]),
|
|
106
|
-
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { DateLineChart } from './chart/DateLineChart';
|
|
2
2
|
export { MetricAlarmChart } from './chart/MetricAlarmChart';
|
|
3
|
-
export * from './ScalingPolicyTypeRegistry';
|
|
4
3
|
export * from './CreateScalingPolicyButton';
|
|
5
4
|
export * from './ScalingPolicyWriter';
|
|
6
5
|
export * from './StepPolicySummary';
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { module } from 'angular';
|
|
2
2
|
|
|
3
|
-
import { AMAZON_SERVERGROUP_DETAILS_SCALINGPOLICY_ALARMBASEDSUMMARY_COMPONENT } from './alarmBasedSummary.component';
|
|
4
3
|
import { SCALING_POLICY_SUMMARY_COMPONENT } from './scalingPolicySummary.component';
|
|
5
|
-
import { STEP_POLICY_SUMMARY_COMPONENT } from './stepPolicySummary.component';
|
|
6
|
-
import { TARGET_TRACKING_MODULE } from './targetTracking/targetTracking.module';
|
|
7
4
|
|
|
8
5
|
export const SCALING_POLICY_MODULE = 'spinnaker.amazon.scalingPolicy.module';
|
|
9
|
-
module(SCALING_POLICY_MODULE, [
|
|
10
|
-
TARGET_TRACKING_MODULE,
|
|
11
|
-
AMAZON_SERVERGROUP_DETAILS_SCALINGPOLICY_ALARMBASEDSUMMARY_COMPONENT,
|
|
12
|
-
STEP_POLICY_SUMMARY_COMPONENT,
|
|
13
|
-
SCALING_POLICY_SUMMARY_COMPONENT,
|
|
14
|
-
]);
|
|
6
|
+
module(SCALING_POLICY_MODULE, [SCALING_POLICY_SUMMARY_COMPONENT]);
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { module } from 'angular';
|
|
2
2
|
import { react2angular } from 'react2angular';
|
|
3
3
|
import { withErrorBoundary } from '@spinnaker/core';
|
|
4
|
-
import {
|
|
4
|
+
import { ScalingPolicySummary } from './ScalingPolicySummary';
|
|
5
5
|
|
|
6
6
|
export const SCALING_POLICY_SUMMARY_COMPONENT = 'spinnaker.amazon.scalingPolicy.scalingPolicySummary.component';
|
|
7
7
|
module(SCALING_POLICY_SUMMARY_COMPONENT, []).component(
|
|
8
8
|
'scalingPolicySummary',
|
|
9
|
-
react2angular(withErrorBoundary(
|
|
9
|
+
react2angular(withErrorBoundary(ScalingPolicySummary, 'scalingPolicySummary'), [
|
|
10
|
+
'application',
|
|
11
|
+
'policy',
|
|
12
|
+
'serverGroup',
|
|
13
|
+
]),
|
|
10
14
|
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Dictionary } from 'lodash';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { Subject } from 'rxjs';
|
|
4
3
|
|
|
5
4
|
import type { ICloudMetricStatistics } from '@spinnaker/core';
|
|
6
5
|
|
|
@@ -8,7 +7,6 @@ import { MetricAlarmChart } from '../chart/MetricAlarmChart';
|
|
|
8
7
|
import type { IAmazonServerGroup, IScalingPolicyAlarm, ITargetTrackingConfiguration } from '../../../../domain';
|
|
9
8
|
|
|
10
9
|
export interface ITargetTrackingChartProps {
|
|
11
|
-
alarmUpdated?: Subject<void>;
|
|
12
10
|
config: ITargetTrackingConfiguration;
|
|
13
11
|
serverGroup: IAmazonServerGroup;
|
|
14
12
|
unit?: string;
|
|
@@ -21,12 +19,7 @@ const predefinedMetricTypeMapping: Dictionary<string> = {
|
|
|
21
19
|
ASGAverageNetworkOut: 'NetworkOut',
|
|
22
20
|
};
|
|
23
21
|
|
|
24
|
-
export const TargetTrackingChart = ({
|
|
25
|
-
alarmUpdated = new Subject<void>(),
|
|
26
|
-
config,
|
|
27
|
-
serverGroup,
|
|
28
|
-
updateUnit,
|
|
29
|
-
}: ITargetTrackingChartProps) => {
|
|
22
|
+
export const TargetTrackingChart = ({ config, serverGroup, updateUnit }: ITargetTrackingChartProps) => {
|
|
30
23
|
const [alarm, setAlarm] = React.useState<IScalingPolicyAlarm>({
|
|
31
24
|
alarmName: null,
|
|
32
25
|
alarmArn: null,
|
|
@@ -72,15 +65,7 @@ export const TargetTrackingChart = ({
|
|
|
72
65
|
if (updateUnit) {
|
|
73
66
|
updateUnit(stats.unit);
|
|
74
67
|
}
|
|
75
|
-
alarmUpdated?.next();
|
|
76
68
|
};
|
|
77
69
|
|
|
78
|
-
return
|
|
79
|
-
<MetricAlarmChart
|
|
80
|
-
alarm={alarm}
|
|
81
|
-
alarmUpdated={alarmUpdated}
|
|
82
|
-
onChartLoaded={onChartLoaded}
|
|
83
|
-
serverGroup={serverGroup}
|
|
84
|
-
/>
|
|
85
|
-
);
|
|
70
|
+
return <MetricAlarmChart alarm={alarm} onChartLoaded={onChartLoaded} serverGroup={serverGroup} />;
|
|
86
71
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { IAmazonAsg, IAmazonServerGroup } from '../../../domain';
|
|
2
|
-
|
|
3
1
|
import { AutoScalingProcessService } from './AutoScalingProcessService';
|
|
2
|
+
import type { IAmazonAsg, IAmazonServerGroup } from '../../../domain';
|
|
4
3
|
|
|
5
4
|
describe('AutoScalingProcessService', () => {
|
|
6
5
|
describe('normalizeScalingProcesses', () => {
|