@gugananuvem/aws-local-simulator 1.0.35 → 1.0.39

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 (149) hide show
  1. package/README.md +662 -658
  2. package/package.json +10 -3
  3. package/src/config/default-config.js +71 -0
  4. package/src/config/env-loader.js +4 -2
  5. package/src/middleware/authorization.js +271 -0
  6. package/src/middleware/cloudtrail-logger.js +333 -0
  7. package/src/middleware/error-handler.js +138 -0
  8. package/src/middleware/index.js +79 -0
  9. package/src/middleware/policy-enforcement.js +407 -0
  10. package/src/server.js +74 -4
  11. package/src/services/acm/index.js +66 -0
  12. package/src/services/acm/models/certificate.js +202 -0
  13. package/src/services/acm/server.js +224 -0
  14. package/src/services/acm/simulator.js +293 -0
  15. package/src/services/alb/index.js +104 -0
  16. package/src/services/alb/models/loadBalancer.js +88 -0
  17. package/src/services/alb/models/targetGroup.js +128 -0
  18. package/src/services/alb/server.js +160 -0
  19. package/src/services/alb/simulator.js +262 -0
  20. package/src/services/apigateway/index.js +22 -0
  21. package/src/services/apigateway/server.js +247 -35
  22. package/src/services/apigateway/simulator.js +780 -26
  23. package/src/services/asg/index.js +100 -0
  24. package/src/services/asg/models/autoScalingGroup.js +110 -0
  25. package/src/services/asg/models/launchTemplate.js +41 -0
  26. package/src/services/asg/models/scalingPolicy.js +51 -0
  27. package/src/services/asg/server.js +236 -0
  28. package/src/services/asg/simulator.js +410 -0
  29. package/src/services/aurora/cluster-manager.js +731 -0
  30. package/src/services/aurora/data-api.js +514 -0
  31. package/src/services/aurora/db-engine.js +270 -0
  32. package/src/services/aurora/index.js +159 -0
  33. package/src/services/aurora/rds-api.js +189 -0
  34. package/src/services/aurora/server.js +213 -0
  35. package/src/services/aurora/sql-translator.js +334 -0
  36. package/src/services/cloudformation/index.js +2 -2
  37. package/src/services/cloudformation/server.js +1 -0
  38. package/src/services/cloudfront/cache-engine.js +225 -0
  39. package/src/services/cloudfront/geo-restrictions.js +377 -0
  40. package/src/services/cloudfront/index.js +220 -0
  41. package/src/services/cloudfront/models/behavior.js +158 -0
  42. package/src/services/cloudfront/models/distribution.js +284 -0
  43. package/src/services/cloudfront/models/index.js +99 -0
  44. package/src/services/cloudfront/models/invalidation.js +109 -0
  45. package/src/services/cloudfront/models/origin.js +155 -0
  46. package/src/services/cloudfront/origin-router.js +552 -0
  47. package/src/services/cloudfront/origin-validator.js +398 -0
  48. package/src/services/cloudfront/server.js +512 -0
  49. package/src/services/cloudfront/signed-url-generator.js +377 -0
  50. package/src/services/cloudfront/simulator.js +425 -0
  51. package/src/services/cloudfront/store.js +326 -0
  52. package/src/services/cloudshell/env-builder.js +27 -0
  53. package/src/services/cloudshell/index.js +48 -0
  54. package/src/services/cloudshell/routes.js +60 -0
  55. package/src/services/cloudshell/session-manager.js +226 -0
  56. package/src/services/cloudshell/static/.gitkeep +0 -0
  57. package/src/services/cloudshell/static/index.html +406 -0
  58. package/src/services/cloudshell/websocket-handler.js +107 -0
  59. package/src/services/cloudtrail/index.js +2 -3
  60. package/src/services/cloudtrail/server.js +68 -0
  61. package/src/services/cognito/server.js +4 -1
  62. package/src/services/dynamodb/server.js +4 -1
  63. package/src/services/dynamodb/simulator.js +2 -1
  64. package/src/services/ec2/index.js +101 -0
  65. package/src/services/ec2/instanceServer.js +311 -0
  66. package/src/services/ec2/models/ami.js +39 -0
  67. package/src/services/ec2/models/instance.js +98 -0
  68. package/src/services/ec2/models/networkInterface.js +74 -0
  69. package/src/services/ec2/models/securityGroup.js +71 -0
  70. package/src/services/ec2/server.js +350 -0
  71. package/src/services/ec2/simulator.js +436 -0
  72. package/src/services/eventbridge/server.js +36 -0
  73. package/src/services/eventbridge/simulator.js +230 -45
  74. package/src/services/iam/index.js +65 -0
  75. package/src/services/iam/middleware.js +99 -0
  76. package/src/services/iam/server.js +331 -0
  77. package/src/services/iam/simulator.js +1432 -0
  78. package/src/services/index.js +28 -0
  79. package/src/services/kinesis-analytics/index.js +105 -0
  80. package/src/services/kinesis-analytics/models/application.js +325 -0
  81. package/src/services/kinesis-analytics/models/index.js +12 -0
  82. package/src/services/kinesis-analytics/server.js +250 -0
  83. package/src/services/kinesis-analytics/simulator.js +407 -0
  84. package/src/services/kinesis-analytics/store.js +176 -0
  85. package/src/services/kinesis-data-streams/index.js +106 -0
  86. package/src/services/kinesis-data-streams/models/index.js +12 -0
  87. package/src/services/kinesis-data-streams/models/record.js +70 -0
  88. package/src/services/kinesis-data-streams/models/stream.js +280 -0
  89. package/src/services/kinesis-data-streams/server.js +255 -0
  90. package/src/services/kinesis-data-streams/simulator.js +514 -0
  91. package/src/services/kinesis-data-streams/store.js +163 -0
  92. package/src/services/kinesis-firehose/index.js +106 -0
  93. package/src/services/kinesis-firehose/models/delivery-stream.js +265 -0
  94. package/src/services/kinesis-firehose/models/index.js +10 -0
  95. package/src/services/kinesis-firehose/server.js +215 -0
  96. package/src/services/kinesis-firehose/simulator.js +388 -0
  97. package/src/services/kinesis-firehose/store.js +163 -0
  98. package/src/services/kms/server.js +4 -1
  99. package/src/services/lambda/index.js +26 -0
  100. package/src/services/lambda/server.js +12 -1
  101. package/src/services/lambda/simulator.js +4 -0
  102. package/src/services/opensearch/index.js +105 -0
  103. package/src/services/opensearch/models/document.js +115 -0
  104. package/src/services/opensearch/models/index.js +73 -0
  105. package/src/services/opensearch/server.js +310 -0
  106. package/src/services/opensearch/simulator.js +605 -0
  107. package/src/services/opensearch/store.js +162 -0
  108. package/src/services/organizations/control-tower-simulator.js +321 -0
  109. package/src/services/organizations/control-tower-store.js +182 -0
  110. package/src/services/organizations/iam-integration.js +413 -0
  111. package/src/services/organizations/index.js +172 -0
  112. package/src/services/organizations/models/index.js +13 -0
  113. package/src/services/organizations/models/invitation.js +48 -0
  114. package/src/services/organizations/models/organization.js +566 -0
  115. package/src/services/organizations/models/role.js +244 -0
  116. package/src/services/organizations/models/scp.js +131 -0
  117. package/src/services/organizations/server.js +736 -0
  118. package/src/services/organizations/simulator.js +593 -0
  119. package/src/services/organizations/store.js +235 -0
  120. package/src/services/organizations/vpc-integration.js +453 -0
  121. package/src/services/route53/index.js +67 -0
  122. package/src/services/route53/models/healthCheck.js +101 -0
  123. package/src/services/route53/models/hostedZone.js +37 -0
  124. package/src/services/route53/models/resourceRecord.js +106 -0
  125. package/src/services/route53/server.js +841 -0
  126. package/src/services/route53/simulator.js +350 -0
  127. package/src/services/s3/index.js +62 -0
  128. package/src/services/s3/presigned-url-generator.js +337 -0
  129. package/src/services/s3/server.js +231 -0
  130. package/src/services/s3/simulator.js +551 -4
  131. package/src/services/sns/index.js +31 -0
  132. package/src/services/sns/server.js +9 -0
  133. package/src/services/sqs/index.js +38 -0
  134. package/src/services/sqs/server.js +57 -4
  135. package/src/services/sqs/simulator.js +423 -33
  136. package/src/services/sts/simulator.js +209 -17
  137. package/src/services/vpc/README.md +459 -0
  138. package/src/services/vpc/ec2ResponseFormatter.js +431 -0
  139. package/src/services/vpc/index.js +90 -0
  140. package/src/services/vpc/models/internetGateway.js +71 -0
  141. package/src/services/vpc/models/routeTable.js +160 -0
  142. package/src/services/vpc/models/subnet.js +48 -0
  143. package/src/services/vpc/models/vpc.js +37 -0
  144. package/src/services/vpc/models/vpcEndpoint.js +100 -0
  145. package/src/services/vpc/models/vpcGateway.js +134 -0
  146. package/src/services/vpc/server.js +836 -0
  147. package/src/services/vpc/simulator.js +613 -0
  148. package/src/utils/policy-cache.js +215 -0
  149. package/aws-config +0 -154
