synapse-mcp 1.0.0 → 1.0.2
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 +1820 -147
- package/dist/constants.d.ts +10 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +18 -8
- package/dist/constants.js.map +1 -1
- package/dist/events/emitter.d.ts +63 -0
- package/dist/events/emitter.d.ts.map +1 -0
- package/dist/events/emitter.js +112 -0
- package/dist/events/emitter.js.map +1 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +51 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +3 -0
- package/dist/events/types.js.map +1 -0
- package/dist/formatters/compose.d.ts +185 -0
- package/dist/formatters/compose.d.ts.map +1 -0
- package/dist/formatters/compose.js +397 -0
- package/dist/formatters/compose.js.map +1 -0
- package/dist/formatters/container.d.ts +84 -0
- package/dist/formatters/container.d.ts.map +1 -0
- package/dist/formatters/container.js +323 -0
- package/dist/formatters/container.js.map +1 -0
- package/dist/formatters/diagnostics.d.ts +20 -0
- package/dist/formatters/diagnostics.d.ts.map +1 -0
- package/dist/formatters/diagnostics.js +73 -0
- package/dist/formatters/diagnostics.js.map +1 -0
- package/dist/formatters/docker.d.ts +139 -0
- package/dist/formatters/docker.d.ts.map +1 -0
- package/dist/formatters/docker.js +216 -0
- package/dist/formatters/docker.js.map +1 -0
- package/dist/formatters/host.d.ts +137 -0
- package/dist/formatters/host.d.ts.map +1 -0
- package/dist/formatters/host.js +198 -0
- package/dist/formatters/host.js.map +1 -0
- package/dist/formatters/index.d.ts +17 -270
- package/dist/formatters/index.d.ts.map +1 -1
- package/dist/formatters/index.js +21 -456
- package/dist/formatters/index.js.map +1 -1
- package/dist/formatters/scout.d.ts +424 -0
- package/dist/formatters/scout.d.ts.map +1 -0
- package/dist/formatters/scout.js +687 -0
- package/dist/formatters/scout.js.map +1 -0
- package/dist/formatters/strategy.d.ts +105 -0
- package/dist/formatters/strategy.d.ts.map +1 -0
- package/dist/formatters/strategy.js +120 -0
- package/dist/formatters/strategy.js.map +1 -0
- package/dist/formatters/utils.d.ts +84 -0
- package/dist/formatters/utils.d.ts.map +1 -0
- package/dist/formatters/utils.js +129 -0
- package/dist/formatters/utils.js.map +1 -0
- package/dist/health-rate-limiter.d.ts +59 -0
- package/dist/health-rate-limiter.d.ts.map +1 -0
- package/dist/health-rate-limiter.js +159 -0
- package/dist/health-rate-limiter.js.map +1 -0
- package/dist/index.js +61 -100
- package/dist/index.js.map +1 -1
- package/dist/middleware/async-handler.d.ts +62 -0
- package/dist/middleware/async-handler.d.ts.map +1 -0
- package/dist/middleware/async-handler.js +58 -0
- package/dist/middleware/async-handler.js.map +1 -0
- package/dist/middleware/auth.d.ts +32 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +63 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/csrf-protection.d.ts +58 -0
- package/dist/middleware/csrf-protection.d.ts.map +1 -0
- package/dist/middleware/csrf-protection.js +123 -0
- package/dist/middleware/csrf-protection.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +49 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +90 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/error-mapper.d.ts +44 -0
- package/dist/middleware/error-mapper.d.ts.map +1 -0
- package/dist/middleware/error-mapper.js +127 -0
- package/dist/middleware/error-mapper.js.map +1 -0
- package/dist/middleware/index.d.ts +13 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +13 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/request-id.d.ts +22 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +31 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/middleware/types.d.ts +33 -0
- package/dist/middleware/types.d.ts.map +1 -0
- package/dist/middleware/types.js +2 -0
- package/dist/middleware/types.js.map +1 -0
- package/dist/schemas/common.d.ts +205 -8
- package/dist/schemas/common.d.ts.map +1 -1
- package/dist/schemas/common.js +290 -17
- package/dist/schemas/common.js.map +1 -1
- package/dist/schemas/flux/compose.d.ts +307 -44
- package/dist/schemas/flux/compose.d.ts.map +1 -1
- package/dist/schemas/flux/compose.js +74 -48
- package/dist/schemas/flux/compose.js.map +1 -1
- package/dist/schemas/flux/container.d.ts +423 -56
- package/dist/schemas/flux/container.d.ts.map +1 -1
- package/dist/schemas/flux/container.js +83 -61
- package/dist/schemas/flux/container.js.map +1 -1
- package/dist/schemas/flux/docker.d.ts +254 -37
- package/dist/schemas/flux/docker.d.ts.map +1 -1
- package/dist/schemas/flux/docker.js +69 -39
- package/dist/schemas/flux/docker.js.map +1 -1
- package/dist/schemas/flux/host.d.ts +312 -29
- package/dist/schemas/flux/host.d.ts.map +1 -1
- package/dist/schemas/flux/host.js +74 -31
- package/dist/schemas/flux/host.js.map +1 -1
- package/dist/schemas/flux/index.d.ts +503 -11
- package/dist/schemas/flux/index.d.ts.map +1 -1
- package/dist/schemas/flux/index.js +34 -70
- package/dist/schemas/flux/index.js.map +1 -1
- package/dist/schemas/host-config.d.ts +76 -0
- package/dist/schemas/host-config.d.ts.map +1 -0
- package/dist/schemas/host-config.js +105 -0
- package/dist/schemas/host-config.js.map +1 -0
- package/dist/schemas/scout/index.d.ts +80 -23
- package/dist/schemas/scout/index.d.ts.map +1 -1
- package/dist/schemas/scout/index.js +26 -11
- package/dist/schemas/scout/index.js.map +1 -1
- package/dist/schemas/scout/logs.d.ts +17 -5
- package/dist/schemas/scout/logs.d.ts.map +1 -1
- package/dist/schemas/scout/logs.js +41 -31
- package/dist/schemas/scout/logs.js.map +1 -1
- package/dist/schemas/scout/simple.d.ts +126 -11
- package/dist/schemas/scout/simple.d.ts.map +1 -1
- package/dist/schemas/scout/simple.js +112 -57
- package/dist/schemas/scout/simple.js.map +1 -1
- package/dist/schemas/scout/zfs.d.ts +17 -5
- package/dist/schemas/scout/zfs.d.ts.map +1 -1
- package/dist/schemas/scout/zfs.js +34 -25
- package/dist/schemas/scout/zfs.js.map +1 -1
- package/dist/services/cache-layer.d.ts +160 -0
- package/dist/services/cache-layer.d.ts.map +1 -0
- package/dist/services/cache-layer.js +138 -0
- package/dist/services/cache-layer.js.map +1 -0
- package/dist/services/compose-cache.d.ts +75 -0
- package/dist/services/compose-cache.d.ts.map +1 -0
- package/dist/services/compose-cache.js +178 -0
- package/dist/services/compose-cache.js.map +1 -0
- package/dist/services/compose-discovery.d.ts +46 -0
- package/dist/services/compose-discovery.d.ts.map +1 -0
- package/dist/services/compose-discovery.js +219 -0
- package/dist/services/compose-discovery.js.map +1 -0
- package/dist/services/compose-project-lister.d.ts +27 -0
- package/dist/services/compose-project-lister.d.ts.map +1 -0
- package/dist/services/compose-project-lister.js +71 -0
- package/dist/services/compose-project-lister.js.map +1 -0
- package/dist/services/compose-scanner.d.ts +63 -0
- package/dist/services/compose-scanner.d.ts.map +1 -0
- package/dist/services/compose-scanner.js +253 -0
- package/dist/services/compose-scanner.js.map +1 -0
- package/dist/services/compose.d.ts +64 -28
- package/dist/services/compose.d.ts.map +1 -1
- package/dist/services/compose.js +220 -98
- package/dist/services/compose.js.map +1 -1
- package/dist/services/config-loader.d.ts +23 -0
- package/dist/services/config-loader.d.ts.map +1 -0
- package/dist/services/config-loader.js +124 -0
- package/dist/services/config-loader.js.map +1 -0
- package/dist/services/config-service.d.ts +38 -0
- package/dist/services/config-service.d.ts.map +1 -0
- package/dist/services/config-service.js +225 -0
- package/dist/services/config-service.js.map +1 -0
- package/dist/services/container-host-map-cache.d.ts +121 -0
- package/dist/services/container-host-map-cache.d.ts.map +1 -0
- package/dist/services/container-host-map-cache.js +188 -0
- package/dist/services/container-host-map-cache.js.map +1 -0
- package/dist/services/container.d.ts +194 -6
- package/dist/services/container.d.ts.map +1 -1
- package/dist/services/container.js +386 -11
- package/dist/services/container.js.map +1 -1
- package/dist/services/diagnostics.d.ts +57 -0
- package/dist/services/diagnostics.d.ts.map +1 -0
- package/dist/services/diagnostics.js +271 -0
- package/dist/services/diagnostics.js.map +1 -0
- package/dist/services/docker/container-service.d.ts +123 -0
- package/dist/services/docker/container-service.d.ts.map +1 -0
- package/dist/services/docker/container-service.js +347 -0
- package/dist/services/docker/container-service.js.map +1 -0
- package/dist/services/docker/image-service.d.ts +82 -0
- package/dist/services/docker/image-service.d.ts.map +1 -0
- package/dist/services/docker/image-service.js +193 -0
- package/dist/services/docker/image-service.js.map +1 -0
- package/dist/services/docker/index.d.ts +80 -0
- package/dist/services/docker/index.d.ts.map +1 -0
- package/dist/services/docker/index.js +103 -0
- package/dist/services/docker/index.js.map +1 -0
- package/dist/services/docker/network-service.d.ts +22 -0
- package/dist/services/docker/network-service.d.ts.map +1 -0
- package/dist/services/docker/network-service.js +43 -0
- package/dist/services/docker/network-service.js.map +1 -0
- package/dist/services/docker/system-service.d.ts +49 -0
- package/dist/services/docker/system-service.d.ts.map +1 -0
- package/dist/services/docker/system-service.js +215 -0
- package/dist/services/docker/system-service.js.map +1 -0
- package/dist/services/docker/utils/client-factory.d.ts +56 -0
- package/dist/services/docker/utils/client-factory.d.ts.map +1 -0
- package/dist/services/docker/utils/client-factory.js +139 -0
- package/dist/services/docker/utils/client-factory.js.map +1 -0
- package/dist/services/docker/utils/client-manager.d.ts +88 -0
- package/dist/services/docker/utils/client-manager.d.ts.map +1 -0
- package/dist/services/docker/utils/client-manager.js +124 -0
- package/dist/services/docker/utils/client-manager.js.map +1 -0
- package/dist/services/docker/utils/exec-handler.d.ts +94 -0
- package/dist/services/docker/utils/exec-handler.d.ts.map +1 -0
- package/dist/services/docker/utils/exec-handler.js +197 -0
- package/dist/services/docker/utils/exec-handler.js.map +1 -0
- package/dist/services/docker/utils/formatters.d.ts +13 -0
- package/dist/services/docker/utils/formatters.d.ts.map +1 -0
- package/dist/services/docker/utils/formatters.js +33 -0
- package/dist/services/docker/utils/formatters.js.map +1 -0
- package/dist/services/docker/utils/log-parser.d.ts +10 -0
- package/dist/services/docker/utils/log-parser.d.ts.map +1 -0
- package/dist/services/docker/utils/log-parser.js +48 -0
- package/dist/services/docker/utils/log-parser.js.map +1 -0
- package/dist/services/docker/utils/stats-calculator.d.ts +68 -0
- package/dist/services/docker/utils/stats-calculator.d.ts.map +1 -0
- package/dist/services/docker/utils/stats-calculator.js +61 -0
- package/dist/services/docker/utils/stats-calculator.js.map +1 -0
- package/dist/services/docker/volume-service.d.ts +22 -0
- package/dist/services/docker/volume-service.d.ts.map +1 -0
- package/dist/services/docker/volume-service.js +48 -0
- package/dist/services/docker/volume-service.js.map +1 -0
- package/dist/services/docker-interfaces.d.ts +283 -0
- package/dist/services/docker-interfaces.d.ts.map +1 -0
- package/dist/services/docker-interfaces.js +13 -0
- package/dist/services/docker-interfaces.js.map +1 -0
- package/dist/services/docker.d.ts +42 -5
- package/dist/services/docker.d.ts.map +1 -1
- package/dist/services/docker.js +335 -127
- package/dist/services/docker.js.map +1 -1
- package/dist/services/file-service.d.ts +6 -2
- package/dist/services/file-service.d.ts.map +1 -1
- package/dist/services/file-service.js +156 -52
- package/dist/services/file-service.js.map +1 -1
- package/dist/services/host-config-repository.d.ts +133 -0
- package/dist/services/host-config-repository.d.ts.map +1 -0
- package/dist/services/host-config-repository.js +323 -0
- package/dist/services/host-config-repository.js.map +1 -0
- package/dist/services/host-resolver.d.ts +49 -0
- package/dist/services/host-resolver.d.ts.map +1 -0
- package/dist/services/host-resolver.js +176 -0
- package/dist/services/host-resolver.js.map +1 -0
- package/dist/services/interfaces.d.ts +61 -194
- package/dist/services/interfaces.d.ts.map +1 -1
- package/dist/services/local-executor.d.ts +31 -0
- package/dist/services/local-executor.d.ts.map +1 -0
- package/dist/services/local-executor.js +71 -0
- package/dist/services/local-executor.js.map +1 -0
- package/dist/services/ssh-config-loader.d.ts +35 -0
- package/dist/services/ssh-config-loader.d.ts.map +1 -0
- package/dist/services/ssh-config-loader.js +218 -0
- package/dist/services/ssh-config-loader.js.map +1 -0
- package/dist/services/ssh-pool.d.ts +26 -1
- package/dist/services/ssh-pool.d.ts.map +1 -1
- package/dist/services/ssh-pool.js +166 -25
- package/dist/services/ssh-pool.js.map +1 -1
- package/dist/services/ssh-service.d.ts +3 -0
- package/dist/services/ssh-service.d.ts.map +1 -1
- package/dist/services/ssh-service.js +53 -31
- package/dist/services/ssh-service.js.map +1 -1
- package/dist/services/ssh.d.ts +2 -6
- package/dist/services/ssh.d.ts.map +1 -1
- package/dist/services/ssh.js +9 -40
- package/dist/services/ssh.js.map +1 -1
- package/dist/tools/definitions/flux.d.ts +13 -0
- package/dist/tools/definitions/flux.d.ts.map +1 -0
- package/dist/tools/definitions/flux.js +101 -0
- package/dist/tools/definitions/flux.js.map +1 -0
- package/dist/tools/definitions/index.d.ts +8 -0
- package/dist/tools/definitions/index.d.ts.map +1 -0
- package/dist/tools/definitions/index.js +8 -0
- package/dist/tools/definitions/index.js.map +1 -0
- package/dist/tools/definitions/scout.d.ts +13 -0
- package/dist/tools/definitions/scout.d.ts.map +1 -0
- package/dist/tools/definitions/scout.js +78 -0
- package/dist/tools/definitions/scout.js.map +1 -0
- package/dist/tools/flux.d.ts +16 -8
- package/dist/tools/flux.d.ts.map +1 -1
- package/dist/tools/flux.js +27 -66
- package/dist/tools/flux.js.map +1 -1
- package/dist/tools/handlers/base-handler.d.ts +172 -0
- package/dist/tools/handlers/base-handler.d.ts.map +1 -0
- package/dist/tools/handlers/base-handler.js +234 -0
- package/dist/tools/handlers/base-handler.js.map +1 -0
- package/dist/tools/handlers/compose-handlers.d.ts +108 -0
- package/dist/tools/handlers/compose-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/compose-handlers.js +293 -0
- package/dist/tools/handlers/compose-handlers.js.map +1 -0
- package/dist/tools/handlers/compose-utils.d.ts +35 -0
- package/dist/tools/handlers/compose-utils.d.ts.map +1 -0
- package/dist/tools/handlers/compose-utils.js +76 -0
- package/dist/tools/handlers/compose-utils.js.map +1 -0
- package/dist/tools/handlers/compose.d.ts +23 -0
- package/dist/tools/handlers/compose.d.ts.map +1 -0
- package/dist/tools/handlers/compose.js +125 -0
- package/dist/tools/handlers/compose.js.map +1 -0
- package/dist/tools/handlers/container.d.ts +23 -0
- package/dist/tools/handlers/container.d.ts.map +1 -0
- package/dist/tools/handlers/container.js +333 -0
- package/dist/tools/handlers/container.js.map +1 -0
- package/dist/tools/handlers/docker.d.ts +24 -0
- package/dist/tools/handlers/docker.d.ts.map +1 -0
- package/dist/tools/handlers/docker.js +155 -0
- package/dist/tools/handlers/docker.js.map +1 -0
- package/dist/tools/handlers/host.d.ts +23 -0
- package/dist/tools/handlers/host.d.ts.map +1 -0
- package/dist/tools/handlers/host.js +196 -0
- package/dist/tools/handlers/host.js.map +1 -0
- package/dist/tools/handlers/scout-logs.d.ts +24 -0
- package/dist/tools/handlers/scout-logs.d.ts.map +1 -0
- package/dist/tools/handlers/scout-logs.js +119 -0
- package/dist/tools/handlers/scout-logs.js.map +1 -0
- package/dist/tools/handlers/scout-simple.d.ts +23 -0
- package/dist/tools/handlers/scout-simple.d.ts.map +1 -0
- package/dist/tools/handlers/scout-simple.js +286 -0
- package/dist/tools/handlers/scout-simple.js.map +1 -0
- package/dist/tools/handlers/scout-zfs.d.ts +23 -0
- package/dist/tools/handlers/scout-zfs.d.ts.map +1 -0
- package/dist/tools/handlers/scout-zfs.js +82 -0
- package/dist/tools/handlers/scout-zfs.js.map +1 -0
- package/dist/tools/index.d.ts +32 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +41 -35
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/registry.d.ts +135 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +151 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/scout.d.ts +16 -8
- package/dist/tools/scout.d.ts.map +1 -1
- package/dist/tools/scout.js +36 -78
- package/dist/tools/scout.js.map +1 -1
- package/dist/types.d.ts +629 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/command-security.d.ts +82 -0
- package/dist/utils/command-security.d.ts.map +1 -0
- package/dist/utils/command-security.js +122 -0
- package/dist/utils/command-security.js.map +1 -0
- package/dist/utils/error-sanitization.d.ts +77 -0
- package/dist/utils/error-sanitization.d.ts.map +1 -0
- package/dist/utils/error-sanitization.js +107 -0
- package/dist/utils/error-sanitization.js.map +1 -0
- package/dist/utils/errors.d.ts +30 -6
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +91 -12
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/help-handler.d.ts +23 -0
- package/dist/utils/help-handler.d.ts.map +1 -0
- package/dist/utils/help-handler.js +21 -0
- package/dist/utils/help-handler.js.map +1 -0
- package/dist/utils/help.d.ts +1 -1
- package/dist/utils/help.d.ts.map +1 -1
- package/dist/utils/help.js +57 -16
- package/dist/utils/help.js.map +1 -1
- package/dist/utils/host-utils.d.ts +31 -0
- package/dist/utils/host-utils.d.ts.map +1 -0
- package/dist/utils/host-utils.js +80 -0
- package/dist/utils/host-utils.js.map +1 -0
- package/dist/utils/index.d.ts +8 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +8 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/init-detection.d.ts +36 -0
- package/dist/utils/init-detection.d.ts.map +1 -0
- package/dist/utils/init-detection.js +79 -0
- package/dist/utils/init-detection.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pagination.d.ts +20 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +29 -0
- package/dist/utils/pagination.js.map +1 -0
- package/dist/utils/path-security.d.ts +132 -18
- package/dist/utils/path-security.d.ts.map +1 -1
- package/dist/utils/path-security.js +164 -35
- package/dist/utils/path-security.js.map +1 -1
- package/dist/utils/sorting.d.ts +33 -0
- package/dist/utils/sorting.d.ts.map +1 -0
- package/dist/utils/sorting.js +57 -0
- package/dist/utils/sorting.js.map +1 -0
- package/dist/utils/text-filters.d.ts +13 -0
- package/dist/utils/text-filters.d.ts.map +1 -0
- package/dist/utils/text-filters.js +18 -0
- package/dist/utils/text-filters.js.map +1 -0
- package/dist/utils/time.d.ts +11 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +13 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/validation.d.ts +25 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +56 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +45 -19
- package/dist/schemas/discriminator.d.ts +0 -20
- package/dist/schemas/discriminator.d.ts.map +0 -1
- package/dist/schemas/discriminator.js +0 -25
- package/dist/schemas/discriminator.js.map +0 -1
- package/dist/schemas/unified.d.ts +0 -674
- package/dist/schemas/unified.d.ts.map +0 -1
- package/dist/schemas/unified.js +0 -453
- package/dist/schemas/unified.js.map +0 -1
- package/dist/tools/unified.d.ts +0 -7
- package/dist/tools/unified.d.ts.map +0 -1
- package/dist/tools/unified.js +0 -827
- package/dist/tools/unified.js.map +0 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import Docker from "dockerode";
|
|
3
|
+
import { API_TIMEOUT } from "../../../constants.js";
|
|
4
|
+
const DEFAULT_DOCKER_SSH_CONNECT_TIMEOUT_MS = 5000;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve Docker-over-SSH connection timeout from environment.
|
|
7
|
+
*
|
|
8
|
+
* Uses a conservative default (5s) so unreachable SSH hosts fail fast.
|
|
9
|
+
* Override with DOCKER_SSH_CONNECT_TIMEOUT_MS when needed.
|
|
10
|
+
*/
|
|
11
|
+
function getDockerSshConnectTimeoutMs() {
|
|
12
|
+
const raw = process.env.DOCKER_SSH_CONNECT_TIMEOUT_MS;
|
|
13
|
+
if (!raw) {
|
|
14
|
+
return DEFAULT_DOCKER_SSH_CONNECT_TIMEOUT_MS;
|
|
15
|
+
}
|
|
16
|
+
const parsed = Number.parseInt(raw, 10);
|
|
17
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
18
|
+
return DEFAULT_DOCKER_SSH_CONNECT_TIMEOUT_MS;
|
|
19
|
+
}
|
|
20
|
+
return parsed;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if a string looks like a Unix socket path
|
|
24
|
+
*/
|
|
25
|
+
export function isSocketPath(value) {
|
|
26
|
+
return (value.startsWith("/") &&
|
|
27
|
+
(value.endsWith(".sock") || value.includes("/docker") || value.includes("/run/")));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Default Docker client factory implementation.
|
|
31
|
+
* Creates Docker clients based on host configuration (socket, SSH, HTTP/HTTPS).
|
|
32
|
+
*
|
|
33
|
+
* Architecture Note: Dual SSH Connection Strategy
|
|
34
|
+
* ------------------------------------------------
|
|
35
|
+
* This system uses TWO separate SSH connection mechanisms:
|
|
36
|
+
*
|
|
37
|
+
* 1. Docker API SSH (via dockerode/ssh2):
|
|
38
|
+
* - Used for Docker API calls (listContainers, stats, etc.)
|
|
39
|
+
* - Managed by dockerode library with native SSH tunnel support
|
|
40
|
+
* - Connections created per Docker client instance
|
|
41
|
+
* - Cached at the client level by ClientManager
|
|
42
|
+
*
|
|
43
|
+
* 2. SSH Command Execution (via node-ssh/SSHConnectionPool):
|
|
44
|
+
* - Used for shell commands (compose, find, scan, exec)
|
|
45
|
+
* - Managed by SSHConnectionPool with health checks and pooling
|
|
46
|
+
* - Connections pooled and reused across operations
|
|
47
|
+
*
|
|
48
|
+
* This separation is intentional and provides:
|
|
49
|
+
* - API operations isolated from command execution failures
|
|
50
|
+
* - Different retry/timeout strategies for different operation types
|
|
51
|
+
* - No dependency between Docker API and shell command availability
|
|
52
|
+
*
|
|
53
|
+
* Future optimization: Consider SSH multiplexing (ControlMaster) at the OS level
|
|
54
|
+
* to share TCP connections between both mechanisms.
|
|
55
|
+
*/
|
|
56
|
+
export class DefaultDockerClientFactory {
|
|
57
|
+
keyCache = new Map();
|
|
58
|
+
/**
|
|
59
|
+
* Get private key content with caching.
|
|
60
|
+
* Caching eliminates redundant file I/O for repeated client creation.
|
|
61
|
+
* Matches SSHConnectionPool pattern for consistency.
|
|
62
|
+
*/
|
|
63
|
+
getPrivateKey(keyPath) {
|
|
64
|
+
const cached = this.keyCache.get(keyPath);
|
|
65
|
+
if (cached)
|
|
66
|
+
return cached;
|
|
67
|
+
const key = readFileSync(keyPath);
|
|
68
|
+
this.keyCache.set(keyPath, key);
|
|
69
|
+
return key;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Clear cached SSH private keys.
|
|
73
|
+
* Call during shutdown to release sensitive key material from memory.
|
|
74
|
+
*/
|
|
75
|
+
clearKeyCache() {
|
|
76
|
+
this.keyCache.clear();
|
|
77
|
+
}
|
|
78
|
+
async createClient(config) {
|
|
79
|
+
// Check for explicit socket path OR socket path in host field
|
|
80
|
+
const socketPath = config.dockerSocketPath || (isSocketPath(config.host) ? config.host : null);
|
|
81
|
+
if (socketPath) {
|
|
82
|
+
// Unix socket connection
|
|
83
|
+
return new Docker({ socketPath });
|
|
84
|
+
}
|
|
85
|
+
if (config.protocol === "ssh") {
|
|
86
|
+
// SSH tunneling to Docker socket
|
|
87
|
+
// Dockerode supports SSH protocol natively via ssh:// URL
|
|
88
|
+
// Format: ssh://user@host:port
|
|
89
|
+
// SECURITY (CWE-250): Require explicit SSH user; fallback to process user, not root
|
|
90
|
+
const user = config.sshUser || process.env.USER;
|
|
91
|
+
if (!user) {
|
|
92
|
+
throw new Error(`No SSH username configured for Docker host ${config.name}. Set sshUser in config or USER env var.`);
|
|
93
|
+
}
|
|
94
|
+
if (user === "root") {
|
|
95
|
+
throw new Error(`SSH as root is not allowed for Docker host ${config.name}. Use a non-root user with Docker group access.`);
|
|
96
|
+
}
|
|
97
|
+
const port = config.port || 22;
|
|
98
|
+
const dockerOptions = {
|
|
99
|
+
protocol: "ssh",
|
|
100
|
+
host: config.host,
|
|
101
|
+
port: port,
|
|
102
|
+
username: user,
|
|
103
|
+
};
|
|
104
|
+
// Configure SSH options for agent and/or private key authentication
|
|
105
|
+
// Always use SSH agent if available (matches OpenSSH CLI behavior)
|
|
106
|
+
const sshOptions = {};
|
|
107
|
+
sshOptions.readyTimeout = getDockerSshConnectTimeoutMs();
|
|
108
|
+
if (process.env.SSH_AUTH_SOCK) {
|
|
109
|
+
sshOptions.agent = process.env.SSH_AUTH_SOCK;
|
|
110
|
+
}
|
|
111
|
+
if (config.sshKeyPath) {
|
|
112
|
+
try {
|
|
113
|
+
sshOptions.privateKey = this.getPrivateKey(config.sshKeyPath);
|
|
114
|
+
}
|
|
115
|
+
catch (_error) {
|
|
116
|
+
/* Intentionally swallow errors - will fallback to SSH agent authentication */
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Only set sshOptions if we have authentication configured
|
|
120
|
+
if (sshOptions.agent || sshOptions.privateKey) {
|
|
121
|
+
dockerOptions.sshOptions = sshOptions;
|
|
122
|
+
}
|
|
123
|
+
return new Docker(dockerOptions);
|
|
124
|
+
}
|
|
125
|
+
// Remote TCP connection (HTTP/HTTPS)
|
|
126
|
+
// Default to HTTP if no protocol specified
|
|
127
|
+
const protocol = config.protocol || "http";
|
|
128
|
+
if (protocol !== "http" && protocol !== "https") {
|
|
129
|
+
throw new Error(`Unsupported protocol: ${protocol}`);
|
|
130
|
+
}
|
|
131
|
+
return new Docker({
|
|
132
|
+
host: config.host,
|
|
133
|
+
port: config.port || 2375,
|
|
134
|
+
protocol: protocol,
|
|
135
|
+
timeout: API_TIMEOUT,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=client-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-factory.js","sourceRoot":"","sources":["../../../../src/services/docker/utils/client-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type Docker from "dockerode";
|
|
2
|
+
import type { HostConfig } from "../../../types.js";
|
|
3
|
+
import type { IDockerClientFactory } from "./client-factory.js";
|
|
4
|
+
/**
|
|
5
|
+
* Manages Docker client instances with caching.
|
|
6
|
+
* Maintains a cache of Docker clients keyed by host configuration to avoid
|
|
7
|
+
* creating multiple connections to the same Docker daemon.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ClientManager {
|
|
10
|
+
private clientFactory;
|
|
11
|
+
private clientCache;
|
|
12
|
+
private pendingClients;
|
|
13
|
+
constructor(clientFactory: IDockerClientFactory);
|
|
14
|
+
/**
|
|
15
|
+
* Get or create Docker client for a host configuration.
|
|
16
|
+
* Clients are cached based on name and host to reuse connections.
|
|
17
|
+
* Concurrent calls for the same host are deduplicated via a pending-promise map
|
|
18
|
+
* to prevent race conditions where multiple clients would be created.
|
|
19
|
+
*
|
|
20
|
+
* @param config - Host configuration for the Docker daemon
|
|
21
|
+
* @returns Docker client instance (cached or newly created)
|
|
22
|
+
*/
|
|
23
|
+
getClient(config: HostConfig): Promise<Docker>;
|
|
24
|
+
/**
|
|
25
|
+
* Clears all cached Docker clients.
|
|
26
|
+
*
|
|
27
|
+
* Call this during application shutdown or when you need to force new connections
|
|
28
|
+
* to all Docker hosts. The cached client instances will be removed, and any
|
|
29
|
+
* underlying HTTP/socket connections will be cleaned up by garbage collection
|
|
30
|
+
* when the client objects are no longer referenced.
|
|
31
|
+
*
|
|
32
|
+
* Note: Dockerode clients do not have an explicit close() method. The HTTP agent
|
|
33
|
+
* connections are automatically managed and will be released by the Node.js runtime
|
|
34
|
+
* when the client objects are garbage collected.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* // Force fresh connections on next access
|
|
39
|
+
* clientManager.clearClients();
|
|
40
|
+
*
|
|
41
|
+
* // Or during shutdown
|
|
42
|
+
* process.on('SIGTERM', () => {
|
|
43
|
+
* clientManager.clearClients();
|
|
44
|
+
* process.exit(0);
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
clearClients(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Clears a specific cached Docker client by host name.
|
|
51
|
+
*
|
|
52
|
+
* Removes all cache entries where the cache key starts with the given host name.
|
|
53
|
+
* This allows granular cache invalidation for a specific host without affecting
|
|
54
|
+
* other cached connections.
|
|
55
|
+
*
|
|
56
|
+
* @param hostName - The name of the host whose cached clients should be removed
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* // Clear only the prod-server cache
|
|
61
|
+
* clientManager.clearClient('prod-server');
|
|
62
|
+
*
|
|
63
|
+
* // Next access to prod-server will create new connection
|
|
64
|
+
* const client = clientManager.getClient({ name: 'prod-server', host: '10.0.0.1' });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
clearClient(hostName: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Gets statistics about cached Docker clients.
|
|
70
|
+
*
|
|
71
|
+
* Provides observability into the cache state, showing total number of
|
|
72
|
+
* cached clients and the list of all cache keys.
|
|
73
|
+
*
|
|
74
|
+
* @returns Object with totalClients count and hosts array of cache keys
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const stats = clientManager.getStats();
|
|
79
|
+
* console.log(`Cached clients: ${stats.totalClients}`);
|
|
80
|
+
* console.log(`Hosts: ${stats.hosts.join(', ')}`);
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
getStats(): {
|
|
84
|
+
totalClients: number;
|
|
85
|
+
hosts: string[];
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=client-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-manager.d.ts","sourceRoot":"","sources":["../../../../src/services/docker/utils/client-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE;;;;GAIG;AACH,qBAAa,aAAa;IAIZ,OAAO,CAAC,aAAa;IAHjC,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,cAAc,CAAsC;gBAExC,aAAa,EAAE,oBAAoB;IAEvD;;;;;;;;OAQG;IACG,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAgCpD;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,YAAY,IAAI,IAAI;IAKpB;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQnC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,IAAI;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE;CAMtD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages Docker client instances with caching.
|
|
3
|
+
* Maintains a cache of Docker clients keyed by host configuration to avoid
|
|
4
|
+
* creating multiple connections to the same Docker daemon.
|
|
5
|
+
*/
|
|
6
|
+
export class ClientManager {
|
|
7
|
+
clientFactory;
|
|
8
|
+
clientCache = new Map();
|
|
9
|
+
pendingClients = new Map();
|
|
10
|
+
constructor(clientFactory) {
|
|
11
|
+
this.clientFactory = clientFactory;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get or create Docker client for a host configuration.
|
|
15
|
+
* Clients are cached based on name and host to reuse connections.
|
|
16
|
+
* Concurrent calls for the same host are deduplicated via a pending-promise map
|
|
17
|
+
* to prevent race conditions where multiple clients would be created.
|
|
18
|
+
*
|
|
19
|
+
* @param config - Host configuration for the Docker daemon
|
|
20
|
+
* @returns Docker client instance (cached or newly created)
|
|
21
|
+
*/
|
|
22
|
+
async getClient(config) {
|
|
23
|
+
const cacheKey = `${config.name}-${config.host}`;
|
|
24
|
+
const cached = this.clientCache.get(cacheKey);
|
|
25
|
+
if (cached) {
|
|
26
|
+
return cached;
|
|
27
|
+
}
|
|
28
|
+
// Check if another caller is already creating a client for this key
|
|
29
|
+
const pending = this.pendingClients.get(cacheKey);
|
|
30
|
+
if (pending) {
|
|
31
|
+
return pending;
|
|
32
|
+
}
|
|
33
|
+
// Create client with deduplication — store the promise so concurrent
|
|
34
|
+
// callers await the same creation instead of spawning duplicates
|
|
35
|
+
const clientPromise = this.clientFactory
|
|
36
|
+
.createClient(config)
|
|
37
|
+
.then((client) => {
|
|
38
|
+
this.clientCache.set(cacheKey, client);
|
|
39
|
+
this.pendingClients.delete(cacheKey);
|
|
40
|
+
return client;
|
|
41
|
+
})
|
|
42
|
+
.catch((error) => {
|
|
43
|
+
this.pendingClients.delete(cacheKey);
|
|
44
|
+
throw error;
|
|
45
|
+
});
|
|
46
|
+
this.pendingClients.set(cacheKey, clientPromise);
|
|
47
|
+
return clientPromise;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Clears all cached Docker clients.
|
|
51
|
+
*
|
|
52
|
+
* Call this during application shutdown or when you need to force new connections
|
|
53
|
+
* to all Docker hosts. The cached client instances will be removed, and any
|
|
54
|
+
* underlying HTTP/socket connections will be cleaned up by garbage collection
|
|
55
|
+
* when the client objects are no longer referenced.
|
|
56
|
+
*
|
|
57
|
+
* Note: Dockerode clients do not have an explicit close() method. The HTTP agent
|
|
58
|
+
* connections are automatically managed and will be released by the Node.js runtime
|
|
59
|
+
* when the client objects are garbage collected.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* // Force fresh connections on next access
|
|
64
|
+
* clientManager.clearClients();
|
|
65
|
+
*
|
|
66
|
+
* // Or during shutdown
|
|
67
|
+
* process.on('SIGTERM', () => {
|
|
68
|
+
* clientManager.clearClients();
|
|
69
|
+
* process.exit(0);
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
clearClients() {
|
|
74
|
+
this.clientCache.clear();
|
|
75
|
+
this.pendingClients.clear();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Clears a specific cached Docker client by host name.
|
|
79
|
+
*
|
|
80
|
+
* Removes all cache entries where the cache key starts with the given host name.
|
|
81
|
+
* This allows granular cache invalidation for a specific host without affecting
|
|
82
|
+
* other cached connections.
|
|
83
|
+
*
|
|
84
|
+
* @param hostName - The name of the host whose cached clients should be removed
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* // Clear only the prod-server cache
|
|
89
|
+
* clientManager.clearClient('prod-server');
|
|
90
|
+
*
|
|
91
|
+
* // Next access to prod-server will create new connection
|
|
92
|
+
* const client = clientManager.getClient({ name: 'prod-server', host: '10.0.0.1' });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
clearClient(hostName) {
|
|
96
|
+
for (const key of this.clientCache.keys()) {
|
|
97
|
+
if (key.startsWith(`${hostName}-`)) {
|
|
98
|
+
this.clientCache.delete(key);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Gets statistics about cached Docker clients.
|
|
104
|
+
*
|
|
105
|
+
* Provides observability into the cache state, showing total number of
|
|
106
|
+
* cached clients and the list of all cache keys.
|
|
107
|
+
*
|
|
108
|
+
* @returns Object with totalClients count and hosts array of cache keys
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const stats = clientManager.getStats();
|
|
113
|
+
* console.log(`Cached clients: ${stats.totalClients}`);
|
|
114
|
+
* console.log(`Hosts: ${stats.hosts.join(', ')}`);
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
getStats() {
|
|
118
|
+
return {
|
|
119
|
+
totalClients: this.clientCache.size,
|
|
120
|
+
hosts: Array.from(this.clientCache.keys()),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=client-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-manager.js","sourceRoot":"","sources":["../../../../src/services/docker/utils/client-manager.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,OAAO,aAAa;IAIJ;IAHZ,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,cAAc,GAAG,IAAI,GAAG,EAA2B,CAAC;IAE5D,YAAoB,aAAmC;QAAnC,kBAAa,GAAb,aAAa,CAAsB;IAAG,CAAC;IAE3D;;;;;;;;OAQG;IACH,KAAK,CAAC,SAAS,CAAC,MAAkB;QAChC,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAEjD,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,oEAAoE;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,qEAAqE;QACrE,iEAAiE;QACjE,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa;aACrC,YAAY,CAAC,MAAM,CAAC;aACpB,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACrC,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QAEL,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QACjD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,YAAY;QACV,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,QAAgB;QAC1B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1C,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,QAAQ;QACN,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI;YACnC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;SAC3C,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { PassThrough } from "node:stream";
|
|
2
|
+
import type Docker from "dockerode";
|
|
3
|
+
/**
|
|
4
|
+
* Stream context for container exec operations.
|
|
5
|
+
* Manages all streams and buffers for capturing command output.
|
|
6
|
+
*/
|
|
7
|
+
export interface ExecStreamContext {
|
|
8
|
+
stream: NodeJS.ReadableStream;
|
|
9
|
+
stdoutStream: PassThrough;
|
|
10
|
+
stderrStream: PassThrough;
|
|
11
|
+
stdoutChunks: Buffer[];
|
|
12
|
+
stderrChunks: Buffer[];
|
|
13
|
+
stdoutSize: number;
|
|
14
|
+
stderrSize: number;
|
|
15
|
+
bufferExceeded: {
|
|
16
|
+
value: boolean;
|
|
17
|
+
};
|
|
18
|
+
cleanup: () => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Settlement handlers for promise resolution.
|
|
22
|
+
* Ensures only one settlement (success or rejection) occurs.
|
|
23
|
+
*/
|
|
24
|
+
export interface SettlementHandlers {
|
|
25
|
+
settleWithRejection: (error: Error) => void;
|
|
26
|
+
settleWithSuccess: () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Set up Docker exec instance with validated command.
|
|
30
|
+
* Validates command against allowlist and creates exec configuration.
|
|
31
|
+
*
|
|
32
|
+
* @param container - Docker container instance
|
|
33
|
+
* @param options - Exec options including command, user, and workdir
|
|
34
|
+
* @returns Promise resolving to Docker.Exec instance
|
|
35
|
+
* @throws Error if command validation fails
|
|
36
|
+
*/
|
|
37
|
+
export declare function setupExecInstance(container: Docker.Container, options: {
|
|
38
|
+
command: string;
|
|
39
|
+
user?: string;
|
|
40
|
+
workdir?: string;
|
|
41
|
+
}): Promise<Docker.Exec>;
|
|
42
|
+
/**
|
|
43
|
+
* Set up buffer tracking for stdout and stderr streams.
|
|
44
|
+
* Attaches data event handlers that track buffer sizes and detect overflows.
|
|
45
|
+
*
|
|
46
|
+
* @param context - Stream context containing streams and buffer state
|
|
47
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
48
|
+
*/
|
|
49
|
+
export declare function setupBufferTracking(context: Pick<ExecStreamContext, "stdoutStream" | "stderrStream" | "stdoutChunks" | "stderrChunks" | "stdoutSize" | "stderrSize" | "bufferExceeded" | "cleanup">, maxBuffer: number): void;
|
|
50
|
+
/**
|
|
51
|
+
* Create stream context for exec operation.
|
|
52
|
+
* Sets up streams, buffers, and cleanup handler for container exec.
|
|
53
|
+
*
|
|
54
|
+
* @param exec - Docker exec instance
|
|
55
|
+
* @param modem - Docker modem for stream demuxing
|
|
56
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
57
|
+
* @returns Stream context with initialized streams and cleanup function
|
|
58
|
+
*/
|
|
59
|
+
export declare function createStreamContext(exec: Docker.Exec, modem: ReturnType<Docker["getContainer"]>["modem"], maxBuffer: number): Promise<ExecStreamContext>;
|
|
60
|
+
/**
|
|
61
|
+
* Attach event handlers for execution monitoring.
|
|
62
|
+
* Sets up error, data, and end event listeners on streams.
|
|
63
|
+
*
|
|
64
|
+
* @param context - Stream context with streams and buffer state
|
|
65
|
+
* @param handlers - Handler functions for error, success, and buffer checks
|
|
66
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
67
|
+
*/
|
|
68
|
+
export declare function attachExecutionHandlers(context: Pick<ExecStreamContext, "stream" | "stdoutStream" | "stderrStream" | "bufferExceeded">, handlers: {
|
|
69
|
+
onError: (err: Error) => void;
|
|
70
|
+
onSuccess: () => void;
|
|
71
|
+
checkBufferExceeded: () => void;
|
|
72
|
+
}, maxBuffer: number): void;
|
|
73
|
+
/**
|
|
74
|
+
* Create settlement handlers with guard against double settlement.
|
|
75
|
+
* Encapsulates cleanup and promise settlement logic.
|
|
76
|
+
*
|
|
77
|
+
* @param cleanup - Cleanup function to call before settlement
|
|
78
|
+
* @param resolve - Promise resolve function
|
|
79
|
+
* @param reject - Promise reject function
|
|
80
|
+
* @returns Settlement handlers object
|
|
81
|
+
*/
|
|
82
|
+
export declare function createSettlementHandlers(cleanup: () => void, resolve: () => void, reject: (error: Error) => void): SettlementHandlers;
|
|
83
|
+
/**
|
|
84
|
+
* Execute with timeout and buffer limit monitoring.
|
|
85
|
+
* Wraps stream context in promise with timeout and error handling.
|
|
86
|
+
*
|
|
87
|
+
* @param context - Stream context from createStreamContext
|
|
88
|
+
* @param timeout - Timeout in milliseconds
|
|
89
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
90
|
+
* @returns Promise that resolves when stream completes successfully
|
|
91
|
+
* @throws Error on timeout, buffer exceeded, or stream error
|
|
92
|
+
*/
|
|
93
|
+
export declare function executeWithTimeout(context: Pick<ExecStreamContext, "stream" | "stdoutStream" | "stderrStream" | "bufferExceeded" | "cleanup">, timeout: number, maxBuffer: number): Promise<void>;
|
|
94
|
+
//# sourceMappingURL=exec-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-handler.d.ts","sourceRoot":"","sources":["../../../../src/services/docker/utils/exec-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAGpC;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,YAAY,EAAE,WAAW,CAAC;IAC1B,YAAY,EAAE,WAAW,CAAC;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,mBAAmB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC5C,iBAAiB,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,CAAC,SAAS,EAC3B,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAUtB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,IAAI,CACX,iBAAiB,EACf,cAAc,GACd,cAAc,GACd,cAAc,GACd,cAAc,GACd,YAAY,GACZ,YAAY,GACZ,gBAAgB,GAChB,SAAS,CACZ,EACD,SAAS,EAAE,MAAM,GAChB,IAAI,CA4BN;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,EAClD,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,CAAC,CA0C5B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,CAAC,EAC/F,QAAQ,EAAE;IACR,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACjC,EACD,SAAS,EAAE,MAAM,GAChB,IAAI,CAkBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,IAAI,EACnB,OAAO,EAAE,MAAM,IAAI,EACnB,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAC7B,kBAAkB,CAiBpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,IAAI,CACX,iBAAiB,EACjB,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,GAAG,SAAS,CAC1E,EACD,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAwCf"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { PassThrough } from "node:stream";
|
|
2
|
+
import { validateCommandAllowlist } from "../../../utils/command-security.js";
|
|
3
|
+
/**
|
|
4
|
+
* Set up Docker exec instance with validated command.
|
|
5
|
+
* Validates command against allowlist and creates exec configuration.
|
|
6
|
+
*
|
|
7
|
+
* @param container - Docker container instance
|
|
8
|
+
* @param options - Exec options including command, user, and workdir
|
|
9
|
+
* @returns Promise resolving to Docker.Exec instance
|
|
10
|
+
* @throws Error if command validation fails
|
|
11
|
+
*/
|
|
12
|
+
export async function setupExecInstance(container, options) {
|
|
13
|
+
const parts = validateCommandAllowlist(options.command);
|
|
14
|
+
return await container.exec({
|
|
15
|
+
Cmd: parts,
|
|
16
|
+
AttachStdout: true,
|
|
17
|
+
AttachStderr: true,
|
|
18
|
+
User: options.user,
|
|
19
|
+
WorkingDir: options.workdir,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Set up buffer tracking for stdout and stderr streams.
|
|
24
|
+
* Attaches data event handlers that track buffer sizes and detect overflows.
|
|
25
|
+
*
|
|
26
|
+
* @param context - Stream context containing streams and buffer state
|
|
27
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
28
|
+
*/
|
|
29
|
+
export function setupBufferTracking(context, maxBuffer) {
|
|
30
|
+
// Track stdout buffer size and set flag if limit exceeded
|
|
31
|
+
context.stdoutStream.on("data", (chunk) => {
|
|
32
|
+
if (context.bufferExceeded.value)
|
|
33
|
+
return;
|
|
34
|
+
if (context.stdoutSize + chunk.length > maxBuffer) {
|
|
35
|
+
context.bufferExceeded.value = true;
|
|
36
|
+
context.cleanup();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
context.stdoutSize += chunk.length;
|
|
40
|
+
context.stdoutChunks.push(chunk);
|
|
41
|
+
});
|
|
42
|
+
// Track stderr buffer size and set flag if limit exceeded
|
|
43
|
+
context.stderrStream.on("data", (chunk) => {
|
|
44
|
+
if (context.bufferExceeded.value)
|
|
45
|
+
return;
|
|
46
|
+
if (context.stderrSize + chunk.length > maxBuffer) {
|
|
47
|
+
context.bufferExceeded.value = true;
|
|
48
|
+
context.cleanup();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
context.stderrSize += chunk.length;
|
|
52
|
+
context.stderrChunks.push(chunk);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create stream context for exec operation.
|
|
57
|
+
* Sets up streams, buffers, and cleanup handler for container exec.
|
|
58
|
+
*
|
|
59
|
+
* @param exec - Docker exec instance
|
|
60
|
+
* @param modem - Docker modem for stream demuxing
|
|
61
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
62
|
+
* @returns Stream context with initialized streams and cleanup function
|
|
63
|
+
*/
|
|
64
|
+
export async function createStreamContext(exec, modem, maxBuffer) {
|
|
65
|
+
const stream = await exec.start({ hijack: true, stdin: false });
|
|
66
|
+
const stdoutStream = new PassThrough();
|
|
67
|
+
const stderrStream = new PassThrough();
|
|
68
|
+
const stdoutChunks = [];
|
|
69
|
+
const stderrChunks = [];
|
|
70
|
+
const bufferExceeded = { value: false };
|
|
71
|
+
const context = {
|
|
72
|
+
stream,
|
|
73
|
+
stdoutStream,
|
|
74
|
+
stderrStream,
|
|
75
|
+
stdoutChunks,
|
|
76
|
+
stderrChunks,
|
|
77
|
+
stdoutSize: 0,
|
|
78
|
+
stderrSize: 0,
|
|
79
|
+
bufferExceeded,
|
|
80
|
+
cleanup: () => {
|
|
81
|
+
try {
|
|
82
|
+
stream.destroy();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
/* Intentionally swallow errors - stream already destroyed or errored */
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
stdoutStream.destroy();
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
/* Intentionally swallow errors - stream already destroyed or errored */
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
stderrStream.destroy();
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
/* Intentionally swallow errors - stream already destroyed or errored */
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
setupBufferTracking(context, maxBuffer);
|
|
102
|
+
// Demux the main stream into stdout and stderr
|
|
103
|
+
modem.demuxStream(stream, stdoutStream, stderrStream);
|
|
104
|
+
return context;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Attach event handlers for execution monitoring.
|
|
108
|
+
* Sets up error, data, and end event listeners on streams.
|
|
109
|
+
*
|
|
110
|
+
* @param context - Stream context with streams and buffer state
|
|
111
|
+
* @param handlers - Handler functions for error, success, and buffer checks
|
|
112
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
113
|
+
*/
|
|
114
|
+
export function attachExecutionHandlers(context, handlers, maxBuffer) {
|
|
115
|
+
// Handle stream errors
|
|
116
|
+
context.stream.on("error", handlers.onError);
|
|
117
|
+
context.stdoutStream.on("error", handlers.onError);
|
|
118
|
+
context.stderrStream.on("error", handlers.onError);
|
|
119
|
+
// Check for buffer exceeded after each data event
|
|
120
|
+
context.stdoutStream.on("data", handlers.checkBufferExceeded);
|
|
121
|
+
context.stderrStream.on("data", handlers.checkBufferExceeded);
|
|
122
|
+
// Handle stream end
|
|
123
|
+
context.stream.on("end", () => {
|
|
124
|
+
if (context.bufferExceeded.value) {
|
|
125
|
+
handlers.onError(new Error(`Buffer limit exceeded: output exceeded ${maxBuffer} bytes`));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
handlers.onSuccess();
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Create settlement handlers with guard against double settlement.
|
|
134
|
+
* Encapsulates cleanup and promise settlement logic.
|
|
135
|
+
*
|
|
136
|
+
* @param cleanup - Cleanup function to call before settlement
|
|
137
|
+
* @param resolve - Promise resolve function
|
|
138
|
+
* @param reject - Promise reject function
|
|
139
|
+
* @returns Settlement handlers object
|
|
140
|
+
*/
|
|
141
|
+
export function createSettlementHandlers(cleanup, resolve, reject) {
|
|
142
|
+
let settled = false;
|
|
143
|
+
return {
|
|
144
|
+
settleWithRejection: (error) => {
|
|
145
|
+
if (settled)
|
|
146
|
+
return;
|
|
147
|
+
settled = true;
|
|
148
|
+
cleanup();
|
|
149
|
+
reject(error);
|
|
150
|
+
},
|
|
151
|
+
settleWithSuccess: () => {
|
|
152
|
+
if (settled)
|
|
153
|
+
return;
|
|
154
|
+
settled = true;
|
|
155
|
+
cleanup();
|
|
156
|
+
resolve();
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Execute with timeout and buffer limit monitoring.
|
|
162
|
+
* Wraps stream context in promise with timeout and error handling.
|
|
163
|
+
*
|
|
164
|
+
* @param context - Stream context from createStreamContext
|
|
165
|
+
* @param timeout - Timeout in milliseconds
|
|
166
|
+
* @param maxBuffer - Maximum buffer size in bytes
|
|
167
|
+
* @returns Promise that resolves when stream completes successfully
|
|
168
|
+
* @throws Error on timeout, buffer exceeded, or stream error
|
|
169
|
+
*/
|
|
170
|
+
export async function executeWithTimeout(context, timeout, maxBuffer) {
|
|
171
|
+
let timeoutId = null;
|
|
172
|
+
const cleanup = () => {
|
|
173
|
+
if (timeoutId !== null) {
|
|
174
|
+
clearTimeout(timeoutId);
|
|
175
|
+
timeoutId = null;
|
|
176
|
+
}
|
|
177
|
+
context.cleanup();
|
|
178
|
+
};
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
const { settleWithRejection, settleWithSuccess } = createSettlementHandlers(cleanup, resolve, reject);
|
|
181
|
+
// Set up timeout
|
|
182
|
+
timeoutId = setTimeout(() => {
|
|
183
|
+
settleWithRejection(new Error(`Exec timeout: command exceeded ${timeout}ms limit`));
|
|
184
|
+
}, timeout);
|
|
185
|
+
// Attach stream event handlers
|
|
186
|
+
attachExecutionHandlers(context, {
|
|
187
|
+
onError: settleWithRejection,
|
|
188
|
+
onSuccess: settleWithSuccess,
|
|
189
|
+
checkBufferExceeded: () => {
|
|
190
|
+
if (context.bufferExceeded.value) {
|
|
191
|
+
settleWithRejection(new Error(`Buffer limit exceeded: output exceeded ${maxBuffer} bytes`));
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
}, maxBuffer);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=exec-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-handler.js","sourceRoot":"","sources":["../../../../src/services/docker/utils/exec-handler.ts"],"names":[],"mappings":"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"}
|