@spinnaker/amazon 0.13.0 → 0.13.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.
Files changed (30) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/image/image.reader.d.ts +1 -0
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/instance/awsInstanceType.service.d.ts +41 -1
  6. package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +4 -0
  7. package/dist/serverGroup/configure/wizard/instanceType/advancedMode/AmazonInstanceTypeInfoRenderer.d.ts +5 -0
  8. package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeRow.d.ts +2 -0
  9. package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeSelect.d.ts +7 -0
  10. package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTable.d.ts +2 -1
  11. package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableBody.d.ts +2 -0
  12. package/dist/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableParts.d.ts +3 -1
  13. package/package.json +2 -2
  14. package/src/help/amazon.help.ts +19 -1
  15. package/src/image/image.reader.ts +1 -0
  16. package/src/instance/awsInstanceType.service.spec.js +225 -32
  17. package/src/instance/awsInstanceType.service.ts +77 -21
  18. package/src/serverGroup/configure/AmazonImageSelectInput.tsx +1 -1
  19. package/src/serverGroup/configure/serverGroupConfiguration.service.ts +21 -10
  20. package/src/serverGroup/configure/wizard/instanceType/InstanceTypeSelector.tsx +2 -2
  21. package/src/serverGroup/configure/wizard/instanceType/advancedMode/AdvancedModeSelector.tsx +1 -1
  22. package/src/serverGroup/configure/wizard/instanceType/advancedMode/AmazonInstanceTypeInfoRenderer.tsx +59 -0
  23. package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeRow.tsx +15 -2
  24. package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeSelect.tsx +78 -0
  25. package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTable.tsx +6 -2
  26. package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableBody.tsx +10 -1
  27. package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstanceTypeTableParts.tsx +16 -24
  28. package/src/serverGroup/configure/wizard/instanceType/advancedMode/InstancesDistribution.tsx +4 -1
  29. package/src/serverGroup/configure/wizard/instanceType/advancedMode/advancedMode.less +13 -1
  30. package/src/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.tsx +3 -0
@@ -1,4 +1,4 @@
1
- import type { IInstanceTypeCategory, IPreferredInstanceType } from '@spinnaker/core';
1
+ import type { IInstanceType, IInstanceTypeCategory, IInstanceTypesByRegion, IPreferredInstanceType } from '@spinnaker/core';
2
2
  export interface IAmazonPreferredInstanceType extends IPreferredInstanceType {
3
3
  cpuCreditsPerHour?: number;
4
4
  }
@@ -6,5 +6,45 @@ export interface IAmazonInstanceTypeCategory extends IInstanceTypeCategory {
6
6
  showCpuCredits?: boolean;
7
7
  descriptionListOverride?: string[];
8
8
  }
9
+ export interface IAmazonInstanceType extends IInstanceType {
10
+ defaultVCpus: number;
11
+ memoryInGiB: number;
12
+ hypervisor: string;
13
+ instanceStorageInfo?: IAmazonInstanceTypeStorageInfo;
14
+ ebsInfo?: IAmazonInstanceTypeEbsInfo;
15
+ gpuInfo?: IAmazonInstanceGpuInfo;
16
+ instanceStorageSupported: boolean;
17
+ currentGeneration: boolean;
18
+ bareMetal: boolean;
19
+ ipv6Supported?: boolean;
20
+ burstablePerformanceSupported: boolean;
21
+ supportedArchitectures: string[];
22
+ supportedUsageClasses: string[];
23
+ supportedRootDeviceTypes: string[];
24
+ supportedVirtualizationTypes: string[];
25
+ }
26
+ export interface IAmazonInstanceTypeStorageInfo {
27
+ storageTypes: string;
28
+ totalSizeInGB?: number;
29
+ nvmeSupport?: string;
30
+ }
31
+ export interface IAmazonInstanceTypeEbsInfo {
32
+ ebsOptimizedSupport: string;
33
+ nvmeSupport?: string;
34
+ encryptionSupport: string;
35
+ }
36
+ export interface IAmazonInstanceGpuInfo {
37
+ totalGpuMemoryInMiB: number;
38
+ gpus: IAmazonInstanceGpuDeviceInfo[];
39
+ }
40
+ export interface IAmazonInstanceGpuDeviceInfo {
41
+ name: string;
42
+ manufacturer: string;
43
+ count: number;
44
+ gpuSizeInMiB: number;
45
+ }
46
+ export interface IAmazonInstanceTypesByRegion extends IInstanceTypesByRegion {
47
+ [region: string]: IAmazonInstanceType[];
48
+ }
9
49
  export declare const AMAZON_INSTANCE_AWSINSTANCETYPE_SERVICE = "spinnaker.amazon.instanceType.service";
