@spinnaker/amazon 0.14.5 → 2025.0.1
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/dist/domain/ITargetTrackingPolicy.d.ts +2 -1
- package/dist/index.js +20872 -1
- package/dist/index.js.map +1 -1
- package/dist/serverGroup/details/scalingPolicy/targetTracking/TargetMetricFields.d.ts +3 -1
- package/package.json +4 -3
- package/src/domain/ITargetTrackingPolicy.ts +6 -1
- package/src/serverGroup/configure/serverGroupCommandBuilder.service.ts +5 -1
- package/src/serverGroup/details/scalingPolicy/chart/MetricAlarmChart.tsx +6 -3
- package/src/serverGroup/details/scalingPolicy/targetTracking/TargetMetricFields.tsx +63 -2
- package/src/serverGroup/details/scalingPolicy/targetTracking/TargetTrackingChart.tsx +17 -3
- package/src/serverGroup/details/scalingPolicy/targetTracking/UpsertTargetTrackingModal.tsx +1 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import type { Application } from '@spinnaker/core';
|
|
2
3
|
import type { ITargetTrackingPolicyCommand } from '../ScalingPolicyWriter';
|
|
3
4
|
import type { IAmazonServerGroup } from '../../../../domain';
|
|
4
5
|
import './TargetMetricFields.less';
|
|
@@ -8,8 +9,9 @@ export interface ITargetMetricFieldsProps {
|
|
|
8
9
|
cloudwatch?: boolean;
|
|
9
10
|
command: ITargetTrackingPolicyCommand;
|
|
10
11
|
isCustomMetric: boolean;
|
|
12
|
+
app: Application;
|
|
11
13
|
serverGroup: IAmazonServerGroup;
|
|
12
14
|
toggleMetricType?: (type: MetricType) => void;
|
|
13
15
|
updateCommand: (command: ITargetTrackingPolicyCommand) => void;
|
|
14
16
|
}
|
|
15
|
-
export declare const TargetMetricFields: ({ allowDualMode, cloudwatch, command, isCustomMetric, serverGroup, toggleMetricType, updateCommand, }: ITargetMetricFieldsProps) => JSX.Element;
|
|
17
|
+
export declare const TargetMetricFields: ({ allowDualMode, cloudwatch, command, isCustomMetric, app, serverGroup, toggleMetricType, updateCommand, }: ITargetMetricFieldsProps) => JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spinnaker/amazon",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "2025.0.1",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"publishConfig": {
|
|
8
|
-
"access": "public"
|
|
8
|
+
"access": "public",
|
|
9
|
+
"registry": "https://registry.npmjs.org"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
12
|
"clean": "shx rm -rf dist",
|
|
@@ -58,5 +59,5 @@
|
|
|
58
59
|
"shx": "0.3.3",
|
|
59
60
|
"typescript": "4.3.5"
|
|
60
61
|
},
|
|
61
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "ad8bab4aea2c6174eeb6c5e20614f15d26313a7a"
|
|
62
63
|
}
|
|
@@ -21,6 +21,11 @@ export interface ICustomizedMetricSpecification {
|
|
|
21
21
|
|
|
22
22
|
export interface IPredefinedMetricSpecification {
|
|
23
23
|
predefinedMetricType: PredefinedMetricType;
|
|
24
|
+
resourceLabel?: string;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
export type PredefinedMetricType =
|
|
27
|
+
export type PredefinedMetricType =
|
|
28
|
+
| 'ASGAverageCPUUtilization'
|
|
29
|
+
| 'ASGAverageNetworkIn'
|
|
30
|
+
| 'ASGAverageNetworkOut'
|
|
31
|
+
| 'ALBRequestCountPerTarget';
|
|
@@ -405,6 +405,9 @@ angular
|
|
|
405
405
|
spotMaxPrice = launchTemplateData.instanceMarketOptions?.spotOptions?.maxPrice;
|
|
406
406
|
command.instanceType = launchTemplateData.instanceType;
|
|
407
407
|
command.viewState.useSimpleInstanceTypeSelector = true;
|
|
408
|
+
if (launchTemplateData.userData) {
|
|
409
|
+
command.base64UserData = launchTemplateData.userData;
|
|
410
|
+
}
|
|
408
411
|
}
|
|
409
412
|
|
|
410
413
|
if (serverGroup.mixedInstancesPolicy) {
|
|
@@ -434,7 +437,8 @@ angular
|
|
|
434
437
|
command.viewState.useSimpleInstanceTypeSelector = isSimpleModeEnabled(command);
|
|
435
438
|
}
|
|
436
439
|
|
|
437
|
-
const
|
|
440
|
+
const networkInterfaces = _.get(launchTemplateData, 'networkInterfaces[0]');
|
|
441
|
+
const ipv6AddressCount = (networkInterfaces as INetworkInterface)?.ipv6AddressCount ?? 0;
|
|
438
442
|
|
|
439
443
|
const asgSettings = AWSProviderSettings.serverGroups;
|
|
440
444
|
const isTestEnv = serverGroup.accountDetails && serverGroup.accountDetails.environment === 'test';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { get } from 'lodash';
|
|
1
2
|
import * as React from 'react';
|
|
2
3
|
|
|
3
4
|
import type { ICloudMetricStatistics } from '@spinnaker/core';
|
|
@@ -36,7 +37,7 @@ export function MetricAlarmChartImpl(props: IMetricAlarmChartProps) {
|
|
|
36
37
|
return result;
|
|
37
38
|
},
|
|
38
39
|
{ datapoints: [], unit: '' },
|
|
39
|
-
[namespace, statistic, period, type, account, region, metricName],
|
|
40
|
+
[namespace, statistic, period, type, account, region, metricName, alarm.dimensions],
|
|
40
41
|
);
|
|
41
42
|
|
|
42
43
|
if (status === 'PENDING') {
|
|
@@ -60,13 +61,15 @@ export function MetricAlarmChartImpl(props: IMetricAlarmChartProps) {
|
|
|
60
61
|
|
|
61
62
|
const now = new Date();
|
|
62
63
|
const oneDayAgo = new Date(Date.now() - 1000 * 60 * 60 * 24);
|
|
63
|
-
|
|
64
64
|
const line: IDateLine = {
|
|
65
65
|
label: metricName,
|
|
66
66
|
fill: 'stack',
|
|
67
67
|
borderColor: 'green',
|
|
68
68
|
borderWidth: 2,
|
|
69
|
-
data: result.datapoints.map((dp) => ({
|
|
69
|
+
data: result.datapoints.map((dp) => ({
|
|
70
|
+
x: new Date(dp.timestamp),
|
|
71
|
+
y: get(dp, [alarm.statistic.toLowerCase()], undefined),
|
|
72
|
+
})),
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
const setline: IDateLine = {
|
|
@@ -2,10 +2,17 @@ import { cloneDeep, set } from 'lodash';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
4
|
import { NumberInput, ReactSelectInput } from '@spinnaker/core';
|
|
5
|
+
import type { Application, ILoadBalancer } from '@spinnaker/core';
|
|
5
6
|
|
|
6
7
|
import type { ITargetTrackingPolicyCommand } from '../ScalingPolicyWriter';
|
|
7
8
|
import { TargetTrackingChart } from './TargetTrackingChart';
|
|
8
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
IAmazonApplicationLoadBalancer,
|
|
11
|
+
IAmazonServerGroup,
|
|
12
|
+
ICustomizedMetricSpecification,
|
|
13
|
+
IScalingPolicyAlarmView,
|
|
14
|
+
ITargetGroup,
|
|
15
|
+
} from '../../../../domain';
|
|
9
16
|
import { MetricSelector } from '../upsert/alarm/MetricSelector';
|
|
10
17
|
|
|
11
18
|
import './TargetMetricFields.less';
|
|
@@ -16,21 +23,36 @@ export interface ITargetMetricFieldsProps {
|
|
|
16
23
|
cloudwatch?: boolean;
|
|
17
24
|
command: ITargetTrackingPolicyCommand;
|
|
18
25
|
isCustomMetric: boolean;
|
|
26
|
+
app: Application;
|
|
19
27
|
serverGroup: IAmazonServerGroup;
|
|
20
28
|
toggleMetricType?: (type: MetricType) => void;
|
|
21
29
|
updateCommand: (command: ITargetTrackingPolicyCommand) => void;
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
interface IalbArn {
|
|
33
|
+
loadBalancerArn: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ItargetGroupArn {
|
|
37
|
+
targetGroupArn: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
24
40
|
export const TargetMetricFields = ({
|
|
25
41
|
allowDualMode,
|
|
26
42
|
cloudwatch,
|
|
27
43
|
command,
|
|
28
44
|
isCustomMetric,
|
|
45
|
+
app,
|
|
29
46
|
serverGroup,
|
|
30
47
|
toggleMetricType,
|
|
31
48
|
updateCommand,
|
|
32
49
|
}: ITargetMetricFieldsProps) => {
|
|
33
|
-
const predefinedMetrics = [
|
|
50
|
+
const predefinedMetrics = [
|
|
51
|
+
'ASGAverageCPUUtilization',
|
|
52
|
+
'ASGAverageNetworkOut',
|
|
53
|
+
'ASGAverageNetworkIn',
|
|
54
|
+
'ALBRequestCountPerTarget',
|
|
55
|
+
];
|
|
34
56
|
const statistics = ['Average', 'Maximum', 'Minimum', 'SampleCount', 'Sum'];
|
|
35
57
|
const [unit, setUnit] = React.useState<string>(null);
|
|
36
58
|
|
|
@@ -65,6 +87,24 @@ export const TargetMetricFields = ({
|
|
|
65
87
|
toggleMetricType(isCustomMetric ? 'predefined' : 'custom');
|
|
66
88
|
};
|
|
67
89
|
|
|
90
|
+
const targetGroupOptions = () => {
|
|
91
|
+
const loadBalancers = app.loadBalancers.data as ILoadBalancer[];
|
|
92
|
+
const albs = loadBalancers.filter(
|
|
93
|
+
(lb) => lb.account === serverGroup.account && lb.region === serverGroup.region,
|
|
94
|
+
) as Array<IAmazonApplicationLoadBalancer & IalbArn>;
|
|
95
|
+
const targetGroups = albs.flatMap((alb) =>
|
|
96
|
+
alb.targetGroups
|
|
97
|
+
.filter((tg) => serverGroup.targetGroups.some((serverGroupTg) => serverGroupTg === tg.name))
|
|
98
|
+
.map((tg) => ({ ...tg, loadBalancerArn: alb.loadBalancerArn })),
|
|
99
|
+
) as Array<ITargetGroup & IalbArn & ItargetGroupArn>;
|
|
100
|
+
return targetGroups.map((tg) => ({
|
|
101
|
+
label: tg.name,
|
|
102
|
+
value: `${tg.loadBalancerArn.substring(tg.loadBalancerArn.indexOf('app'))}/${tg.targetGroupArn.substring(
|
|
103
|
+
tg.targetGroupArn.indexOf('targetgroup'),
|
|
104
|
+
)}`,
|
|
105
|
+
}));
|
|
106
|
+
};
|
|
107
|
+
|
|
68
108
|
return (
|
|
69
109
|
<div className="TargetMetricFields sp-margin-l-xaxis">
|
|
70
110
|
<p>
|
|
@@ -94,6 +134,7 @@ export const TargetMetricFields = ({
|
|
|
94
134
|
inputClassName="metric-select-input"
|
|
95
135
|
/>
|
|
96
136
|
)}
|
|
137
|
+
|
|
97
138
|
{isCustomMetric && (
|
|
98
139
|
<MetricSelector
|
|
99
140
|
alarm={command.targetTrackingConfiguration.customizedMetricSpecification as IScalingPolicyAlarmView}
|
|
@@ -108,6 +149,26 @@ export const TargetMetricFields = ({
|
|
|
108
149
|
)}
|
|
109
150
|
</div>
|
|
110
151
|
</div>
|
|
152
|
+
{!isCustomMetric &&
|
|
153
|
+
command.targetTrackingConfiguration.predefinedMetricSpecification?.predefinedMetricType ===
|
|
154
|
+
'ALBRequestCountPerTarget' && (
|
|
155
|
+
<div className="row sp-margin-s-yaxis">
|
|
156
|
+
<div className="col-md-2 sm-label-right">Target Group</div>
|
|
157
|
+
<div className="col-md-10 content-fields horizontal">
|
|
158
|
+
<ReactSelectInput
|
|
159
|
+
value={command.targetTrackingConfiguration.predefinedMetricSpecification?.resourceLabel}
|
|
160
|
+
options={targetGroupOptions()}
|
|
161
|
+
onChange={(e) =>
|
|
162
|
+
setCommandField(
|
|
163
|
+
'targetTrackingConfiguration.predefinedMetricSpecification.resourceLabel',
|
|
164
|
+
e.target.value,
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
inputClassName="metric-select-input"
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
)}
|
|
111
172
|
<div className="row sp-margin-s-yaxis">
|
|
112
173
|
<div className="col-md-2 sm-label-right">Target</div>
|
|
113
174
|
<div className="col-md-10 content-fields horizontal">
|
|
@@ -17,6 +17,7 @@ const predefinedMetricTypeMapping: Dictionary<string> = {
|
|
|
17
17
|
ASGAverageCPUUtilization: 'CPUUtilization',
|
|
18
18
|
ASGAverageNetworkIn: 'NetworkIn',
|
|
19
19
|
ASGAverageNetworkOut: 'NetworkOut',
|
|
20
|
+
ALBRequestCountPerTarget: 'RequestCountPerTarget',
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
export const TargetTrackingChart = ({ config, serverGroup, updateUnit }: ITargetTrackingChartProps) => {
|
|
@@ -40,12 +41,11 @@ export const TargetTrackingChart = ({ config, serverGroup, updateUnit }: ITarget
|
|
|
40
41
|
|
|
41
42
|
const synchronizeAlarm = () => {
|
|
42
43
|
const customMetric = config?.customizedMetricSpecification;
|
|
44
|
+
const predefMetric = config?.predefinedMetricSpecification;
|
|
43
45
|
const updatedAlarm = {
|
|
44
46
|
...alarm,
|
|
45
47
|
dimensions: customMetric?.dimensions || [{ name: 'AutoScalingGroupName', value: serverGroup.name }],
|
|
46
|
-
metricName:
|
|
47
|
-
customMetric?.metricName ||
|
|
48
|
-
predefinedMetricTypeMapping[config?.predefinedMetricSpecification?.predefinedMetricType],
|
|
48
|
+
metricName: customMetric?.metricName || predefinedMetricTypeMapping[predefMetric?.predefinedMetricType],
|
|
49
49
|
namespace: customMetric?.namespace || 'AWS/EC2',
|
|
50
50
|
threshold: config?.targetValue,
|
|
51
51
|
};
|
|
@@ -54,6 +54,20 @@ export const TargetTrackingChart = ({ config, serverGroup, updateUnit }: ITarget
|
|
|
54
54
|
updatedAlarm.statistic = customMetric?.statistic;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
if (predefMetric && predefMetric.predefinedMetricType === 'ALBRequestCountPerTarget') {
|
|
58
|
+
updatedAlarm.statistic = 'Sum';
|
|
59
|
+
updatedAlarm.namespace = 'AWS/ApplicationELB';
|
|
60
|
+
if (predefMetric?.resourceLabel) {
|
|
61
|
+
const parts = predefMetric?.resourceLabel.split('/');
|
|
62
|
+
const loadBalancer = parts.slice(0, 3).join('/');
|
|
63
|
+
const targetGroup = parts.slice(3).join('/');
|
|
64
|
+
updatedAlarm.dimensions = [
|
|
65
|
+
{ name: 'LoadBalancer', value: loadBalancer },
|
|
66
|
+
{ name: 'TargetGroup', value: targetGroup },
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
57
71
|
setAlarm(updatedAlarm);
|
|
58
72
|
};
|
|
59
73
|
|
|
@@ -58,6 +58,7 @@ export const UpsertTargetTrackingModal = ({
|
|
|
58
58
|
cloudwatch={false}
|
|
59
59
|
command={command as ITargetTrackingPolicyCommand}
|
|
60
60
|
isCustomMetric={isCustom}
|
|
61
|
+
app={app}
|
|
61
62
|
serverGroup={serverGroup}
|
|
62
63
|
toggleMetricType={(t) => setIsCustom(t === 'custom')}
|
|
63
64
|
updateCommand={setCommand}
|