@@ -0,0 +1,104 @@
1
+ /**
2
+ * ALB Service - Ponto de entrada
3
+ */
4
+
5
+ const ALBServer = require('./server');
6
+ const ALBSimulator = require('./simulator');
7
+
8
+ class ALBService {
9
+ constructor(config) {
10
+ this.config = config;
11
+ this.name = 'alb';
12
+ this.port = config.ports.alb || 4021;
13
+ this.server = null;
14
+ this.simulator = null;
15
+ this.isRunning = false;
16
+ }
17
+
18
+ async initialize() {
19
+ const logger = require('../../utils/logger');
20
+ logger.debug(`Inicializando ALB Service na porta ${this.port}...`);
21
+
22
+ this.simulator = new ALBSimulator(this.config.alb || {});
23
+ await this.simulator.initialize();
24
+
25
+ this.server = new ALBServer(this.port, this.config);
26
+ this.server.simulator = this.simulator;
27
+
28
+ await this.server.initialize();
29
+
30
+ logger.debug('ALB Service inicializado');
31
+ }
32
+
33
+ injectDependencies(server) {
34
+ // Aqui você pode injetar dependências de outros serviços se necessário
35
+ // Por exemplo, integração com EC2 para health checks
36
+ }
37
+
38
+ async start() {
39
+ const logger = require('../../utils/logger');
40
+
41
+ if (this.isRunning) {
42
+ logger.warn('ALB Service já está em execução');
43
+ return;
44
+ }
45
+
46
+ try {
47
+ await this.server.start();
48
+ this.isRunning = true;
49
+ logger.info('ALB Service iniciado com sucesso');
50
+ } catch (error) {
51
+ logger.error(`Erro ao iniciar ALB Service: ${error.message}`);
52
+ throw error;
53
+ }
54
+ }
55
+
56
+ async stop() {
57
+ const logger = require('../../utils/logger');
58
+
59
+ if (!this.isRunning) {
60
+ logger.warn('ALB Service não está em execução');
61
+ return;
62
+ }
63
+
64
+ try {
65
+ await this.server.stop();
66
+ this.isRunning = false;
67
+ logger.info('ALB Service parado com sucesso');
68
+ } catch (error) {
69
+ logger.error(`Erro ao parar ALB Service: ${error.message}`);
70
+ throw error;
71
+ }
72
+ }
73
+
74
+ getSimulator() {
75
+ return this.simulator;
76
+ }
77
+
78
+ getStatus() {
79
+ const resources = this.simulator.getAllResources();
80
+ const totalTargets = resources.targetGroups.reduce(
81
+ (sum, tg) => sum + tg.Targets.length,
82
+ 0
83
+ );
84
+ const healthyTargets = resources.targetGroups.reduce((sum, tg) => {
85
+ return sum + tg.Targets.filter(t => t.HealthState === 'healthy').length;
86
+ }, 0);
87
+
88
+ return {
89
+ name: this.name,
90
+ running: this.isRunning,
91
+ port: this.port,
92
+ endpoint: `http://localhost:${this.port}`,
93
+ resources: {
94
+ loadBalancersCount: resources.loadBalancers.length,
95
+ targetGroupsCount: resources.targetGroups.length,
96
+ totalTargets,
97
+ healthyTargets,
98
+ unhealthyTargets: totalTargets - healthyTargets
99
+ }
100
+ };
101
+ }
102
+ }
103
+
104
+ module.exports = ALBService;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Application Load Balancer Model
3
+ */
4
+
5
+ const { v4: uuidv4 } = require('uuid');
6
+
7
+ class LoadBalancer {
8
+ constructor(name, scheme = 'internet-facing', config = {}) {
9
+ this.LoadBalancerArn = `arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/${name}/${uuidv4().substring(0, 8)}`;
10
+ this.LoadBalancerName = name;
11
+ this.DNSName = `${name}-${Math.random().toString(36).substring(7)}.elb.us-east-1.amazonaws.com`;
12
+ this.Scheme = scheme; // internet-facing ou internal
13
+ this.Type = 'application';
14
+ this.State = 'active';
15
+ this.VpcId = config.VpcId || null;
16
+ this.SubnetIds = config.SubnetIds || [];
17
+ this.SecurityGroupIds = config.SecurityGroupIds || [];
18
+ this.IpAddressType = config.IpAddressType || 'ipv4';
19
+ this.Listeners = [];
20
+ this.TargetGroups = [];
21
+ this.Tags = config.Tags || [];
22
+ this.CreatedTime = new Date().toISOString();
23
+ this.Port = config.Port || 80;
24
+ }
25
+
26
+ addListener(protocol = 'HTTP', port = 80, targetGroupArn = null) {
27
+ const listener = {
28
+ ListenerArn: `arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/${uuidv4().substring(0, 8)}`,
29
+ LoadBalancerArn: this.LoadBalancerArn,
30
+ Port: port,
31
+ Protocol: protocol,
32
+ Certificates: [],
33
+ DefaultActions: [
34
+ {
35
+ Type: 'forward',
36
+ TargetGroupArn: targetGroupArn
37
+ }
38
+ ],
39
+ AlpnPolicy: []
40
+ };
41
+ this.Listeners.push(listener);
42
+ return listener;
43
+ }
44
+
45
+ addTargetGroup(targetGroup) {
46
+ this.TargetGroups.push(targetGroup);
47
+ }
48
+
49
+ removeTargetGroup(targetGroupArn) {
50
+ const index = this.TargetGroups.findIndex(tg => tg.TargetGroupArn === targetGroupArn);
51
+ if (index > -1) {
52
+ this.TargetGroups.splice(index, 1);
53
+ }
54
+ }
55
+
56
+ getHealthyTargets() {
57
+ const healthyTargets = [];
58
+ this.TargetGroups.forEach(tg => {
59
+ tg.Targets.forEach(target => {
60
+ if (target.HealthState === 'healthy') {
61
+ healthyTargets.push(target);
62
+ }
63
+ });
64
+ });
65
+ return healthyTargets;
66
+ }
67
+
68
+ toJSON() {
69
+ return {
70
+ LoadBalancerArn: this.LoadBalancerArn,
71
+ LoadBalancerName: this.LoadBalancerName,
72
+ DNSName: this.DNSName,
73
+ Scheme: this.Scheme,
74
+ Type: this.Type,
75
+ State: this.State,
76
+ VpcId: this.VpcId,
77
+ SubnetIds: this.SubnetIds,
78
+ SecurityGroupIds: this.SecurityGroupIds,
79
+ IpAddressType: this.IpAddressType,
80
+ CreatedTime: this.CreatedTime,
81
+ Port: this.Port,
82
+ ListenersCount: this.Listeners.length,
83
+ TargetGroupsCount: this.TargetGroups.length
84
+ };
85
+ }
86
+ }
87
+
88
+ module.exports = LoadBalancer;
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Target Group Model
3
+ */
4
+
5
+ const { v4: uuidv4 } = require('uuid');
6
+
7
+ class Target {
8
+ constructor(targetId, port = 80) {
9
+ this.TargetId = targetId; // instance-id ou IP
10
+ this.Port = port;
11
+ this.HealthState = 'healthy';
12
+ this.HealthReason = 'N/A';
13
+ this.Description = 'Target registered';
14
+ this.RegisteredAt = new Date().toISOString();
15
+ }
16
+
17
+ setHealthy() {
18
+ this.HealthState = 'healthy';
19
+ this.HealthReason = 'N/A';
20
+ }
21
+
22
+ setUnhealthy(reason = 'Health checks failed') {
23
+ this.HealthState = 'unhealthy';
24
+ this.HealthReason = reason;
25
+ }
26
+
27
+ toJSON() {
28
+ return {
29
+ TargetId: this.TargetId,
30
+ Port: this.Port,
31
+ HealthState: this.HealthState,
32
+ HealthReason: this.HealthReason,
33
+ Description: this.Description,
34
+ RegisteredAt: this.RegisteredAt
35
+ };
36
+ }
37
+ }
38
+
39
+ class TargetGroup {
40
+ constructor(name, protocol = 'HTTP', port = 80, vpcId = null, config = {}) {
41
+ this.TargetGroupArn = `arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/${name}/${uuidv4().substring(0, 8)}`;
42
+ this.TargetGroupName = name;
43
+ this.Protocol = protocol;
44
+ this.Port = port;
45
+ this.VpcId = vpcId;
46
+ this.TargetType = config.TargetType || 'instance'; // instance ou ip
47
+ this.Targets = [];
48
+ this.HealthCheckEnabled = config.HealthCheckEnabled !== false;
49
+ this.HealthCheckProtocol = config.HealthCheckProtocol || 'HTTP';
50
+ this.HealthCheckPath = config.HealthCheckPath || '/';
51
+ this.HealthCheckPort = config.HealthCheckPort || String(port);
52
+ this.HealthCheckIntervalSeconds = config.HealthCheckIntervalSeconds || 30;
53
+ this.HealthCheckTimeoutSeconds = config.HealthCheckTimeoutSeconds || 5;
54
+ this.HealthyThresholdCount = config.HealthyThresholdCount || 2;
55
+ this.UnhealthyThresholdCount = config.UnhealthyThresholdCount || 2;
56
+ this.Matcher = config.Matcher || { HttpCode: '200' };
57
+ this.Tags = config.Tags || [];
58
+ this.CreatedTime = new Date().toISOString();
59
+ this.LoadBalancingAlgorithmType = 'round_robin';
60
+ this.TargetCount = 0;
61
+ this.HealthyCount = 0;
62
+ this.UnhealthyCount = 0;
63
+ }
64
+
65
+ registerTarget(targetId, port = null) {
66
+ const targetPort = port || this.Port;
67
+
68
+ // Verificar se já existe
69
+ if (this.Targets.some(t => t.TargetId === targetId && t.Port === targetPort)) {
70
+ throw new Error(`Target ${targetId}:${targetPort} already registered`);
71
+ }
72
+
73
+ const target = new Target(targetId, targetPort);
74
+ this.Targets.push(target);
75
+ this.updateCounts();
76
+ return target;
77
+ }
78
+
79
+ deregisterTarget(targetId, port = null) {
80
+ const targetPort = port || this.Port;
81
+ const index = this.Targets.findIndex(t => t.TargetId === targetId && t.Port === targetPort);
82
+
83
+ if (index === -1) {
84
+ throw new Error(`Target ${targetId}:${targetPort} not found`);
85
+ }
86
+
87
+ const target = this.Targets.splice(index, 1)[0];
88
+ this.updateCounts();
89
+ return target;
90
+ }
91
+
92
+ getNextTarget() {
93
+ const healthyTargets = this.Targets.filter(t => t.HealthState === 'healthy');
94
+ if (healthyTargets.length === 0) {
95
+ return null;
96
+ }
97
+ // Round robin simples
98
+ return healthyTargets[Math.floor(Math.random() * healthyTargets.length)];
99
+ }
100
+
101
+ updateCounts() {
102
+ this.TargetCount = this.Targets.length;
103
+ this.HealthyCount = this.Targets.filter(t => t.HealthState === 'healthy').length;
104
+ this.UnhealthyCount = this.Targets.filter(t => t.HealthState === 'unhealthy').length;
105
+ }
106
+
107
+ toJSON() {
108
+ return {
109
+ TargetGroupArn: this.TargetGroupArn,
110
+ TargetGroupName: this.TargetGroupName,
111
+ Protocol: this.Protocol,
112
+ Port: this.Port,
113
+ VpcId: this.VpcId,
114
+ TargetType: this.TargetType,
115
+ TargetCount: this.TargetCount,
116
+ HealthyCount: this.HealthyCount,
117
+ UnhealthyCount: this.UnhealthyCount,
118
+ HealthCheckEnabled: this.HealthCheckEnabled,
119
+ HealthCheckProtocol: this.HealthCheckProtocol,
120
+ HealthCheckPath: this.HealthCheckPath,
121
+ CreatedTime: this.CreatedTime,
122
+ LoadBalancingAlgorithmType: this.LoadBalancingAlgorithmType,
123
+ Targets: this.Targets.map(t => t.toJSON())
124
+ };
125
+ }
126
+ }
127
+
128
+ module.exports = { TargetGroup, Target };
@@ -0,0 +1,160 @@
1
+ /**
2
+ * ALB Server - API REST para Application Load Balancer
3
+ */
4
+
5
+ const express = require('express');
6
+ const logger = require('../../utils/logger');
7
+
8
+ class ALBServer {
9
+ constructor(port, config) {
10
+ this.port = port;
11
+ this.config = config;
12
+ this.app = express();
13
+ this.simulator = null;
14
+ }
15
+
16
+ setupMiddlewares() {
17
+ this.app.use(express.json());
18
+ this.app.use((req, res, next) => {
19
+ logger.debug(`ALB Request: ${req.method} ${req.path}`);
20
+ next();
21
+ });
22
+ }
23
+
24
+ async initialize() {
25
+ logger.debug(`Inicializando ALB Server na porta ${this.port}`);
26
+ this.setupMiddlewares();
27
+ this.setupRoutes();
28
+ }
29
+
30
+ setupRoutes() {
31
+ // Create Load Balancer
32
+ this.app.post('/__admin/alb/load-balancers/create', (req, res) => {
33
+ try {
34
+ const { Name, Scheme = 'internet-facing', ...config } = req.body;
35
+ if (!Name) return res.status(400).json({ error: 'Name is required' });
36
+
37
+ const alb = this.simulator.createLoadBalancer(Name, Scheme, config);
38
+ res.json({ LoadBalancer: alb.toJSON() });
39
+ } catch (error) {
40
+ res.status(400).json({ error: error.message });
41
+ }
42
+ });
43
+
44
+ // Describe Load Balancers
45
+ this.app.get('/__admin/alb/load-balancers', (req, res) => {
46
+ try {
47
+ const albs = this.simulator.describeLoadBalancers();
48
+ res.json({ LoadBalancers: albs.map(a => a.toJSON()) });
49
+ } catch (error) {
50
+ res.status(400).json({ error: error.message });
51
+ }
52
+ });
53
+
54
+ // Get Load Balancer
55
+ this.app.get('/__admin/alb/load-balancers/:albArn', (req, res) => {
56
+ try {
57
+ const alb = this.simulator.getLoadBalancer(req.params.albArn);
58
+ res.json({ LoadBalancer: alb.toJSON() });
59
+ } catch (error) {
60
+ res.status(404).json({ error: error.message });
61
+ }
62
+ });
63
+
64
+ // Delete Load Balancer
65
+ this.app.delete('/__admin/alb/load-balancers/:albArn', (req, res) => {
66
+ try {
67
+ this.simulator.deleteLoadBalancer(req.params.albArn);
68
+ res.json({ success: true });
69
+ } catch (error) {
70
+ res.status(400).json({ error: error.message });
71
+ }
72
+ });
73
+
74
+ // Create Target Group
75
+ this.app.post('/__admin/alb/target-groups/create', (req, res) => {
76
+ try {
77
+ const { Name, Protocol = 'HTTP', Port = 80, VpcId = null, ...config } = req.body;
78
+ if (!Name) return res.status(400).json({ error: 'Name is required' });
79
+
80
+ const tg = this.simulator.createTargetGroup(Name, Protocol, Port, VpcId, config);
81
+ res.json({ TargetGroup: tg.toJSON() });
82
+ } catch (error) {
83
+ res.status(400).json({ error: error.message });
84
+ }
85
+ });
86
+
87
+ // Describe Target Groups
88
+ this.app.get('/__admin/alb/target-groups', (req, res) => {
89
+ try {
90
+ const tgs = this.simulator.describeTargetGroups();
91
+ res.json({ TargetGroups: tgs.map(t => t.toJSON()) });
92
+ } catch (error) {
93
+ res.status(400).json({ error: error.message });
94
+ }
95
+ });
96
+
97
+ // Register Target
98
+ this.app.post('/__admin/alb/target-groups/:tgArn/register-target', (req, res) => {
99
+ try {
100
+ const { TargetId, Port } = req.body;
101
+ if (!TargetId) return res.status(400).json({ error: 'TargetId is required' });
102
+
103
+ const target = this.simulator.registerTarget(req.params.tgArn, TargetId, Port);
104
+ res.json({ Target: target.toJSON() });
105
+ } catch (error) {
106
+ res.status(400).json({ error: error.message });
107
+ }
108
+ });
109
+
110
+ // Describe Target Health
111
+ this.app.get('/__admin/alb/target-groups/:tgArn/health', (req, res) => {
112
+ try {
113
+ const health = this.simulator.describeTargetHealth(req.params.tgArn);
114
+ res.json(health);
115
+ } catch (error) {
116
+ res.status(400).json({ error: error.message });
117
+ }
118
+ });
119
+
120
+ // Health Check
121
+ this.app.get('/__admin/alb/health', (req, res) => {
122
+ res.json({ status: 'ok', service: 'alb' });
123
+ });
124
+
125
+ // Get All Resources
126
+ this.app.get('/__admin/alb/resources', (req, res) => {
127
+ try {
128
+ const resources = this.simulator.getAllResources();
129
+ res.json({
130
+ loadBalancers: resources.loadBalancers.map(a => a.toJSON()),
131
+ targetGroups: resources.targetGroups.map(t => t.toJSON())
132
+ });
133
+ } catch (error) {
134
+ res.status(400).json({ error: error.message });
135
+ }
136
+ });
137
+ }
138
+
139
+ async start() {
140
+ return new Promise((resolve) => {
141
+ this.server = this.app.listen(this.port, () => {
142
+ logger.info(`ALB Server running on http://localhost:${this.port}`);
143
+ resolve();
144
+ });
145
+ });
146
+ }
147
+
148
+ async stop() {
149
+ if (this.server) {
150
+ return new Promise((resolve) => {
151
+ this.server.close(() => {
152
+ logger.info('ALB Server stopped');
153
+ resolve();
154
+ });
155
+ });
156
+ }
157
+ }
158
+ }
159
+
160
+ module.exports = ALBServer;