10
50
  export declare const name = "spinnaker.amazon.instanceType.service";
@@ -1,5 +1,6 @@
1
1
  import type { Application, CacheInitializerService, ISecurityGroup, IServerGroupCommand, IServerGroupCommandBackingData, IServerGroupCommandBackingDataFiltered, IServerGroupCommandDirty, IServerGroupCommandResult, IServerGroupCommandViewState, LoadBalancerReader, SecurityGroupReader, ServerGroupCommandRegistry } from '@spinnaker/core';
2
2
  import type { IAmazonLoadBalancerSourceData, IKeyPair, IScalingProcess } from '../../domain';
3
+ import type { IAmazonInstanceType } from '../../instance/awsInstanceType.service';
3
4
  export declare type IBlockDeviceMappingSource = 'source' | 'ami' | 'default';
4
5
  export interface IAmazonServerGroupCommandDirty extends IServerGroupCommandDirty {
5
6
  targetGroups?: string[];
@@ -10,6 +11,7 @@ export interface IAmazonServerGroupCommandResult extends IServerGroupCommandResu
10
11
  export interface IAmazonServerGroupCommandBackingDataFiltered extends IServerGroupCommandBackingDataFiltered {
11
12
  keyPairs: string[];
12
13
  targetGroups: string[];
14
+ instanceTypesInfo: IAmazonInstanceType[];
13
15
  }
14
16
  export interface IAmazonServerGroupCommandBackingData extends IServerGroupCommandBackingData {
15
17
  appLoadBalancers: IAmazonLoadBalancerSourceData[];
@@ -17,6 +19,7 @@ export interface IAmazonServerGroupCommandBackingData extends IServerGroupComman
17
19
  keyPairs: IKeyPair[];
18
20
  targetGroups: string[];
19
21
  scalingProcesses: IScalingProcess[];
22
+ instanceTypesInfo: IAmazonInstanceType[];
20
23
  }
21
24
  export interface IAmazonServerGroupCommandViewState extends IServerGroupCommandViewState {
22
25
  isNew: boolean;
@@ -79,6 +82,7 @@ export interface IAmazonServerGroupCommand extends IServerGroupCommand {
79
82
  spotAllocationStrategy?: string;
80
83
  spotInstancePools?: number;
81
84
  launchTemplateOverridesForInstanceType?: IAmazonInstanceTypeOverride[];
85
+ amiArchitecture: string;
82
86
  getBlockDeviceMappingsSource: (command: IServerGroupCommand) => IBlockDeviceMappingSource;
83
87
  selectBlockDeviceMappingsSource: (command: IServerGroupCommand, selection: string) => void;
84
88
  usePreferredZonesChanged: (command: IServerGroupCommand) => IAmazonServerGroupCommandResult;
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ import type { IAmazonInstanceType } from '../../../../../instance/awsInstanceType.service';
3
+ export declare function AmazonInstanceTypeInfoRenderer(props: {
4
+ instanceType: IAmazonInstanceType;
5
+ }): JSX.Element;
@@ -1,9 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import type { IAmazonPreferredInstanceType } from '../../../../../instance/awsInstanceType.service';
3
+ import type { IAmazonInstanceType } from '../../../../../instance/awsInstanceType.service';
3
4
  import type { IAmazonInstanceTypeOverride } from '../../../serverGroupConfiguration.service';
4
5
  export interface IRowProps {
5
6
  isCustom: boolean;
6
7
  selectedType?: IAmazonInstanceTypeOverride;
8
+ selectedTypeInfo?: IAmazonInstanceType;
7
9
  instanceTypeDetails?: IAmazonPreferredInstanceType;
8
10
  removeInstanceType?: (typeToRemove: string) => void;
9
11
  addOrUpdateInstanceType: (instanceType: string, weight: string) => void;
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import type { IAmazonInstanceType } from '../../../../../instance/awsInstanceType.service';
3
+ export interface InstanceTypeSelectProps {
4
+ availableInstanceTypesList: IAmazonInstanceType[];
5
+ addOrUpdateInstanceType: (type: string, weight: string) => void;
6
+ }
7
+ export declare function InstanceTypeSelect(props: InstanceTypeSelectProps): JSX.Element;
@@ -1,5 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import type { IAmazonInstanceTypeCategory } from '../../../../../instance/awsInstanceType.service';
3
+ import type { IAmazonInstanceType } from '../../../../../instance/awsInstanceType.service';
3
4
  import type { IAmazonInstanceTypeOverride } from '../../../serverGroupConfiguration.service';
4
5
  import './advancedMode.less';
5
6
  export interface IInstanceTypeTableProps {
@@ -7,7 +8,7 @@ export interface IInstanceTypeTableProps {
7
8
  selectedInstanceTypesMap: Map<string, IAmazonInstanceTypeOverride>;
8
9
  unlimitedCpuCreditsInCmd: boolean;
9
10
  profileDetails: IAmazonInstanceTypeCategory;
10
- availableInstanceTypesList: string[];
11
+ availableInstanceTypesList: IAmazonInstanceType[];
11
12
  handleInstanceTypesChange: (instanceTypes: IAmazonInstanceTypeOverride[]) => void;
12
13
  setUnlimitedCpuCredits: (unlimitedCpuCredits: boolean | undefined) => void;
13
14
  }
@@ -1,11 +1,13 @@
1
1
  /// <reference types="react" />
2
2
  import type { SortEnd } from 'react-sortable-hoc';
3
3
  import type { IInstanceTypeFamily } from '@spinnaker/core';
4
+ import type { IAmazonInstanceType } from '../../../../../instance/awsInstanceType.service';
4
5
  import type { IAmazonInstanceTypeOverride } from '../../../serverGroupConfiguration.service';
5
6
  export declare function InstanceTypeTableBody(props: {
6
7
  isCustom: boolean;
7
8
  profileFamiliesDetails?: IInstanceTypeFamily[];
8
9
  selectedInstanceTypesMap: Map<string, IAmazonInstanceTypeOverride>;
10
+ selectedInstanceTypesInfo?: IAmazonInstanceType[];
9
11
  addOrUpdateInstanceType: (instanceType: string, weight: string) => void;
10
12
  removeInstanceType: (instanceType: string) => void;
11
13
  handleSortEnd: (sortEnd: SortEnd) => void;
@@ -1,4 +1,6 @@
1
1
  /// <reference types="react" />
2
+ import type { IAmazonInstanceType } from '../../../../../instance/awsInstanceType.service';
3
+ import './advancedMode.less';
2
4
  export declare function Heading(props: {
3
5
  isCustom: boolean;
4
6
  profileLabel?: string;
@@ -10,6 +12,6 @@ export declare function Header(props: {
10
12
  }): JSX.Element;
11
13
  export declare function Footer(props: {
12
14
  isCustom: boolean;
13
- availableInstanceTypesList: string[];
15
+ availableInstanceTypesList: IAmazonInstanceType[];
14
16
  addOrUpdateInstanceType: (type: string, weight: string) => void;
15
17
  }): JSX.Element;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spinnaker/amazon",
3
3
  "license": "Apache-2.0",
4
- "version": "0.13.0",
4
+ "version": "0.13.1",
5
5
  "module": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
7
7
  "scripts": {
@@ -55,5 +55,5 @@
55
55
  "shx": "0.3.3",
56
56
  "typescript": "4.3.5"
57
57
  },
58
- "gitHead": "3efb67c7d040c3b549e9d3f589663f4e70c74390"
58
+ "gitHead": "12dc0b2f8cb61cc6ee529fa1a017890390e69d54"
59
59
  }
@@ -73,8 +73,26 @@ const helpContents: { [key: string]: string } = {
73
73
  'aws.serverGroup.odAllocationStrategy': `The only strategy / <b>default is 'prioritized'</b>. The order specified in the list of selected instance types is used to determine which instance type to use first when fulfilling On-Demand capacity.`,
74
74
  'aws.serverGroup.odBase': `Minimum amount of the Auto Scaling Group's capacity that must be fulfilled by On-Demand Instances. This base portion is provisioned first as the group scales. <b>Default: 0.</b>`,
75
75
  'aws.serverGroup.odPercentAboveBase': `Percentages of On-Demand and Spot instances for additional capacity beyond OnDemandBaseCapacity.<b>Default: 100.</b>`,
76
- 'aws.serverGroup.instanceTypeWeight': `The number of capacity units gives the instance type a proportional weight to other instance types. When specified, weights count towards desired capacity.`,
76
+ 'aws.serverGroup.instanceTypeWeight': `The number of capacity units gives the instance type a proportional weight to other instance types. When specified, weights count towards desired capacity.
77
+ Learn more in <a target="_blank" href="https://spinnaker.io/docs/setup/other_config/server-group-launch-settings/aws-ec2/launch-templates/#convert-a-server-group-with-launch-template-to-use-mixed-instances-policy-with-multiple-instance-types-and-capacity-weighting">examples and docs</a>.`,
77
78
  'aws.serverGroup.instanceTypes': `Specify up to 20 instance types.`,
79
+ 'aws.serverGroup.instanceTypesSelect': `<p>Filter instance types on one or more criteria, comma separated:
80
+ <ul>
81
+ <li>Minimum vCPU e.g. 16vcpu</li>
82
+ <li>Minimum memory e.g. 32gib</li>
83
+ <li>Spot support</li>
84
+ <li>EBS support</li>
85
+ <li>GPU support</li>
86
+ <li>Instance storage type e.g. ssd</li>
87
+ <li>Generation with 'currentGen' / 'oldGen'</li>
88
+ <li>Instance family / size / type e.g. c3 / large / c3.large</li>
89
+ </ul>
90
+ Examples:
91
+ <ul>
92
+ <li>16vcpu, 32gib, spot, oldGen</li>
93
+ <li>medium, ebs</li>
94
+ <li>ssd,ebs,gpu,currentgen</li>
95
+ </ul>`,
78
96
  'aws.serverGroup.multipleInstanceTypes': `Instance types a server group can launch, first (highest priority) to last (lowest priority).`,
79
97
  'aws.serverGroup.unlimitedCpuCredits': `<p>CPU credits can be configured with 2 modes:</p><br/>
80
98
  <ul>
@@ -8,6 +8,7 @@ export interface IAmazonImage {
8
8
  [region: string]: string[];
9
9
  };
10
10
  attributes: {
11
+ architecture: string;
11
12
  creationDate: string;
12
13
  virtualizationType: string;
13
14
  };
@@ -12,20 +12,132 @@ describe('Service: InstanceType', function () {
12
12
  this.awsInstanceTypeService = _awsInstanceTypeService_;
13
13
 
14
14
  this.allTypes = [
15
- { account: 'test', region: 'us-west-2', name: 'm1.small', availabilityZone: 'us-west-2a' },
16
- { account: 'test', region: 'us-west-2', name: 'm2.xlarge', availabilityZone: 'us-west-2b' },
17
- { account: 'test', region: 'eu-west-1', name: 'hs1.8xlarge', availabilityZone: 'eu-west-1c' },
18
- { account: 'test', region: 'eu-west-1', name: 'm2.xlarge', availabilityZone: 'eu-west-1c' },
19
- { account: 'test', region: 'us-east-1', name: 'm4.2xlarge', availabilityZone: 'us-east-1c' },
20
- { account: 'test', region: 'us-east-1', name: 't2.nano', availabilityZone: 'us-east-1c' },
21
- { account: 'test', region: 'us-east-1', name: 't2.micro', availabilityZone: 'us-east-1c' },
22
- { account: 'test', region: 'us-east-1', name: 'm4.xlarge', availabilityZone: 'us-east-1c' },
23
- { account: 'test', region: 'us-east-1', name: 'm4.4xlarge', availabilityZone: 'us-east-1c' },
24
- { account: 'test', region: 'us-east-1', name: 't2.medium', availabilityZone: 'us-east-1c' },
25
- { account: 'test', region: 'us-east-1', name: 'm4.large', availabilityZone: 'us-east-1c' },
26
- { account: 'test', region: 'us-east-1', name: 'm4.16xlarge', availabilityZone: 'us-east-1c' },
27
- { account: 'test', region: 'us-east-1', name: 'm4.10xlarge', availabilityZone: 'us-east-1c' },
28
- { account: 'test', region: 'us-east-1', name: 't2.loltiny', availabilityZone: 'us-east-1c' },
15
+ {
16
+ account: 'test',
17
+ region: 'us-west-2',
18
+ name: 'm1.small',
19
+ defaultVCpus: 1,
20
+ memoryInGiB: 1,
21
+ supportedArchitectures: ['i386', 'x86_64'],
22
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
23
+ },
24
+ {
25
+ account: 'test',
26
+ region: 'us-west-2',
27
+ name: 'm2.xlarge',
28
+ defaultVCpus: 2,
29
+ memoryInGiB: 17,
30
+ supportedArchitectures: ['x86_64'],
31
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
32
+ },
33
+ {
34
+ account: 'test',
35
+ region: 'eu-west-1',
36
+ name: 'hs1.8xlarge',
37
+ defaultVCpus: 32,
38
+ memoryInGiB: 256,
39
+ supportedArchitectures: ['i386', 'x86_64'],
40
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
41
+ },
42
+ {
43
+ account: 'test',
44
+ region: 'eu-west-1',
45
+ name: 'm2.xlarge',
46
+ defaultVCpus: 2,
47
+ memoryInGiB: 17,
48
+ supportedArchitectures: ['x86_64'],
49
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
50
+ },
51
+ {
52
+ account: 'test',
53
+ region: 'us-east-1',
54
+ name: 'm4.2xlarge',
55
+ defaultVCpus: 8,
56
+ memoryInGiB: 32,
57
+ supportedArchitectures: ['x86_64'],
58
+ supportedVirtualizationTypes: ['hvm'],
59
+ },
60
+ {
61
+ account: 'test',
62
+ region: 'us-east-1',
63
+ name: 't2.nano',
64
+ defaultVCpus: 1,
65
+ memoryInGiB: 0,
66
+ supportedArchitectures: ['i386', 'x86_64'],
67
+ supportedVirtualizationTypes: ['hvm'],
68
+ },
69
+ {
70
+ account: 'test',
71
+ region: 'us-east-1',
72
+ name: 't2.micro',
73
+ defaultVCpus: 1,
74
+ memoryInGiB: 1,
75
+ supportedArchitectures: ['i386', 'x86_64'],
76
+ supportedVirtualizationTypes: ['hvm'],
77
+ },
78
+ {
79
+ account: 'test',
80
+ region: 'us-east-1',
81
+ name: 'm4.xlarge',
82
+ defaultVCpus: 4,
83
+ memoryInGiB: 16,
84
+ supportedArchitectures: ['x86_64'],
85
+ supportedVirtualizationTypes: ['hvm'],
86
+ },
87
+ {
88
+ account: 'test',
89
+ region: 'us-east-1',
90
+ name: 'm4.4xlarge',
91
+ defaultVCpus: 16,
92
+ memoryInGiB: 64,
93
+ supportedArchitectures: ['x86_64'],
94
+ supportedVirtualizationTypes: ['hvm'],
95
+ },
96
+ {
97
+ account: 'test',
98
+ region: 'us-east-1',
99
+ name: 't2.medium',
100
+ defaultVCpus: 2,
101
+ memoryInGiB: 4,
102
+ supportedArchitectures: ['i386', 'x86_64'],
103
+ supportedVirtualizationTypes: ['hvm'],
104
+ },
105
+ {
106
+ account: 'test',
107
+ region: 'us-east-1',
108
+ name: 'm4.large',
109
+ defaultVCpus: 2,
110
+ memoryInGiB: 8,
111
+ supportedArchitectures: ['x86_64'],
112
+ supportedVirtualizationTypes: ['hvm'],
113
+ },
114
+ {
115
+ account: 'test',
116
+ region: 'us-east-1',
117
+ name: 'm4.16xlarge',
118
+ defaultVCpus: 64,
119
+ memoryInGiB: 256,
120
+ supportedArchitectures: ['x86_64'],
121
+ supportedVirtualizationTypes: ['hvm'],
122
+ },
123
+ {
124
+ account: 'test',
125
+ region: 'us-east-1',
126
+ name: 'm4.10xlarge',
127
+ defaultVCpus: 40,
128
+ memoryInGiB: 160,
129
+ supportedArchitectures: ['x86_64'],
130
+ supportedVirtualizationTypes: ['hvm'],
131
+ },
132
+ {
133
+ account: 'test',
134
+ region: 'us-east-1',
135
+ name: 't2.loltiny',
136
+ defaultVCpus: 1,
137
+ memoryInGiB: 0,
138
+ supportedArchitectures: ['i386', 'x86_64'],
139
+ supportedVirtualizationTypes: ['hvm'],
140
+ },
29
141
  ];
30
142
  }),
31
143
  );
@@ -59,7 +171,28 @@ describe('Service: InstanceType', function () {
59
171
  });
60
172
 
61
173
  await http.flush();
62
- expect(results).toEqual(['m1.small', 'm2.xlarge']);
174
+ expect(results).toEqual([
175
+ {
176
+ account: 'test',
177
+ region: 'us-west-2',
178
+ name: 'm1.small',
179
+ defaultVCpus: 1,
180
+ memoryInGiB: 1,
181
+ supportedArchitectures: ['i386', 'x86_64'],
182
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
183
+ key: 'us-west-2:test:m1.small',
184
+ },
185
+ {
186
+ account: 'test',
187
+ region: 'us-west-2',
188
+ name: 'm2.xlarge',
189
+ defaultVCpus: 2,
190
+ memoryInGiB: 17,
191
+ supportedArchitectures: ['x86_64'],
192
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
193
+ key: 'us-west-2:test:m2.xlarge',
194
+ },
195
+ ]);
63
196
  });
64
197
 
65
198
  it('returns empty list for region with no instance types', async function () {
@@ -89,22 +222,7 @@ describe('Service: InstanceType', function () {
89
222
  });
90
223
 
91
224
  await http.flush();
92
- expect(results).toEqual(['m2.xlarge']);
93
- });
94
-
95
- it('filters instance types by VPC and virtualization type', function () {
96
- const types = ['c4.a', 'c3.a', 'c4.a', 'c1.a'];
97
- const service = this.awsInstanceTypeService;
98
- expect(service.filterInstanceTypes(types, 'hvm', true)).toEqual(['c4.a', 'c3.a', 'c4.a']);
99
- expect(service.filterInstanceTypes(types, 'hvm', false)).toEqual(['c3.a']);
100
- expect(service.filterInstanceTypes(types, 'paravirtual', true)).toEqual(['c3.a', 'c1.a']);
101
- expect(service.filterInstanceTypes(types, 'paravirtual', false)).toEqual(['c3.a', 'c1.a']);
102
- });
103
-
104
- it('assumes HVM is supported for unknown families', function () {
105
- const types = ['c400.a', 'c300.a', 'c3.a', 'c1.a'];
106
- const service = this.awsInstanceTypeService;
107
- expect(service.filterInstanceTypes(types, 'hvm', true)).toEqual(['c400.a', 'c300.a', 'c3.a']);
225
+ expect(map(results, 'name')).toEqual(['m2.xlarge']);
108
226
  });
109
227
 
110
228
  it('sorts instance types by family then class size', async function () {
@@ -119,7 +237,7 @@ describe('Service: InstanceType', function () {
119
237
  });
120
238
 
121
239
  await http.flush();
122
- expect(results).toEqual([
240
+ expect(map(results, 'name')).toEqual([
123
241
  'm4.large',
124
242
  'm4.xlarge',
125
243
  'm4.2xlarge',
@@ -134,6 +252,81 @@ describe('Service: InstanceType', function () {
134
252
  });
135
253
  });
136
254
 
255
+ describe('filterInstanceTypes', function () {
256
+ const instanceTypes = [
257
+ {
258
+ account: 'test',
259
+ region: 'us-west-2',
260
+ name: 'm1.small',
261
+ defaultVCpus: 1,
262
+ memoryInGiB: 1,
263
+ supportedArchitectures: ['i386', 'x86_64'],
264
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
265
+ },
266
+ {
267
+ account: 'test',
268
+ region: 'eu-west-1',
269
+ name: 'hs1.8xlarge',
270
+ defaultVCpus: 32,
271
+ memoryInGiB: 256,
272
+ supportedArchitectures: ['i386', 'x86_64'],
273
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
274
+ },
275
+ {
276
+ account: 'test',
277
+ region: 'eu-west-1',
278
+ name: 'm2.xlarge',
279
+ defaultVCpus: 2,
280
+ memoryInGiB: 17,
281
+ supportedArchitectures: ['x86_64'],
282
+ supportedVirtualizationTypes: ['hvm', 'paravirtual'],
283
+ },
284
+ {
285
+ account: 'test',
286
+ region: 'us-east-1',
287
+ name: 'm4.2xlarge',
288
+ defaultVCpus: 8,
289
+ memoryInGiB: 32,
290
+ supportedArchitectures: ['x86_64'],
291
+ supportedVirtualizationTypes: ['hvm'],
292
+ },
293
+ {
294
+ account: 'test',
295
+ region: 'us-east-1',
296
+ name: 't2.nano',
297
+ defaultVCpus: 1,
298
+ memoryInGiB: 0,
299
+ supportedArchitectures: ['i386', 'x86_64'],
300
+ supportedVirtualizationTypes: ['hvm'],
301
+ },
302
+ ];
303
+
304
+ it('filters instance types by VPC, virtualization type and architecture', function () {
305
+ const service = this.awsInstanceTypeService;
306
+ expect(map(service.filterInstanceTypes(instanceTypes, 'hvm', true, 'x86_64'), 'name')).toEqual([
307
+ 'm1.small',
308
+ 'hs1.8xlarge',
309
+ 'm2.xlarge',
310
+ 'm4.2xlarge',
311
+ 't2.nano',
312
+ ]);
313
+ expect(map(service.filterInstanceTypes(instanceTypes, 'hvm', false, 'x86_64'), 'name')).toEqual([
314
+ 'm1.small',
315
+ 'hs1.8xlarge',
316
+ 'm2.xlarge',
317
+ ]);
318
+ expect(map(service.filterInstanceTypes(instanceTypes, 'hvm', true, 'i386'), 'name')).toEqual([
319
+ 'm1.small',
320
+ 'hs1.8xlarge',
321
+ 't2.nano',
322
+ ]);
323
+ expect(map(service.filterInstanceTypes(instanceTypes, 'paravirtual', true, 'i386'), 'name')).toEqual([
324
+ 'm1.small',
325
+ 'hs1.8xlarge',
326
+ ]);
327
+ });
328
+ });
329
+
137
330
  describe('isBurstingSupportedForAllTypes', function () {
138
331
  const testInputs = [
139
332
  { types: ['t2.small', 't3.nano', 't3a.medium', 't4g.large'], result: true },
@@ -21,6 +21,54 @@ export interface IAmazonInstanceTypeCategory extends IInstanceTypeCategory {
21
21
  descriptionListOverride?: string[];
22
22
  }
23
23
 
24
+ export interface IAmazonInstanceType extends IInstanceType {
25
+ defaultVCpus: number;
26
+ memoryInGiB: number;
27
+ hypervisor: string;
28
+ instanceStorageInfo?: IAmazonInstanceTypeStorageInfo;
29
+ ebsInfo?: IAmazonInstanceTypeEbsInfo;
30
+ gpuInfo?: IAmazonInstanceGpuInfo;
31
+
32
+ instanceStorageSupported: boolean;
33
+ currentGeneration: boolean;
34
+ bareMetal: boolean;
35
+ ipv6Supported?: boolean;
36
+ burstablePerformanceSupported: boolean;
37
+
38
+ supportedArchitectures: string[];
39
+ supportedUsageClasses: string[];
40
+ supportedRootDeviceTypes: string[];
41
+ supportedVirtualizationTypes: string[];
42
+ }
43
+
44
+ export interface IAmazonInstanceTypeStorageInfo {
45
+ storageTypes: string;
46
+ totalSizeInGB?: number;
47
+ nvmeSupport?: string;
48
+ }
49
+
50
+ export interface IAmazonInstanceTypeEbsInfo {
51
+ ebsOptimizedSupport: string;
52
+ nvmeSupport?: string;
53
+ encryptionSupport: string;
54
+ }
55
+
56
+ export interface IAmazonInstanceGpuInfo {
57
+ totalGpuMemoryInMiB: number;
58
+ gpus: IAmazonInstanceGpuDeviceInfo[];
59
+ }
60
+
61
+ export interface IAmazonInstanceGpuDeviceInfo {
62
+ name: string;
63
+ manufacturer: string;
64
+ count: number;
65
+ gpuSizeInMiB: number;
66
+ }
67
+
68
+ export interface IAmazonInstanceTypesByRegion extends IInstanceTypesByRegion {
69
+ [region: string]: IAmazonInstanceType[];
70
+ }
71
+
24
72
  export const AMAZON_INSTANCE_AWSINSTANCETYPE_SERVICE = 'spinnaker.amazon.instanceType.service';
25
73
  export const name = AMAZON_INSTANCE_AWSINSTANCETYPE_SERVICE; // for backwards compatibility
26
74
 
@@ -31,16 +79,14 @@ module(AMAZON_INSTANCE_AWSINSTANCETYPE_SERVICE, []).factory('awsInstanceTypeServ
31
79
  return $q.when(categories);
32
80
  }
33
81
 
34
- const getAllTypesByRegion = function getAllTypesByRegion(): PromiseLike<IInstanceTypesByRegion> {
82
+ const getAllTypesByRegion = function getAllTypesByRegion(): PromiseLike<IAmazonInstanceTypesByRegion> {
35
83
  return REST('/instanceTypes')
36
84
  .get()
37
85
  .then(function (types) {
38
86
  return _.chain(types)
39
- .map(function (type: IInstanceType) {
87
+ .map(function (type: IAmazonInstanceType) {
40
88
  return {
41
- region: type.region,
42
- account: type.account,
43
- name: type.name,
89
+ ...type,
44
90
  key: [type.region, type.account, type.name].join(':'),
45
91
  };
46
92
  })
@@ -95,47 +141,57 @@ module(AMAZON_INSTANCE_AWSINSTANCETYPE_SERVICE, []).factory('awsInstanceTypeServ
95
141
  return 0;
96
142
  }
97
143
 
98
- function getAvailableTypesForRegions(availableInstanceTypes: IInstanceTypesByRegion, selectedRegions: string[]) {
144
+ function getAvailableTypesForRegions(
145
+ availableInstanceTypes: IAmazonInstanceTypesByRegion,
146
+ selectedRegions: string[],
147
+ ): IAmazonInstanceType[] {
99
148
  selectedRegions = selectedRegions || [];
100
- let availableTypes: string[] = [];
149
+ let availableTypes: IAmazonInstanceType[] = [];
101
150
 
102
151
  // prime the list of available types
103
152
  if (selectedRegions && selectedRegions.length) {
104
- availableTypes = _.map(availableInstanceTypes[selectedRegions[0]], 'name');
153
+ availableTypes = availableInstanceTypes[selectedRegions[0]] || [];
105
154
  }
106
155
 
107
156
  // this will perform an unnecessary intersection with the first region, which is fine
108
157
  selectedRegions.forEach(function (selectedRegion) {
109
158
  if (availableInstanceTypes[selectedRegion]) {
110
- availableTypes = _.intersection(availableTypes, _.map(availableInstanceTypes[selectedRegion], 'name'));
159
+ availableTypes = _.intersectionBy(availableTypes, availableInstanceTypes[selectedRegion], 'name');
111
160
  }
112
161
  });
113
162
 
114
- return availableTypes.sort(sortTypesByFamilyAndSize);
163
+ return availableTypes?.sort((a, b) => sortTypesByFamilyAndSize(a.name, b.name));
115
164
  }
116
165
 
117
166
  const families: { [key: string]: string[] } = {
118
- paravirtual: ['c1', 'c3', 'hi1', 'hs1', 'm1', 'm2', 'm3', 't1'],
119
- hvm: ['c3', 'c4', 'd2', 'i2', 'g2', 'm3', 'm4', 'm5', 'p2', 'r3', 'r4', 'r5', 't2', 'x1'],
120
- vpcOnly: ['c4', 'm4', 'm5', 'r4', 'r5', 't2', 'x1'],
167
+ ec2ClassicSupported: ['m1', 'm3', 't1', 'c1', 'c3', 'cc2', 'cr1', 'm2', 'r3', 'd2', 'hs1', 'i2', 'g2'], // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-classic-platform.html#ec2-classic-instance-types
121
168
  ebsOptimized: ['c4', 'd2', 'f1', 'g3', 'i3', 'm4', 'm5', 'p2', 'r4', 'r5', 'x1'],
122
169
  burstablePerf: ['t2', 't3', 't3a', 't4g'],
123
170
  };
124
171
 
125
- function filterInstanceTypes(instanceTypes: string[], virtualizationType: string, vpcOnly: boolean): string[] {
126
- return instanceTypes.filter((instanceType: string) => {
127
- if (virtualizationType === '*') {
172
+ function filterInstanceTypes(
173
+ instanceTypes: IAmazonInstanceType[],
174
+ virtualizationType: string,
175
+ vpcConfigured: boolean,
176
+ architecture: string,
177
+ ): IAmazonInstanceType[] {
178
+ return _.filter(instanceTypes, function (i) {
179
+ if (virtualizationType === '*' && architecture === '*') {
128
180
  // show all instance types
129
181
  return true;
130
182
  }
131
- const [family] = instanceType.split('.');
132
- if (!vpcOnly && families.vpcOnly.includes(family)) {
183
+
184
+ if (!vpcConfigured && !families.ec2ClassicSupported.includes(i.name.split('.')[0])) {
133
185
  return false;
134
186
  }
135
- if (!families.paravirtual.includes(family) && virtualizationType === 'hvm') {
136
- return true;
187
+ if (virtualizationType && !i.supportedVirtualizationTypes.includes(virtualizationType)) {
188
+ return false;
189
+ }
190
+ if (architecture && !i.supportedArchitectures.includes(architecture)) {
191
+ return false;
137
192
  }
138
- return families[virtualizationType].includes(family);
193
+
194
+ return true;
139
195
  });
140
196
  }
141
197
 
@@ -59,7 +59,7 @@ export class AmazonImageSelectInput extends React.Component<IAmazonImageSelector
59
59
 
60
60
  // assume that the specific image exists in the selected region
61
61
  const amis = { [region]: [imageId] };
62
- const attributes = { virtualizationType: '*', creationDate: new Date().toISOString() };
62
+ const attributes = { virtualizationType: '*', architecture: '*', creationDate: new Date().toISOString() };
63
63
 
64
64
  return { imageName, amis, attributes } as IAmazonImage;
65
65
  }