feat: fully functioning ALB
This commit is contained in:
@@ -12,6 +12,25 @@ const computeFilters: FieldSchema[] = [
|
||||
{name: 'search', label: 'Search', type: 'text', required: false},
|
||||
]
|
||||
|
||||
const awsComputeFilters: FieldSchema[] = [
|
||||
...computeFilters,
|
||||
{
|
||||
name: 'state',
|
||||
label: 'Lifecycle state',
|
||||
type: 'select',
|
||||
required: false,
|
||||
options: [
|
||||
{label: 'All states', value: ''},
|
||||
{label: 'Running', value: 'running'},
|
||||
{label: 'Stopped', value: 'stopped'},
|
||||
{label: 'Pending', value: 'pending'},
|
||||
{label: 'Stopping', value: 'stopping'},
|
||||
{label: 'Shutting down', value: 'shutting-down'},
|
||||
{label: 'Terminated', value: 'terminated'},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const computeFields: FieldSchema[] = [
|
||||
// ── Required ──────────────────────────────────────────────────────
|
||||
{
|
||||
@@ -234,7 +253,7 @@ export function awsComputeSchema(): ServiceSchema {
|
||||
displayName: 'Compute',
|
||||
fields: computeFields,
|
||||
actions: ['list', 'inspect', 'create', 'delete'],
|
||||
filters: computeFilters,
|
||||
filters: awsComputeFilters,
|
||||
columns: computeColumns,
|
||||
capabilities: {
|
||||
resourceActions: [
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import type {ItemActionName} from './childCollections'
|
||||
import type {CapabilitySchema, FieldSchema, ResourceActionName, ServiceSchema, TableColumnSchema} from './types'
|
||||
|
||||
const resourceActions: CapabilitySchema<ResourceActionName>[] = [
|
||||
{name: 'list', label: 'List repositories', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'create', label: 'Create repository', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete repository', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'inspect', label: 'Inspect repository', enabled: true, status: 'available', runtimeRequired: false},
|
||||
]
|
||||
|
||||
const itemActions: CapabilitySchema<ItemActionName>[] = [
|
||||
{name: 'list', label: 'List images', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete image', enabled: true, status: 'available', runtimeRequired: true},
|
||||
]
|
||||
|
||||
const fields: FieldSchema[] = [
|
||||
{
|
||||
name: 'repositoryName',
|
||||
label: 'Repository name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
description: 'Use lowercase letters, numbers, and separators. Names may include namespaces separated by slashes.',
|
||||
validation: {
|
||||
pattern: '^(?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)*[a-z0-9]+(?:[._-][a-z0-9]+)*$',
|
||||
minLength: 2,
|
||||
maxLength: 256,
|
||||
message: 'Use a valid ECR repository name.',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const columns: TableColumnSchema[] = [
|
||||
{name: 'name', label: 'Name'},
|
||||
{name: 'uri', label: 'URI', path: 'metadata.repositoryUri', format: 'code'},
|
||||
{name: 'tagMutability', label: 'Tag mutability', path: 'metadata.imageTagMutability', format: 'badge'},
|
||||
{name: 'createdAt', label: 'Created at', format: 'datetime'},
|
||||
]
|
||||
|
||||
export function awsEcrSchema(): ServiceSchema {
|
||||
return {
|
||||
cloud: 'aws',
|
||||
service: 'ecr',
|
||||
displayName: 'ECR',
|
||||
fields,
|
||||
actions: ['list', 'create', 'delete', 'inspect'],
|
||||
capabilities: {resourceActions, itemActions},
|
||||
filters: [{name: 'search', label: 'Search', type: 'text', required: false}],
|
||||
columns,
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ const loadBalancerColumns: TableColumnSchema[] = [
|
||||
|
||||
const loadBalancerFilters: FieldSchema[] = [{name: 'search', label: 'Search', type: 'text', required: false}]
|
||||
|
||||
export const ELB_TYPES = ['application', 'network'] as const
|
||||
export const ELB_SCHEMES = ['internet-facing', 'internal'] as const
|
||||
|
||||
/** ELBv2 names: up to 32 chars, alphanumerics and hyphens, no leading/trailing hyphen. */
|
||||
@@ -48,14 +47,6 @@ export function awsLoadBalancingSchema(): ServiceSchema {
|
||||
description:
|
||||
'Two or more subnet ids, comma separated — e.g. subnet-aaa, subnet-bbb. ELB requires them to be in different availability zones.',
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
label: 'Type',
|
||||
type: 'select',
|
||||
required: false,
|
||||
description: 'Defaults to application.',
|
||||
options: ELB_TYPES.map((value) => ({label: value, value})),
|
||||
},
|
||||
{
|
||||
name: 'scheme',
|
||||
label: 'Scheme',
|
||||
@@ -65,7 +56,10 @@ export function awsLoadBalancingSchema(): ServiceSchema {
|
||||
options: ELB_SCHEMES.map((value) => ({label: value, value})),
|
||||
},
|
||||
],
|
||||
actions: ['list', 'create', 'delete', 'inspect'],
|
||||
actions: ['list', 'create', 'update', 'delete', 'inspect'],
|
||||
updateFields: [
|
||||
{name: 'securityGroups', label: 'Security Groups', type: 'text', required: true, valuePath: 'metadata.securityGroups'},
|
||||
],
|
||||
capabilities: {
|
||||
resourceActions: [
|
||||
{name: 'list', label: 'List load balancers', enabled: true, status: 'available', runtimeRequired: true},
|
||||
@@ -77,8 +71,14 @@ export function awsLoadBalancingSchema(): ServiceSchema {
|
||||
status: 'available',
|
||||
runtimeRequired: true,
|
||||
},
|
||||
{name: 'update', label: 'Set security groups', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
itemActions: [
|
||||
{name: 'list', label: 'List listeners', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'put', label: 'Create listener', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete listener', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
},
|
||||
filters: loadBalancerFilters,
|
||||
columns: loadBalancerColumns,
|
||||
|
||||
@@ -78,6 +78,13 @@ export const SERVICE_CATALOG = {
|
||||
order: 40,
|
||||
},
|
||||
storage: {displayName: 'Storage', iconKey: 'storage', group: 'Storage', order: 10},
|
||||
ecr: {
|
||||
displayName: 'Elastic Container Registry',
|
||||
displayNameByCloud: {aws: 'ECR'},
|
||||
iconKey: 'ecr',
|
||||
group: 'Storage',
|
||||
order: 20,
|
||||
},
|
||||
database: {displayName: 'Database', iconKey: 'database', group: 'Databases', order: 10},
|
||||
nosql: {
|
||||
displayName: 'NoSQL',
|
||||
@@ -104,6 +111,13 @@ export const SERVICE_CATALOG = {
|
||||
group: 'Networking',
|
||||
order: 20,
|
||||
},
|
||||
targetgroups: {
|
||||
displayName: 'Target Groups',
|
||||
displayNameByCloud: {aws: 'ELB Target Groups'},
|
||||
iconKey: 'loadbalancing',
|
||||
group: 'Networking',
|
||||
order: 30,
|
||||
},
|
||||
messaging: {
|
||||
displayName: 'Messaging',
|
||||
displayNameByCloud: {aws: 'SQS', gcp: 'Pub/Sub'},
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import type {ItemActionName} from './childCollections'
|
||||
import type {CapabilitySchema, FieldSchema, ServiceSchema, TableColumnSchema} from './types'
|
||||
import {ELB_NAME_PATTERN} from './loadBalancingSchema'
|
||||
|
||||
const targetGroupColumns: TableColumnSchema[] = [
|
||||
{name: 'name', label: 'Name'},
|
||||
{name: 'protocol', label: 'Protocol', path: 'metadata.protocol', format: 'badge'},
|
||||
{name: 'port', label: 'Port', path: 'metadata.port'},
|
||||
{name: 'targetType', label: 'Target Type', path: 'metadata.targetType'},
|
||||
{name: 'vpcId', label: 'VPC', path: 'metadata.vpcId', format: 'code', emptyText: '—'},
|
||||
{name: 'loadBalancerArns', label: 'Attached LBs', path: 'metadata.loadBalancerArns', format: 'list', emptyText: '—'},
|
||||
]
|
||||
|
||||
const targetGroupFilters: FieldSchema[] = [{name: 'search', label: 'Search', type: 'text', required: false}]
|
||||
|
||||
const targetHealthActions: CapabilitySchema<ItemActionName>[] = [
|
||||
{name: 'list', label: 'Describe target health', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'put', label: 'Register target', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Deregister target', enabled: true, status: 'available', runtimeRequired: true},
|
||||
]
|
||||
|
||||
const TARGET_GROUP_PROTOCOLS = ['HTTP', 'HTTPS', 'TCP', 'TLS', 'UDP', 'TCP_UDP', 'GENEVE']
|
||||
const TARGET_TYPES = ['instance', 'ip', 'lambda', 'alb']
|
||||
const HEALTH_CHECK_PROTOCOLS = ['HTTP', 'HTTPS', 'TCP', 'TLS', 'UDP', 'TCP_UDP', 'GENEVE']
|
||||
|
||||
export function awsTargetGroupsSchema(): ServiceSchema {
|
||||
return {
|
||||
cloud: 'aws',
|
||||
service: 'targetgroups',
|
||||
displayName: 'AWS ELB Target Groups',
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Target Group Name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
group: 'Required',
|
||||
validation: {
|
||||
pattern: ELB_NAME_PATTERN,
|
||||
minLength: 1,
|
||||
maxLength: 32,
|
||||
message: 'Up to 32 characters: letters, digits and hyphens, not starting or ending with a hyphen.',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'protocol',
|
||||
label: 'Protocol',
|
||||
type: 'select',
|
||||
required: true,
|
||||
group: 'Required',
|
||||
options: TARGET_GROUP_PROTOCOLS.map((value) => ({label: value, value})),
|
||||
},
|
||||
{
|
||||
name: 'port',
|
||||
label: 'Port',
|
||||
type: 'text',
|
||||
required: true,
|
||||
group: 'Required',
|
||||
validation: {pattern: '^[1-9][0-9]{0,4}$', message: 'Enter a port from 1 to 65535.'},
|
||||
},
|
||||
{
|
||||
name: 'targetType',
|
||||
label: 'Target Type',
|
||||
type: 'select',
|
||||
required: false,
|
||||
description: 'Defaults to instance.',
|
||||
options: TARGET_TYPES.map((value) => ({label: value, value})),
|
||||
},
|
||||
{name: 'vpcId', label: 'VPC ID', type: 'text', required: false},
|
||||
{
|
||||
name: 'healthCheckProtocol',
|
||||
label: 'Health Check Protocol',
|
||||
type: 'select',
|
||||
required: false,
|
||||
options: HEALTH_CHECK_PROTOCOLS.map((value) => ({label: value, value})),
|
||||
},
|
||||
{name: 'healthCheckPath', label: 'Health Check Path', type: 'text', required: false},
|
||||
],
|
||||
actions: ['list', 'create', 'delete', 'inspect'],
|
||||
capabilities: {
|
||||
resourceActions: [
|
||||
{name: 'list', label: 'List target groups', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'inspect', label: 'Inspect', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'create', label: 'Create target group', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
itemActions: targetHealthActions,
|
||||
},
|
||||
filters: targetGroupFilters,
|
||||
columns: targetGroupColumns,
|
||||
}
|
||||
}
|
||||
@@ -433,6 +433,7 @@ export interface AppConfigDeployment {
|
||||
|
||||
export interface ResourceQuery {
|
||||
search?: string
|
||||
state?: string
|
||||
}
|
||||
|
||||
export interface CreateResourceInput {
|
||||
@@ -643,6 +644,8 @@ export interface CloudServiceAdapter {
|
||||
get(id: string): Promise<CloudResource | null>
|
||||
create(input: CreateResourceInput): Promise<CloudResource>
|
||||
update?(id: string, input: UpdateResourceInput): Promise<CloudResource>
|
||||
/** Service-specific provider data used to populate resource forms. */
|
||||
dependencies?(): Promise<Record<string, unknown>>
|
||||
delete(id: string): Promise<void>
|
||||
listObjects?(resourceId: string, prefix?: string): Promise<StorageObjectList>
|
||||
putObject?(resourceId: string, key: string, body: Uint8Array, contentType: string): Promise<void>
|
||||
|
||||
Reference in New Issue
Block a user