@stacksjs/ts-cloud 0.1.3 → 0.1.5
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/README.md +98 -13
- package/dist/aws/acm.d.ts +129 -0
- package/dist/aws/application-autoscaling.d.ts +282 -0
- package/dist/aws/bedrock.d.ts +2292 -0
- package/dist/aws/client.d.ts +79 -0
- package/dist/aws/cloudformation.d.ts +105 -0
- package/dist/aws/cloudfront.d.ts +265 -0
- package/dist/aws/cloudwatch-logs.d.ts +48 -0
- package/dist/aws/comprehend.d.ts +505 -0
- package/dist/aws/connect.d.ts +377 -0
- package/dist/aws/deploy-imap.d.ts +14 -0
- package/dist/aws/dynamodb.d.ts +176 -0
- package/dist/aws/ec2.d.ts +272 -0
- package/dist/aws/ecr.d.ts +149 -0
- package/dist/aws/ecs.d.ts +162 -0
- package/dist/aws/elasticache.d.ts +71 -0
- package/dist/aws/elbv2.d.ts +248 -0
- package/dist/aws/email.d.ts +175 -0
- package/dist/aws/eventbridge.d.ts +142 -0
- package/dist/aws/iam.d.ts +638 -0
- package/dist/aws/imap-server.d.ts +119 -0
- package/{src/aws/index.ts → dist/aws/index.d.ts} +62 -83
- package/{src/aws/kendra.ts → dist/aws/kendra.d.ts} +71 -386
- package/dist/aws/lambda.d.ts +232 -0
- package/dist/aws/opensearch.d.ts +87 -0
- package/dist/aws/personalize.d.ts +516 -0
- package/dist/aws/polly.d.ts +214 -0
- package/dist/aws/rds.d.ts +240 -0
- package/dist/aws/rekognition.d.ts +543 -0
- package/dist/aws/route53-domains.d.ts +113 -0
- package/dist/aws/route53.d.ts +215 -0
- package/dist/aws/s3.d.ts +212 -0
- package/dist/aws/scheduler.d.ts +140 -0
- package/dist/aws/secrets-manager.d.ts +170 -0
- package/dist/aws/ses.d.ts +288 -0
- package/dist/aws/setup-phone.d.ts +0 -0
- package/dist/aws/setup-sms.d.ts +115 -0
- package/dist/aws/sms.d.ts +304 -0
- package/dist/aws/smtp-server.d.ts +61 -0
- package/dist/aws/sns.d.ts +117 -0
- package/dist/aws/sqs.d.ts +65 -0
- package/dist/aws/ssm.d.ts +179 -0
- package/dist/aws/sts.d.ts +15 -0
- package/dist/aws/support.d.ts +104 -0
- package/dist/aws/test-imap.d.ts +0 -0
- package/dist/aws/textract.d.ts +403 -0
- package/dist/aws/transcribe.d.ts +60 -0
- package/dist/aws/translate.d.ts +358 -0
- package/dist/aws/voice.d.ts +219 -0
- package/dist/bin/cli.js +1724 -0
- package/dist/config.d.ts +7 -0
- package/dist/deploy/index.d.ts +2 -0
- package/dist/deploy/static-site-external-dns.d.ts +51 -0
- package/dist/deploy/static-site.d.ts +71 -0
- package/dist/dns/cloudflare.d.ts +52 -0
- package/dist/dns/godaddy.d.ts +38 -0
- package/dist/dns/index.d.ts +45 -0
- package/dist/dns/porkbun.d.ts +18 -0
- package/dist/dns/route53-adapter.d.ts +38 -0
- package/{src/dns/types.ts → dist/dns/types.d.ts} +26 -63
- package/dist/dns/validator.d.ts +78 -0
- package/dist/generators/index.d.ts +1 -0
- package/dist/generators/infrastructure.d.ts +30 -0
- package/{src/index.ts → dist/index.d.ts} +70 -93
- package/dist/index.js +7881 -0
- package/dist/push/apns.d.ts +60 -0
- package/dist/push/fcm.d.ts +117 -0
- package/dist/push/index.d.ts +14 -0
- package/dist/security/pre-deploy-scanner.d.ts +69 -0
- package/dist/ssl/acme-client.d.ts +67 -0
- package/dist/ssl/index.d.ts +2 -0
- package/dist/ssl/letsencrypt.d.ts +48 -0
- package/dist/types.d.ts +1 -0
- package/dist/utils/cli.d.ts +123 -0
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/template.d.ts +23 -0
- package/package.json +8 -8
- package/bin/cli.ts +0 -133
- package/bin/commands/analytics.ts +0 -328
- package/bin/commands/api.ts +0 -379
- package/bin/commands/assets.ts +0 -221
- package/bin/commands/audit.ts +0 -501
- package/bin/commands/backup.ts +0 -682
- package/bin/commands/cache.ts +0 -294
- package/bin/commands/cdn.ts +0 -281
- package/bin/commands/config.ts +0 -202
- package/bin/commands/container.ts +0 -105
- package/bin/commands/cost.ts +0 -208
- package/bin/commands/database.ts +0 -401
- package/bin/commands/deploy.ts +0 -674
- package/bin/commands/domain.ts +0 -397
- package/bin/commands/email.ts +0 -423
- package/bin/commands/environment.ts +0 -285
- package/bin/commands/events.ts +0 -424
- package/bin/commands/firewall.ts +0 -145
- package/bin/commands/function.ts +0 -116
- package/bin/commands/generate.ts +0 -280
- package/bin/commands/git.ts +0 -139
- package/bin/commands/iam.ts +0 -464
- package/bin/commands/index.ts +0 -48
- package/bin/commands/init.ts +0 -120
- package/bin/commands/logs.ts +0 -148
- package/bin/commands/network.ts +0 -579
- package/bin/commands/notify.ts +0 -489
- package/bin/commands/queue.ts +0 -407
- package/bin/commands/scheduler.ts +0 -370
- package/bin/commands/secrets.ts +0 -54
- package/bin/commands/server.ts +0 -629
- package/bin/commands/shared.ts +0 -97
- package/bin/commands/ssl.ts +0 -138
- package/bin/commands/stack.ts +0 -325
- package/bin/commands/status.ts +0 -385
- package/bin/commands/storage.ts +0 -450
- package/bin/commands/team.ts +0 -96
- package/bin/commands/tunnel.ts +0 -489
- package/bin/commands/utils.ts +0 -202
- package/build.ts +0 -15
- package/cloud +0 -2
- package/src/aws/acm.ts +0 -768
- package/src/aws/application-autoscaling.ts +0 -845
- package/src/aws/bedrock.ts +0 -4074
- package/src/aws/client.ts +0 -878
- package/src/aws/cloudformation.ts +0 -896
- package/src/aws/cloudfront.ts +0 -1531
- package/src/aws/cloudwatch-logs.ts +0 -154
- package/src/aws/comprehend.ts +0 -839
- package/src/aws/connect.ts +0 -1056
- package/src/aws/deploy-imap.ts +0 -384
- package/src/aws/dynamodb.ts +0 -340
- package/src/aws/ec2.ts +0 -1385
- package/src/aws/ecr.ts +0 -621
- package/src/aws/ecs.ts +0 -615
- package/src/aws/elasticache.ts +0 -301
- package/src/aws/elbv2.ts +0 -942
- package/src/aws/email.ts +0 -928
- package/src/aws/eventbridge.ts +0 -248
- package/src/aws/iam.ts +0 -1689
- package/src/aws/imap-server.ts +0 -2100
- package/src/aws/lambda.ts +0 -786
- package/src/aws/opensearch.ts +0 -158
- package/src/aws/personalize.ts +0 -977
- package/src/aws/polly.ts +0 -559
- package/src/aws/rds.ts +0 -888
- package/src/aws/rekognition.ts +0 -846
- package/src/aws/route53-domains.ts +0 -359
- package/src/aws/route53.ts +0 -1046
- package/src/aws/s3.ts +0 -2318
- package/src/aws/scheduler.ts +0 -571
- package/src/aws/secrets-manager.ts +0 -769
- package/src/aws/ses.ts +0 -1081
- package/src/aws/setup-phone.ts +0 -104
- package/src/aws/setup-sms.ts +0 -580
- package/src/aws/sms.ts +0 -1735
- package/src/aws/smtp-server.ts +0 -531
- package/src/aws/sns.ts +0 -758
- package/src/aws/sqs.ts +0 -382
- package/src/aws/ssm.ts +0 -807
- package/src/aws/sts.ts +0 -92
- package/src/aws/support.ts +0 -391
- package/src/aws/test-imap.ts +0 -86
- package/src/aws/textract.ts +0 -780
- package/src/aws/transcribe.ts +0 -108
- package/src/aws/translate.ts +0 -641
- package/src/aws/voice.ts +0 -1379
- package/src/config.ts +0 -35
- package/src/deploy/index.ts +0 -7
- package/src/deploy/static-site-external-dns.ts +0 -906
- package/src/deploy/static-site.ts +0 -1125
- package/src/dns/godaddy.ts +0 -412
- package/src/dns/index.ts +0 -183
- package/src/dns/porkbun.ts +0 -362
- package/src/dns/route53-adapter.ts +0 -414
- package/src/dns/validator.ts +0 -369
- package/src/generators/index.ts +0 -5
- package/src/generators/infrastructure.ts +0 -1660
- package/src/push/apns.ts +0 -452
- package/src/push/fcm.ts +0 -506
- package/src/push/index.ts +0 -58
- package/src/ssl/acme-client.ts +0 -478
- package/src/ssl/index.ts +0 -7
- package/src/ssl/letsencrypt.ts +0 -747
- package/src/types.ts +0 -2
- package/src/utils/cli.ts +0 -398
- package/src/validation/index.ts +0 -5
- package/src/validation/template.ts +0 -405
- package/test/index.test.ts +0 -128
- package/tsconfig.json +0 -18
package/bin/commands/network.ts
DELETED
|
@@ -1,579 +0,0 @@
|
|
|
1
|
-
import type { CLI } from '@stacksjs/clapp'
|
|
2
|
-
import * as cli from '../../src/utils/cli'
|
|
3
|
-
import { EC2Client } from '../../src/aws/ec2'
|
|
4
|
-
import { loadValidatedConfig } from './shared'
|
|
5
|
-
|
|
6
|
-
export function registerNetworkCommands(app: CLI): void {
|
|
7
|
-
app
|
|
8
|
-
.command('network:list', 'List all VPCs')
|
|
9
|
-
.option('--region <region>', 'AWS region')
|
|
10
|
-
.action(async (options: { region?: string }) => {
|
|
11
|
-
cli.header('VPCs')
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const config = await loadValidatedConfig()
|
|
15
|
-
const region = options.region || config.project.region || 'us-east-1'
|
|
16
|
-
const ec2 = new EC2Client(region)
|
|
17
|
-
|
|
18
|
-
const spinner = new cli.Spinner('Fetching VPCs...')
|
|
19
|
-
spinner.start()
|
|
20
|
-
|
|
21
|
-
const result = await ec2.describeVpcs()
|
|
22
|
-
const vpcs = result.Vpcs || []
|
|
23
|
-
|
|
24
|
-
spinner.succeed(`Found ${vpcs.length} VPC(s)`)
|
|
25
|
-
|
|
26
|
-
if (vpcs.length === 0) {
|
|
27
|
-
cli.info('No VPCs found')
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
cli.table(
|
|
32
|
-
['VPC ID', 'Name', 'CIDR', 'State', 'Default'],
|
|
33
|
-
vpcs.map(vpc => [
|
|
34
|
-
vpc.VpcId || 'N/A',
|
|
35
|
-
vpc.Tags?.find(t => t.Key === 'Name')?.Value || '-',
|
|
36
|
-
vpc.CidrBlock || 'N/A',
|
|
37
|
-
vpc.State || 'N/A',
|
|
38
|
-
vpc.IsDefault ? 'Yes' : 'No',
|
|
39
|
-
]),
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
catch (error: any) {
|
|
43
|
-
cli.error(`Failed to list VPCs: ${error.message}`)
|
|
44
|
-
process.exit(1)
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
app
|
|
49
|
-
.command('network:subnets', 'List all subnets')
|
|
50
|
-
.option('--region <region>', 'AWS region')
|
|
51
|
-
.option('--vpc <vpcId>', 'Filter by VPC ID')
|
|
52
|
-
.action(async (options: { region?: string; vpc?: string }) => {
|
|
53
|
-
cli.header('Subnets')
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const config = await loadValidatedConfig()
|
|
57
|
-
const region = options.region || config.project.region || 'us-east-1'
|
|
58
|
-
const ec2 = new EC2Client(region)
|
|
59
|
-
|
|
60
|
-
const spinner = new cli.Spinner('Fetching subnets...')
|
|
61
|
-
spinner.start()
|
|
62
|
-
|
|
63
|
-
const filters = options.vpc ? [{ Name: 'vpc-id', Values: [options.vpc] }] : undefined
|
|
64
|
-
const result = await ec2.describeSubnets({ Filters: filters })
|
|
65
|
-
const subnets = result.Subnets || []
|
|
66
|
-
|
|
67
|
-
spinner.succeed(`Found ${subnets.length} subnet(s)`)
|
|
68
|
-
|
|
69
|
-
if (subnets.length === 0) {
|
|
70
|
-
cli.info('No subnets found')
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
cli.table(
|
|
75
|
-
['Subnet ID', 'Name', 'VPC', 'CIDR', 'AZ', 'IPs Available', 'Public'],
|
|
76
|
-
subnets.map(subnet => [
|
|
77
|
-
subnet.SubnetId || 'N/A',
|
|
78
|
-
subnet.Tags?.find(t => t.Key === 'Name')?.Value || '-',
|
|
79
|
-
subnet.VpcId || 'N/A',
|
|
80
|
-
subnet.CidrBlock || 'N/A',
|
|
81
|
-
subnet.AvailabilityZone || 'N/A',
|
|
82
|
-
(subnet.AvailableIpAddressCount || 0).toString(),
|
|
83
|
-
subnet.MapPublicIpOnLaunch ? 'Yes' : 'No',
|
|
84
|
-
]),
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
catch (error: any) {
|
|
88
|
-
cli.error(`Failed to list subnets: ${error.message}`)
|
|
89
|
-
process.exit(1)
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
app
|
|
94
|
-
.command('network:security-groups', 'List all security groups')
|
|
95
|
-
.option('--region <region>', 'AWS region')
|
|
96
|
-
.option('--vpc <vpcId>', 'Filter by VPC ID')
|
|
97
|
-
.action(async (options: { region?: string; vpc?: string }) => {
|
|
98
|
-
cli.header('Security Groups')
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
const config = await loadValidatedConfig()
|
|
102
|
-
const region = options.region || config.project.region || 'us-east-1'
|
|
103
|
-
const ec2 = new EC2Client(region)
|
|
104
|
-
|
|
105
|
-
const spinner = new cli.Spinner('Fetching security groups...')
|
|
106
|
-
spinner.start()
|
|
107
|
-
|
|
108
|
-
const filters = options.vpc ? [{ Name: 'vpc-id', Values: [options.vpc] }] : undefined
|
|
109
|
-
const result = await ec2.describeSecurityGroups({ Filters: filters })
|
|
110
|
-
const groups = result.SecurityGroups || []
|
|
111
|
-
|
|
112
|
-
spinner.succeed(`Found ${groups.length} security group(s)`)
|
|
113
|
-
|
|
114
|
-
if (groups.length === 0) {
|
|
115
|
-
cli.info('No security groups found')
|
|
116
|
-
return
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
cli.table(
|
|
120
|
-
['Group ID', 'Name', 'VPC', 'Description', 'Inbound Rules', 'Outbound Rules'],
|
|
121
|
-
groups.map(sg => [
|
|
122
|
-
sg.GroupId || 'N/A',
|
|
123
|
-
sg.GroupName || 'N/A',
|
|
124
|
-
sg.VpcId || 'N/A',
|
|
125
|
-
(sg.Description || '').substring(0, 30),
|
|
126
|
-
(sg.IpPermissions?.length || 0).toString(),
|
|
127
|
-
(sg.IpPermissionsEgress?.length || 0).toString(),
|
|
128
|
-
]),
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
catch (error: any) {
|
|
132
|
-
cli.error(`Failed to list security groups: ${error.message}`)
|
|
133
|
-
process.exit(1)
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
app
|
|
138
|
-
.command('network:security-group <groupId>', 'Show security group details')
|
|
139
|
-
.option('--region <region>', 'AWS region')
|
|
140
|
-
.action(async (groupId: string, options: { region?: string }) => {
|
|
141
|
-
cli.header(`Security Group: ${groupId}`)
|
|
142
|
-
|
|
143
|
-
try {
|
|
144
|
-
const config = await loadValidatedConfig()
|
|
145
|
-
const region = options.region || config.project.region || 'us-east-1'
|
|
146
|
-
const ec2 = new EC2Client(region)
|
|
147
|
-
|
|
148
|
-
const spinner = new cli.Spinner('Fetching security group...')
|
|
149
|
-
spinner.start()
|
|
150
|
-
|
|
151
|
-
const result = await ec2.describeSecurityGroups({
|
|
152
|
-
GroupIds: [groupId],
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
const sg = result.SecurityGroups?.[0]
|
|
156
|
-
|
|
157
|
-
if (!sg) {
|
|
158
|
-
spinner.fail('Security group not found')
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
spinner.succeed('Security group loaded')
|
|
163
|
-
|
|
164
|
-
cli.info('\nGeneral Information:')
|
|
165
|
-
cli.info(` Group ID: ${sg.GroupId}`)
|
|
166
|
-
cli.info(` Name: ${sg.GroupName}`)
|
|
167
|
-
cli.info(` VPC: ${sg.VpcId}`)
|
|
168
|
-
cli.info(` Description: ${sg.Description}`)
|
|
169
|
-
|
|
170
|
-
if (sg.IpPermissions && sg.IpPermissions.length > 0) {
|
|
171
|
-
cli.info('\nInbound Rules:')
|
|
172
|
-
for (const rule of sg.IpPermissions) {
|
|
173
|
-
const protocol = rule.IpProtocol === '-1' ? 'All' : rule.IpProtocol?.toUpperCase()
|
|
174
|
-
const ports = rule.FromPort === rule.ToPort
|
|
175
|
-
? rule.FromPort?.toString() || 'All'
|
|
176
|
-
: `${rule.FromPort}-${rule.ToPort}`
|
|
177
|
-
|
|
178
|
-
for (const range of rule.IpRanges || []) {
|
|
179
|
-
cli.info(` - ${protocol} ${ports} from ${range.CidrIp}${range.Description ? ` (${range.Description})` : ''}`)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
for (const group of rule.UserIdGroupPairs || []) {
|
|
183
|
-
cli.info(` - ${protocol} ${ports} from ${group.GroupId}${group.Description ? ` (${group.Description})` : ''}`)
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
cli.info('\nNo inbound rules configured.')
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (sg.IpPermissionsEgress && sg.IpPermissionsEgress.length > 0) {
|
|
192
|
-
cli.info('\nOutbound Rules:')
|
|
193
|
-
for (const rule of sg.IpPermissionsEgress) {
|
|
194
|
-
const protocol = rule.IpProtocol === '-1' ? 'All' : rule.IpProtocol?.toUpperCase()
|
|
195
|
-
const ports = rule.FromPort === rule.ToPort
|
|
196
|
-
? rule.FromPort?.toString() || 'All'
|
|
197
|
-
: `${rule.FromPort}-${rule.ToPort}`
|
|
198
|
-
|
|
199
|
-
for (const range of rule.IpRanges || []) {
|
|
200
|
-
cli.info(` - ${protocol} ${ports} to ${range.CidrIp}${range.Description ? ` (${range.Description})` : ''}`)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
for (const group of rule.UserIdGroupPairs || []) {
|
|
204
|
-
cli.info(` - ${protocol} ${ports} to ${group.GroupId}${group.Description ? ` (${group.Description})` : ''}`)
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
cli.info('\nNo outbound rules configured.')
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (sg.Tags && sg.Tags.length > 0) {
|
|
213
|
-
cli.info('\nTags:')
|
|
214
|
-
for (const tag of sg.Tags) {
|
|
215
|
-
cli.info(` ${tag.Key}: ${tag.Value}`)
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
catch (error: any) {
|
|
220
|
-
cli.error(`Failed to get security group: ${error.message}`)
|
|
221
|
-
process.exit(1)
|
|
222
|
-
}
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
app
|
|
226
|
-
.command('network:create-vpc <cidr>', 'Create a new VPC')
|
|
227
|
-
.option('--region <region>', 'AWS region', { default: 'us-east-1' })
|
|
228
|
-
.option('--name <name>', 'VPC name tag')
|
|
229
|
-
.option('--tenancy <tenancy>', 'Instance tenancy (default or dedicated)', { default: 'default' })
|
|
230
|
-
.action(async (cidr: string, options: { region: string; name?: string; tenancy: string }) => {
|
|
231
|
-
cli.header('Create VPC')
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
const ec2 = new EC2Client(options.region)
|
|
235
|
-
|
|
236
|
-
cli.info(`CIDR Block: ${cidr}`)
|
|
237
|
-
cli.info(`Region: ${options.region}`)
|
|
238
|
-
cli.info(`Tenancy: ${options.tenancy}`)
|
|
239
|
-
if (options.name) {
|
|
240
|
-
cli.info(`Name: ${options.name}`)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const confirmed = await cli.confirm('\nCreate this VPC?', true)
|
|
244
|
-
if (!confirmed) {
|
|
245
|
-
cli.info('Operation cancelled')
|
|
246
|
-
return
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const spinner = new cli.Spinner('Creating VPC...')
|
|
250
|
-
spinner.start()
|
|
251
|
-
|
|
252
|
-
const result = await ec2.createVpc({
|
|
253
|
-
CidrBlock: cidr,
|
|
254
|
-
InstanceTenancy: options.tenancy,
|
|
255
|
-
TagSpecifications: options.name ? [{
|
|
256
|
-
ResourceType: 'vpc',
|
|
257
|
-
Tags: [{ Key: 'Name', Value: options.name }],
|
|
258
|
-
}] : undefined,
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
spinner.succeed('VPC created')
|
|
262
|
-
|
|
263
|
-
cli.success(`\nVPC ID: ${result.Vpc?.VpcId}`)
|
|
264
|
-
cli.info(`CIDR: ${result.Vpc?.CidrBlock}`)
|
|
265
|
-
cli.info(`State: ${result.Vpc?.State}`)
|
|
266
|
-
}
|
|
267
|
-
catch (error: any) {
|
|
268
|
-
cli.error(`Failed to create VPC: ${error.message}`)
|
|
269
|
-
process.exit(1)
|
|
270
|
-
}
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
app
|
|
274
|
-
.command('network:create-subnet <vpcId> <cidr>', 'Create a new subnet')
|
|
275
|
-
.option('--region <region>', 'AWS region', { default: 'us-east-1' })
|
|
276
|
-
.option('--name <name>', 'Subnet name tag')
|
|
277
|
-
.option('--az <zone>', 'Availability zone')
|
|
278
|
-
.option('--public', 'Auto-assign public IPs')
|
|
279
|
-
.action(async (vpcId: string, cidr: string, options: { region: string; name?: string; az?: string; public?: boolean }) => {
|
|
280
|
-
cli.header('Create Subnet')
|
|
281
|
-
|
|
282
|
-
try {
|
|
283
|
-
const ec2 = new EC2Client(options.region)
|
|
284
|
-
|
|
285
|
-
cli.info(`VPC: ${vpcId}`)
|
|
286
|
-
cli.info(`CIDR Block: ${cidr}`)
|
|
287
|
-
if (options.az) {
|
|
288
|
-
cli.info(`Availability Zone: ${options.az}`)
|
|
289
|
-
}
|
|
290
|
-
if (options.name) {
|
|
291
|
-
cli.info(`Name: ${options.name}`)
|
|
292
|
-
}
|
|
293
|
-
cli.info(`Auto-assign Public IP: ${options.public ? 'Yes' : 'No'}`)
|
|
294
|
-
|
|
295
|
-
const confirmed = await cli.confirm('\nCreate this subnet?', true)
|
|
296
|
-
if (!confirmed) {
|
|
297
|
-
cli.info('Operation cancelled')
|
|
298
|
-
return
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const spinner = new cli.Spinner('Creating subnet...')
|
|
302
|
-
spinner.start()
|
|
303
|
-
|
|
304
|
-
const result = await ec2.createSubnet({
|
|
305
|
-
VpcId: vpcId,
|
|
306
|
-
CidrBlock: cidr,
|
|
307
|
-
AvailabilityZone: options.az,
|
|
308
|
-
TagSpecifications: options.name ? [{
|
|
309
|
-
ResourceType: 'subnet',
|
|
310
|
-
Tags: [{ Key: 'Name', Value: options.name }],
|
|
311
|
-
}] : undefined,
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
if (options.public && result.Subnet?.SubnetId) {
|
|
315
|
-
spinner.text = 'Enabling auto-assign public IP...'
|
|
316
|
-
await ec2.modifySubnetAttribute({
|
|
317
|
-
SubnetId: result.Subnet.SubnetId,
|
|
318
|
-
MapPublicIpOnLaunch: { Value: true },
|
|
319
|
-
})
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
spinner.succeed('Subnet created')
|
|
323
|
-
|
|
324
|
-
cli.success(`\nSubnet ID: ${result.Subnet?.SubnetId}`)
|
|
325
|
-
cli.info(`CIDR: ${result.Subnet?.CidrBlock}`)
|
|
326
|
-
cli.info(`Availability Zone: ${result.Subnet?.AvailabilityZone}`)
|
|
327
|
-
}
|
|
328
|
-
catch (error: any) {
|
|
329
|
-
cli.error(`Failed to create subnet: ${error.message}`)
|
|
330
|
-
process.exit(1)
|
|
331
|
-
}
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
app
|
|
335
|
-
.command('network:create-sg <vpcId> <name>', 'Create a new security group')
|
|
336
|
-
.option('--region <region>', 'AWS region', { default: 'us-east-1' })
|
|
337
|
-
.option('--description <desc>', 'Security group description')
|
|
338
|
-
.action(async (vpcId: string, name: string, options: { region: string; description?: string }) => {
|
|
339
|
-
cli.header('Create Security Group')
|
|
340
|
-
|
|
341
|
-
try {
|
|
342
|
-
const ec2 = new EC2Client(options.region)
|
|
343
|
-
|
|
344
|
-
const description = options.description || `Security group for ${name}`
|
|
345
|
-
|
|
346
|
-
cli.info(`VPC: ${vpcId}`)
|
|
347
|
-
cli.info(`Name: ${name}`)
|
|
348
|
-
cli.info(`Description: ${description}`)
|
|
349
|
-
|
|
350
|
-
const confirmed = await cli.confirm('\nCreate this security group?', true)
|
|
351
|
-
if (!confirmed) {
|
|
352
|
-
cli.info('Operation cancelled')
|
|
353
|
-
return
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const spinner = new cli.Spinner('Creating security group...')
|
|
357
|
-
spinner.start()
|
|
358
|
-
|
|
359
|
-
const result = await ec2.createSecurityGroup({
|
|
360
|
-
GroupName: name,
|
|
361
|
-
Description: description,
|
|
362
|
-
VpcId: vpcId,
|
|
363
|
-
TagSpecifications: [{
|
|
364
|
-
ResourceType: 'security-group',
|
|
365
|
-
Tags: [{ Key: 'Name', Value: name }],
|
|
366
|
-
}],
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
spinner.succeed('Security group created')
|
|
370
|
-
|
|
371
|
-
cli.success(`\nGroup ID: ${result.GroupId}`)
|
|
372
|
-
cli.info('\nTo add rules:')
|
|
373
|
-
cli.info(` cloud network:sg-rule ${result.GroupId} --inbound --port 443 --cidr 0.0.0.0/0`)
|
|
374
|
-
}
|
|
375
|
-
catch (error: any) {
|
|
376
|
-
cli.error(`Failed to create security group: ${error.message}`)
|
|
377
|
-
process.exit(1)
|
|
378
|
-
}
|
|
379
|
-
})
|
|
380
|
-
|
|
381
|
-
app
|
|
382
|
-
.command('network:sg-rule <groupId>', 'Add a rule to a security group')
|
|
383
|
-
.option('--region <region>', 'AWS region', { default: 'us-east-1' })
|
|
384
|
-
.option('--inbound', 'Add inbound rule')
|
|
385
|
-
.option('--outbound', 'Add outbound rule')
|
|
386
|
-
.option('--protocol <protocol>', 'Protocol (tcp, udp, icmp, or -1 for all)', { default: 'tcp' })
|
|
387
|
-
.option('--port <port>', 'Port number or range (e.g., 80 or 80-443)')
|
|
388
|
-
.option('--cidr <cidr>', 'CIDR block (e.g., 0.0.0.0/0)')
|
|
389
|
-
.option('--source-group <groupId>', 'Source security group')
|
|
390
|
-
.option('--description <desc>', 'Rule description')
|
|
391
|
-
.action(async (groupId: string, options: {
|
|
392
|
-
region: string
|
|
393
|
-
inbound?: boolean
|
|
394
|
-
outbound?: boolean
|
|
395
|
-
protocol: string
|
|
396
|
-
port?: string
|
|
397
|
-
cidr?: string
|
|
398
|
-
sourceGroup?: string
|
|
399
|
-
description?: string
|
|
400
|
-
}) => {
|
|
401
|
-
cli.header('Add Security Group Rule')
|
|
402
|
-
|
|
403
|
-
try {
|
|
404
|
-
const ec2 = new EC2Client(options.region)
|
|
405
|
-
|
|
406
|
-
if (!options.inbound && !options.outbound) {
|
|
407
|
-
cli.error('Specify --inbound or --outbound')
|
|
408
|
-
return
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
if (!options.cidr && !options.sourceGroup) {
|
|
412
|
-
cli.error('Specify --cidr or --source-group')
|
|
413
|
-
return
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Parse port range
|
|
417
|
-
let fromPort: number | undefined
|
|
418
|
-
let toPort: number | undefined
|
|
419
|
-
|
|
420
|
-
if (options.port) {
|
|
421
|
-
if (options.port.includes('-')) {
|
|
422
|
-
const [from, to] = options.port.split('-')
|
|
423
|
-
fromPort = Number.parseInt(from)
|
|
424
|
-
toPort = Number.parseInt(to)
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
fromPort = Number.parseInt(options.port)
|
|
428
|
-
toPort = fromPort
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
else if (options.protocol !== '-1') {
|
|
432
|
-
cli.error('Port is required for TCP/UDP protocols')
|
|
433
|
-
return
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
const direction = options.inbound ? 'Inbound' : 'Outbound'
|
|
437
|
-
const portStr = options.protocol === '-1' ? 'All' : (fromPort === toPort ? fromPort : `${fromPort}-${toPort}`)
|
|
438
|
-
|
|
439
|
-
cli.info(`Security Group: ${groupId}`)
|
|
440
|
-
cli.info(`Direction: ${direction}`)
|
|
441
|
-
cli.info(`Protocol: ${options.protocol}`)
|
|
442
|
-
cli.info(`Port(s): ${portStr}`)
|
|
443
|
-
cli.info(`Source: ${options.cidr || options.sourceGroup}`)
|
|
444
|
-
|
|
445
|
-
const confirmed = await cli.confirm('\nAdd this rule?', true)
|
|
446
|
-
if (!confirmed) {
|
|
447
|
-
cli.info('Operation cancelled')
|
|
448
|
-
return
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
const spinner = new cli.Spinner('Adding rule...')
|
|
452
|
-
spinner.start()
|
|
453
|
-
|
|
454
|
-
const ipPermission: any = {
|
|
455
|
-
IpProtocol: options.protocol,
|
|
456
|
-
FromPort: fromPort,
|
|
457
|
-
ToPort: toPort,
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
if (options.cidr) {
|
|
461
|
-
ipPermission.IpRanges = [{
|
|
462
|
-
CidrIp: options.cidr,
|
|
463
|
-
Description: options.description,
|
|
464
|
-
}]
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if (options.sourceGroup) {
|
|
468
|
-
ipPermission.UserIdGroupPairs = [{
|
|
469
|
-
GroupId: options.sourceGroup,
|
|
470
|
-
Description: options.description,
|
|
471
|
-
}]
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
if (options.inbound) {
|
|
475
|
-
await ec2.authorizeSecurityGroupIngress({
|
|
476
|
-
GroupId: groupId,
|
|
477
|
-
IpPermissions: [ipPermission],
|
|
478
|
-
})
|
|
479
|
-
}
|
|
480
|
-
else {
|
|
481
|
-
await ec2.authorizeSecurityGroupEgress({
|
|
482
|
-
GroupId: groupId,
|
|
483
|
-
IpPermissions: [ipPermission],
|
|
484
|
-
})
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
spinner.succeed('Rule added')
|
|
488
|
-
}
|
|
489
|
-
catch (error: any) {
|
|
490
|
-
cli.error(`Failed to add rule: ${error.message}`)
|
|
491
|
-
process.exit(1)
|
|
492
|
-
}
|
|
493
|
-
})
|
|
494
|
-
|
|
495
|
-
app
|
|
496
|
-
.command('network:elastic-ips', 'List Elastic IP addresses')
|
|
497
|
-
.option('--region <region>', 'AWS region')
|
|
498
|
-
.action(async (options: { region?: string }) => {
|
|
499
|
-
cli.header('Elastic IP Addresses')
|
|
500
|
-
|
|
501
|
-
try {
|
|
502
|
-
const config = await loadValidatedConfig()
|
|
503
|
-
const region = options.region || config.project.region || 'us-east-1'
|
|
504
|
-
const ec2 = new EC2Client(region)
|
|
505
|
-
|
|
506
|
-
const spinner = new cli.Spinner('Fetching Elastic IPs...')
|
|
507
|
-
spinner.start()
|
|
508
|
-
|
|
509
|
-
const result = await ec2.describeAddresses()
|
|
510
|
-
const addresses = result.Addresses || []
|
|
511
|
-
|
|
512
|
-
spinner.succeed(`Found ${addresses.length} Elastic IP(s)`)
|
|
513
|
-
|
|
514
|
-
if (addresses.length === 0) {
|
|
515
|
-
cli.info('No Elastic IPs found')
|
|
516
|
-
return
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
cli.table(
|
|
520
|
-
['Public IP', 'Allocation ID', 'Association ID', 'Instance', 'Name'],
|
|
521
|
-
addresses.map(addr => [
|
|
522
|
-
addr.PublicIp || 'N/A',
|
|
523
|
-
addr.AllocationId || 'N/A',
|
|
524
|
-
addr.AssociationId || '-',
|
|
525
|
-
addr.InstanceId || '-',
|
|
526
|
-
addr.Tags?.find(t => t.Key === 'Name')?.Value || '-',
|
|
527
|
-
]),
|
|
528
|
-
)
|
|
529
|
-
}
|
|
530
|
-
catch (error: any) {
|
|
531
|
-
cli.error(`Failed to list Elastic IPs: ${error.message}`)
|
|
532
|
-
process.exit(1)
|
|
533
|
-
}
|
|
534
|
-
})
|
|
535
|
-
|
|
536
|
-
app
|
|
537
|
-
.command('network:route-tables', 'List route tables')
|
|
538
|
-
.option('--region <region>', 'AWS region')
|
|
539
|
-
.option('--vpc <vpcId>', 'Filter by VPC ID')
|
|
540
|
-
.action(async (options: { region?: string; vpc?: string }) => {
|
|
541
|
-
cli.header('Route Tables')
|
|
542
|
-
|
|
543
|
-
try {
|
|
544
|
-
const config = await loadValidatedConfig()
|
|
545
|
-
const region = options.region || config.project.region || 'us-east-1'
|
|
546
|
-
const ec2 = new EC2Client(region)
|
|
547
|
-
|
|
548
|
-
const spinner = new cli.Spinner('Fetching route tables...')
|
|
549
|
-
spinner.start()
|
|
550
|
-
|
|
551
|
-
const filters = options.vpc ? [{ Name: 'vpc-id', Values: [options.vpc] }] : undefined
|
|
552
|
-
const result = await ec2.describeRouteTables({ Filters: filters })
|
|
553
|
-
const tables = result.RouteTables || []
|
|
554
|
-
|
|
555
|
-
spinner.succeed(`Found ${tables.length} route table(s)`)
|
|
556
|
-
|
|
557
|
-
if (tables.length === 0) {
|
|
558
|
-
cli.info('No route tables found')
|
|
559
|
-
return
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
cli.table(
|
|
563
|
-
['Route Table ID', 'VPC', 'Name', 'Main', 'Associations', 'Routes'],
|
|
564
|
-
tables.map(rt => [
|
|
565
|
-
rt.RouteTableId || 'N/A',
|
|
566
|
-
rt.VpcId || 'N/A',
|
|
567
|
-
rt.Tags?.find(t => t.Key === 'Name')?.Value || '-',
|
|
568
|
-
rt.Associations?.some(a => a.Main) ? 'Yes' : 'No',
|
|
569
|
-
(rt.Associations?.length || 0).toString(),
|
|
570
|
-
(rt.Routes?.length || 0).toString(),
|
|
571
|
-
]),
|
|
572
|
-
)
|
|
573
|
-
}
|
|
574
|
-
catch (error: any) {
|
|
575
|
-
cli.error(`Failed to list route tables: ${error.message}`)
|
|
576
|
-
process.exit(1)
|
|
577
|
-
}
|
|
578
|
-
})
|
|
579
|
-
}
|