feat(api): add EC2 Auto Scaling groups to the cloud explorer
CI / checks (pull_request) Successful in 26m54s
CI / checks (pull_request) Successful in 26m54s
Create groups from a launch template (in the default subnets unless given), change their minimum, desired and maximum capacity, replace or remove an instance, and follow the launches and terminations TheCloud's reconciler makes. Deleting a group terminates its instances. Scaling policies are not offered: the runtime stores them but its alarms only drive ECS scaling.
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import type {CloudProvider, FieldSchema, ServiceSchema, TableColumnSchema} from './types'
|
||||
|
||||
/** CreateAutoScalingGroup's name rule: 1 to 255 characters, no colon. */
|
||||
export const AUTO_SCALING_GROUP_NAME_PATTERN = '^[^:]{1,255}$'
|
||||
/** A capacity the console accepts; AWS's own ceiling is far above what a laptop can run. */
|
||||
export const AUTO_SCALING_MAX_INSTANCES = 20
|
||||
|
||||
const groupColumns: TableColumnSchema[] = [
|
||||
{name: 'name', label: 'Name'},
|
||||
{name: 'capacity', label: 'Instances', path: 'metadata.capacity'},
|
||||
{name: 'desired', label: 'Desired', path: 'metadata.desiredCapacity'},
|
||||
{name: 'min', label: 'Min', path: 'metadata.minSize'},
|
||||
{name: 'max', label: 'Max', path: 'metadata.maxSize'},
|
||||
{name: 'launchTemplate', label: 'Launch template', path: 'metadata.launchTemplateName', emptyText: '—'},
|
||||
{name: 'createdAt', label: 'Created', format: 'datetime'},
|
||||
]
|
||||
|
||||
const groupFilters: FieldSchema[] = [{name: 'search', label: 'Search', type: 'text', required: false}]
|
||||
|
||||
const capacity = {pattern: '^\\d{1,2}$', message: `Use a whole number from 0 to ${AUTO_SCALING_MAX_INSTANCES}`}
|
||||
|
||||
export function awsAutoScalingSchema(): ServiceSchema {
|
||||
return {
|
||||
cloud: 'aws',
|
||||
service: 'autoscaling',
|
||||
displayName: 'EC2 Auto Scaling groups',
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
validation: {pattern: AUTO_SCALING_GROUP_NAME_PATTERN, message: 'Use up to 255 characters, without a colon'},
|
||||
},
|
||||
{
|
||||
name: 'launchTemplate',
|
||||
label: 'Launch template',
|
||||
type: 'text',
|
||||
required: true,
|
||||
description: 'The name or ID (lt-…) of an EC2 launch template. New instances use its image and instance type.',
|
||||
},
|
||||
{
|
||||
name: 'launchTemplateVersion',
|
||||
label: 'Template version',
|
||||
type: 'text',
|
||||
required: false,
|
||||
defaultValue: '$Latest',
|
||||
description: 'A version number, $Latest or $Default.',
|
||||
validation: {pattern: '^(\\d+|\\$Latest|\\$Default)$', message: 'Use a version number, $Latest or $Default'},
|
||||
},
|
||||
{name: 'minSize', label: 'Minimum', type: 'text', required: true, defaultValue: '1', validation: capacity},
|
||||
{name: 'desiredCapacity', label: 'Desired', type: 'text', required: false, defaultValue: '1', validation: capacity, description: 'How many instances to run now. Between the minimum and the maximum.'},
|
||||
{name: 'maxSize', label: 'Maximum', type: 'text', required: true, defaultValue: '2', validation: capacity},
|
||||
{
|
||||
name: 'subnets',
|
||||
label: 'Subnets',
|
||||
type: 'text',
|
||||
required: false,
|
||||
span: true,
|
||||
description: 'Subnet IDs to launch into, separated by commas. Leave empty for the default subnets.',
|
||||
validation: {pattern: '^\\s*subnet-[\\w-]+(\\s*,\\s*subnet-[\\w-]+)*\\s*$', message: 'Use subnet IDs separated by commas'},
|
||||
},
|
||||
{
|
||||
name: 'targetGroupArns',
|
||||
label: 'Target groups',
|
||||
type: 'textarea',
|
||||
required: false,
|
||||
span: true,
|
||||
description: 'Optional load balancer target group ARNs, one per line. Instances are registered with them as they launch.',
|
||||
},
|
||||
{
|
||||
name: 'healthCheckType',
|
||||
label: 'Health check',
|
||||
type: 'select',
|
||||
required: false,
|
||||
defaultValue: 'EC2',
|
||||
options: [
|
||||
{label: 'EC2 instance status', value: 'EC2'},
|
||||
{label: 'Load balancer health checks', value: 'ELB'},
|
||||
],
|
||||
},
|
||||
],
|
||||
actions: ['list', 'create', 'delete', 'inspect'],
|
||||
capabilities: {
|
||||
resourceActions: [
|
||||
{name: 'list', label: 'List Auto Scaling groups', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'create', label: 'Create Auto Scaling group', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete group and its instances', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'inspect', label: 'Inspect Auto Scaling group', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
autoScalingActions: [
|
||||
{name: 'setCapacity', label: 'Change minimum, desired and maximum', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'terminateInstance', label: 'Terminate an instance', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
},
|
||||
filters: groupFilters,
|
||||
columns: groupColumns,
|
||||
}
|
||||
}
|
||||
|
||||
export function autoScalingSchemaFor(cloud: CloudProvider): ServiceSchema | null {
|
||||
return cloud === 'aws' ? awsAutoScalingSchema() : null
|
||||
}
|
||||
@@ -74,6 +74,13 @@ export const SERVICE_CATALOG = {
|
||||
order: 20,
|
||||
},
|
||||
serverless: {displayName: 'Serverless', iconKey: 'serverless', group: 'Compute', order: 30},
|
||||
autoscaling: {
|
||||
displayName: 'Auto Scaling',
|
||||
displayNameByCloud: {aws: 'EC2 Auto Scaling'},
|
||||
iconKey: 'autoscaling',
|
||||
group: 'Compute',
|
||||
order: 15,
|
||||
},
|
||||
containers: {
|
||||
displayName: 'Containers',
|
||||
displayNameByCloud: {gcp: 'Cloud Run'},
|
||||
|
||||
@@ -186,6 +186,7 @@ export type UserPoolActionName =
|
||||
| 'describeClient'
|
||||
| 'updateClientOAuth'
|
||||
export type DistributionActionName = 'setEnabled' | 'createInvalidation'
|
||||
export type AutoScalingActionName = 'setCapacity' | 'terminateInstance'
|
||||
export type CertificateActionName = 'download' | 'export' | 'revoke'
|
||||
export type MonitoringActionName = 'listMetrics' | 'getMetricData' | 'alarmHistory' | 'setAlarmState' | 'setAlarmActions'
|
||||
export type HttpApiActionName =
|
||||
@@ -246,6 +247,7 @@ export interface ServiceSchema {
|
||||
kubernetesActions?: CapabilitySchema<KubernetesActionName>[]
|
||||
userPoolActions?: CapabilitySchema<UserPoolActionName>[]
|
||||
distributionActions?: CapabilitySchema<DistributionActionName>[]
|
||||
autoScalingActions?: CapabilitySchema<AutoScalingActionName>[]
|
||||
certificateActions?: CapabilitySchema<CertificateActionName>[]
|
||||
monitoringActions?: CapabilitySchema<MonitoringActionName>[]
|
||||
/** API Gateway v2 (HTTP and WebSocket APIs): what the routes, stages and security panel can do. */
|
||||
@@ -537,6 +539,13 @@ export type CertificateRevocationReason =
|
||||
| 'CESSATION_OF_OPERATION'
|
||||
| 'PRIVILEGE_WITHDRAWN'
|
||||
|
||||
/** Any of the three may be left out to keep its current value. */
|
||||
export interface AutoScalingCapacityInput {
|
||||
minSize?: number
|
||||
desiredCapacity?: number
|
||||
maxSize?: number
|
||||
}
|
||||
|
||||
export interface DistributionInvalidation {
|
||||
id: string
|
||||
status: string
|
||||
@@ -1204,6 +1213,9 @@ export interface CloudServiceAdapter {
|
||||
setAlarmState?(alarmName: string, state: AlarmStateValue, reason: string): Promise<void>
|
||||
setAlarmActionsEnabled?(alarmName: string, enabled: boolean): Promise<void>
|
||||
createDistributionInvalidation?(distributionId: string, paths: string[]): Promise<DistributionInvalidation>
|
||||
setAutoScalingCapacity?(groupName: string, input: AutoScalingCapacityInput): Promise<CloudResource>
|
||||
/** With `replace`, the group launches a new instance in its place; otherwise desired capacity drops by one. */
|
||||
terminateAutoScalingInstance?(groupName: string, instanceId: string, replace: boolean): Promise<void>
|
||||
getCertificatePem?(certificateId: string): Promise<CertificatePem>
|
||||
exportCertificate?(certificateId: string, passphrase: string): Promise<ExportedCertificate>
|
||||
revokeCertificate?(certificateId: string, reason: CertificateRevocationReason): Promise<CloudResource>
|
||||
|
||||
Reference in New Issue
Block a user