@underpostnet/cyberia 3.2.90 → 3.3.73
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/.dockerignore +1 -0
- package/.env.example +16 -0
- package/.github/workflows/coverall.cyberia.ci.yml +107 -0
- package/.github/workflows/cyberia-client.cd.yml +6 -18
- package/.github/workflows/cyberia-server.cd.yml +6 -18
- package/.github/workflows/docker-image.cyberia-client.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-client.dev.ci.yml +8 -3
- package/.github/workflows/docker-image.cyberia-server.ci.yml +8 -5
- package/.github/workflows/docker-image.cyberia-server.dev.ci.yml +8 -5
- package/.github/workflows/docker-image.engine-cyberia.ci.yml +15 -1
- package/.github/workflows/docker-image.engine-cyberia.dev.ci.yml +15 -1
- package/.github/workflows/engine-cyberia.cd.yml +6 -78
- package/.github/workflows/engine-cyberia.ci.yml +4 -5
- package/.github/workflows/ghpkg.ci.yml +42 -21
- package/.github/workflows/hardhat.ci.yml +12 -11
- package/.github/workflows/npmpkg.ci.yml +17 -15
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
- package/.github/workflows/pwa-microservices-template-test.ci.yml +2 -2
- package/.github/workflows/release.cd.yml +2 -9
- package/.prettierignore +1 -0
- package/AGENTS.md +47 -0
- package/CHANGELOG.md +581 -2417
- package/CLI-HELP.md +416 -127
- package/Dockerfile +25 -9
- package/Dockerfile.dev +25 -9
- package/Dockerfile.test +4 -4
- package/README.md +21 -1
- package/bin/build.js +70 -43
- package/bin/build.template.js +8 -3
- package/bin/cyberia.js +372 -135
- package/bin/deploy.js +18 -104
- package/bin/index.js +372 -135
- package/compose.env +16 -0
- package/conf.js +93 -4
- package/deploy/cyberia-client/deploy.sh +47 -0
- package/deploy/cyberia-client/package.sh +18 -0
- package/deploy/cyberia-client/state.sh +14 -0
- package/deploy/cyberia-server/deploy.sh +47 -0
- package/deploy/cyberia-server/package.sh +18 -0
- package/deploy/cyberia-server/state.sh +14 -0
- package/deploy/dd-cyberia/deploy.sh +22 -0
- package/deploy/dd-cyberia/init.sh +55 -0
- package/deploy/dd-cyberia/package.sh +17 -0
- package/deploy/dd-cyberia/state.sh +14 -0
- package/deploy/dd-cyberia/sync-deploy.sh +116 -0
- package/deploy/lib/github-actions-logging.sh +594 -0
- package/deploy/lib/host.sh +185 -0
- package/deploy/lib/state.sh +62 -0
- package/deploy/pwa-microservices-template/deploy.sh +45 -0
- package/deploy/release/deploy.sh +32 -0
- package/deployment.yaml +7 -2
- package/docker-compose.yml +31 -37
- package/examples/static-page/README.md +19 -19
- package/examples/static-page/ssr-components/CustomPage.js +2 -2
- package/hardhat/hardhat.config.js +1 -6
- package/hardhat/package-lock.json +104 -43
- package/hardhat/package.json +3 -3
- package/manifests/alertmanager/deployment.yaml +81 -0
- package/manifests/blackbox-exporter/deployment.yaml +75 -0
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +36 -7
- package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +77 -0
- package/manifests/deployment/dd-cyberia-development/deployment.yaml +7 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/grafana/deployment.yaml +26 -7
- package/manifests/grafana/kustomization.yaml +1 -0
- package/manifests/grafana/service.yaml +6 -1
- package/manifests/mariadb/pv.yaml +1 -0
- package/manifests/mongodb/statefulset.yaml +9 -2
- package/manifests/mysql/pv-pvc.yaml +14 -1
- package/manifests/postgresql/pv.yaml +12 -1
- package/manifests/postgresql/pvc.yaml +1 -0
- package/manifests/prometheus/deployment.yaml +18 -22
- package/package.json +83 -10
- package/scripts/audit-selinux.sh +64 -0
- package/scripts/event-monitor.sh +56 -0
- package/scripts/gpu-diag.sh +0 -0
- package/scripts/ip-info.sh +0 -0
- package/scripts/k3s-node-setup.sh +30 -14
- package/scripts/kubeadm-node-setup.sh +40 -31
- package/scripts/lxd-vm-setup.sh +0 -0
- package/scripts/maas-nat-firewalld.sh +0 -0
- package/scripts/maas-setup.sh +8 -8
- package/scripts/nat-iptables.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +0 -0
- package/scripts/rocky-kickstart.sh +25 -9
- package/scripts/selinux-normalize.sh +907 -0
- package/scripts/shutdown-machine.sh +843 -0
- package/scripts/test-monitor.sh +3 -3
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +1 -1
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.router.js +2 -2
- package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +2 -2
- package/src/api/core/core.controller.js +1 -1
- package/src/api/core/core.router.js +2 -2
- package/src/api/core/core.service.js +2 -2
- package/src/api/crypto/crypto.controller.js +1 -1
- package/src/api/crypto/crypto.service.js +1 -1
- package/src/api/cyberia-action/cyberia-action.controller.js +1 -1
- package/src/api/cyberia-action/cyberia-action.router.js +1 -1
- package/src/api/cyberia-action/cyberia-action.service.js +2 -2
- package/src/api/cyberia-client-hints/cyberia-client-hints.controller.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.router.js +1 -1
- package/src/api/cyberia-client-hints/cyberia-client-hints.service.js +2 -2
- package/src/api/cyberia-dialogue/cyberia-dialogue.controller.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.router.js +1 -1
- package/src/api/cyberia-dialogue/cyberia-dialogue.service.js +2 -2
- package/src/api/cyberia-entity/cyberia-entity.controller.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.router.js +1 -1
- package/src/api/cyberia-entity/cyberia-entity.service.js +2 -2
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.controller.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.router.js +1 -1
- package/src/api/cyberia-entity-type-default/cyberia-entity-type-default.service.js +2 -2
- package/src/api/cyberia-instance/cyberia-fallback-capture.js +466 -0
- package/src/api/cyberia-instance/cyberia-fallback-default-items.js +63 -0
- package/src/api/cyberia-instance/cyberia-fallback-world.js +16 -1
- package/src/api/cyberia-instance/cyberia-instance-map.service.js +1 -1
- package/src/api/cyberia-instance/cyberia-instance.controller.js +4 -1
- package/src/api/cyberia-instance/cyberia-instance.router.js +15 -2
- package/src/api/cyberia-instance/cyberia-instance.service.js +45 -2
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.controller.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.model.js +1 -0
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.router.js +1 -1
- package/src/api/cyberia-instance-conf/cyberia-instance-conf.service.js +2 -2
- package/src/api/cyberia-map/cyberia-map.controller.js +1 -1
- package/src/api/cyberia-map/cyberia-map.router.js +1 -1
- package/src/api/cyberia-map/cyberia-map.service.js +2 -2
- package/src/api/cyberia-quest/cyberia-quest.controller.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.router.js +1 -1
- package/src/api/cyberia-quest/cyberia-quest.service.js +2 -2
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.controller.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.router.js +1 -1
- package/src/api/cyberia-quest-progress/cyberia-quest-progress.service.js +2 -2
- package/src/api/cyberia-saga/cyberia-saga.controller.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.router.js +1 -1
- package/src/api/cyberia-saga/cyberia-saga.service.js +2 -2
- package/src/api/cyberia-server-defaults/cyberia-server-defaults.js +16 -29
- package/src/api/cyberia-skill/cyberia-skill.controller.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.router.js +1 -1
- package/src/api/cyberia-skill/cyberia-skill.service.js +2 -2
- package/src/api/default/default.controller.js +1 -1
- package/src/api/default/default.router.js +1 -1
- package/src/api/default/default.service.js +2 -2
- package/src/api/document/document.controller.js +1 -1
- package/src/api/document/document.router.js +1 -1
- package/src/api/document/document.service.js +2 -2
- package/src/api/file/file.controller.js +1 -1
- package/src/api/file/file.router.js +1 -1
- package/src/api/file/file.service.js +2 -2
- package/src/api/instance/instance.controller.js +1 -1
- package/src/api/instance/instance.router.js +1 -1
- package/src/api/instance/instance.service.js +2 -2
- package/src/api/ipfs/ipfs.controller.js +1 -1
- package/src/api/ipfs/ipfs.router.js +2 -2
- package/src/api/ipfs/ipfs.service.js +2 -2
- package/src/api/object-layer/object-layer.controller.js +1 -1
- package/src/api/object-layer/object-layer.model.js +204 -3
- package/src/api/object-layer/object-layer.router.js +2 -2
- package/src/api/object-layer/object-layer.service.js +4 -17
- package/src/api/object-layer-render-frames/object-layer-render-frames.controller.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.router.js +1 -1
- package/src/api/object-layer-render-frames/object-layer-render-frames.service.js +2 -2
- package/src/api/test/test.controller.js +1 -1
- package/src/api/test/test.service.js +1 -1
- package/src/api/user/guest.service.js +3 -3
- package/src/api/user/user.controller.js +1 -1
- package/src/api/user/user.router.js +2 -2
- package/src/api/user/user.service.js +4 -4
- package/src/api.js +5 -9
- package/src/cli/app.js +391 -0
- package/src/cli/baremetal.js +30 -36
- package/src/cli/client.js +306 -0
- package/src/cli/cloud-init.js +3 -3
- package/src/cli/cluster.js +242 -135
- package/src/cli/db.js +126 -67
- package/src/cli/deploy.js +158 -60
- package/src/cli/docker-compose.js +5 -5
- package/src/cli/domains.js +184 -0
- package/src/cli/dotenv-store.js +143 -0
- package/src/cli/event.js +2281 -0
- package/src/cli/fs.js +3 -3
- package/src/cli/host.js +672 -0
- package/src/cli/image.js +4 -7
- package/src/cli/index.js +426 -134
- package/src/cli/ipfs.js +34 -30
- package/src/cli/kickstart.js +1 -1
- package/src/cli/kubectl.js +218 -41
- package/src/cli/lxd.js +3 -3
- package/src/cli/monitor.js +1359 -26
- package/src/cli/package.js +90 -0
- package/src/cli/release.js +73 -34
- package/src/cli/repository.js +564 -367
- package/src/cli/run.js +362 -654
- package/src/cli/secrets.js +2158 -964
- package/src/cli/ssh.js +651 -331
- package/src/cli/state.js +394 -0
- package/src/cli/static.js +2 -2
- package/src/cli/system.js +26 -13
- package/src/cli/test.js +199 -125
- package/src/cli/vultr.js +623 -0
- package/src/cli/wireguard.js +2930 -0
- package/src/client/components/core/CalendarCore.js +53 -96
- package/src/client/components/core/Docs.js +258 -211
- package/src/client/components/core/FileExplorer.js +0 -21
- package/src/client/components/core/PanelForm.js +4 -4
- package/src/client/components/core/Repository.js +56 -0
- package/src/client/components/core/Translate.js +7 -0
- package/src/client/components/core/{FullScreen.js → ViewModeController.js} +42 -39
- package/src/client/components/core/Wallet.js +0 -11
- package/src/client/components/core/Worker.js +7 -1
- package/src/client/components/cryptokoyn/SettingsCryptokoyn.js +2 -2
- package/src/client/components/cyberia/FallbackWorldEngineCyberia.js +368 -0
- package/src/client/components/cyberia-portal/AppShellCyberiaPortal.js +35 -1
- package/src/client/components/cyberia-portal/RouterCyberiaPortal.js +4 -0
- package/src/client/components/cyberia-portal/SettingsCyberiaPortal.js +2 -2
- package/src/client/components/cyberia-portal/TranslateCyberiaPortal.js +4 -0
- package/src/client/components/default/AppShellDefault.js +1 -1
- package/src/client/components/default/SettingsDefault.js +2 -2
- package/src/client/components/itemledger/SettingsItemledger.js +2 -2
- package/src/client/components/underpost/AppShellUnderpost.js +3 -2
- package/src/client/components/underpost/SettingsUnderpost.js +2 -2
- package/src/client/public/cyberia-docs/ARCHITECTURE.md +17 -3
- package/src/client/public/cyberia-docs/CYBERIA-CLI.md +32 -5
- package/src/client/public/cyberia-docs/CYBERIA-SERVER.md +1 -1
- package/src/client/public/cyberia-docs/CYBERIA.md +21 -1
- package/src/client/public/cyberia-docs/HARDHAT-MODULE.md +23 -6
- package/src/client/public/cyberia-docs/ROADMAP.md +1 -1
- package/src/client/public/cyberia-docs/WHITE-PAPER.md +1 -1
- package/src/client/public/default/android-chrome-144x144.png +0 -0
- package/src/client/public/default/android-chrome-192x192.png +0 -0
- package/src/client/public/default/android-chrome-256x256.png +0 -0
- package/src/client/public/default/android-chrome-36x36.png +0 -0
- package/src/client/public/default/android-chrome-384x384.png +0 -0
- package/src/client/public/default/android-chrome-48x48.png +0 -0
- package/src/client/public/default/android-chrome-512x512.png +0 -0
- package/src/client/public/default/android-chrome-72x72.png +0 -0
- package/src/client/public/default/android-chrome-96x96.png +0 -0
- package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
- package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
- package/src/client/public/default/assets/background/white.jpg +0 -0
- package/src/client/public/default/browserconfig.xml +1 -1
- package/src/client/public/default/favicon-16x16.png +0 -0
- package/src/client/public/default/favicon-32x32.png +0 -0
- package/src/client/public/default/favicon-48x48.png +0 -0
- package/src/client/public/default/favicon.ico +0 -0
- package/src/client/public/default/manifest.webmanifest +5 -5
- package/src/client/public/default/mstile-144x144.png +0 -0
- package/src/client/public/default/mstile-150x150.png +0 -0
- package/src/client/public/default/mstile-310x150.png +0 -0
- package/src/client/public/default/mstile-310x310.png +0 -0
- package/src/client/public/default/mstile-70x70.png +0 -0
- package/src/client/public/default/yandex-browser-50x50.png +0 -0
- package/src/client/public/default/yandex-browser-manifest.json +1 -1
- package/src/client/services/cyberia-instance/cyberia-instance.service.js +40 -0
- package/src/client/services/object-layer/object-layer.management.js +4 -4
- package/src/client/ssr/RootDocument.js +1 -1
- package/src/client/ssr/body/404.js +1 -1
- package/src/client/ssr/body/500.js +1 -1
- package/src/client/ssr/body/CacheControl.js +1 -1
- package/src/client/ssr/body/CyberiaDefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/DefaultSplashScreen.js +1 -1
- package/src/client/ssr/body/SwaggerDarkMode.js +1 -1
- package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +1 -1
- package/src/client/ssr/head/CryptokoynScripts.js +1 -1
- package/src/client/ssr/head/Css.js +1 -1
- package/src/client/ssr/head/CyberiaPortalScripts.js +1 -1
- package/src/client/ssr/head/DefaultScripts.js +1 -1
- package/src/client/ssr/head/ItemledgerScripts.js +1 -1
- package/src/client/ssr/head/Microdata.js +1 -1
- package/src/client/ssr/head/Production.js +1 -1
- package/src/client/ssr/head/Pwa.js +1 -1
- package/src/client/ssr/head/PwaItemledger.js +1 -1
- package/src/client/ssr/head/Seo.js +1 -1
- package/src/client/ssr/head/UnderpostScripts.js +1 -1
- package/src/client/ssr/mailer/DefaultRecoverEmail.js +1 -1
- package/src/client/ssr/mailer/DefaultVerifyEmail.js +1 -1
- package/src/client/ssr/views/Cyberia404.js +7 -5
- package/src/client/ssr/views/CyberiaServerMetrics.js +1 -1
- package/src/client/ssr/views/Maintenance.js +1 -1
- package/src/client/ssr/views/NoNetworkConnection.js +1 -1
- package/src/client/ssr/views/Test.js +1 -1
- package/src/client/sw/core.sw.js +20 -14
- package/src/client-builder/client-build-docs.js +61 -46
- package/src/client-builder/client-build-live.js +2 -2
- package/src/client-builder/client-build.js +58 -44
- package/src/client-builder/client-dev-server.js +3 -3
- package/src/client-builder/client-icons.js +2 -2
- package/src/client-builder/ssr.js +3 -3
- package/src/client.build.js +3 -6
- package/src/client.dev.js +3 -6
- package/src/db/DataBaseProvider.js +186 -3
- package/src/db/mariadb/MariaDB.js +3 -2
- package/src/db/mongo/MongoBootstrap.js +273 -101
- package/src/db/mongo/MongooseDB.js +11 -8
- package/src/{server/valkey.js → db/valkey/Valkey.js} +5 -4
- package/src/grpc/cyberia/grpc-server.js +1 -1
- package/src/index.js +103 -23
- package/src/mailer/EmailRender.js +2 -2
- package/src/mailer/MailerInterceptor.js +87 -0
- package/src/mailer/MailerProvider.js +50 -6
- package/src/projects/cyberia/atlas-sprite-sheet-generator.js +1 -1
- package/src/projects/cyberia/besu-genesis-generator.js +3 -3
- package/src/projects/cyberia/catalog-cyberia.js +54 -6
- package/src/projects/cyberia/gemini-client.js +1 -1
- package/src/projects/cyberia/generate-saga.js +15 -24
- package/src/projects/cyberia/hot-reload-trigger.js +1 -1
- package/src/projects/cyberia/instance-data.js +22 -3
- package/src/projects/cyberia/ipfs-client.js +4 -4
- package/src/projects/cyberia/map-preview-generator.js +1 -1
- package/src/projects/cyberia/object-layer.js +12 -22
- package/src/projects/cyberia/semantic-layer-generator.js +1 -1
- package/src/projects/underpost/catalog-underpost.js +13 -2
- package/src/proxy.js +4 -7
- package/src/runtime/cyberia-client/Dockerfile +9 -4
- package/src/runtime/cyberia-client/Dockerfile.dev +8 -2
- package/src/runtime/cyberia-server/Dockerfile +9 -4
- package/src/runtime/cyberia-server/Dockerfile.dev +8 -2
- package/src/runtime/engine-cyberia/Dockerfile +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.dev +25 -9
- package/src/runtime/engine-cyberia/Dockerfile.test +4 -4
- package/src/runtime/engine-cyberia/compose.env +16 -0
- package/src/runtime/engine-cyberia/docker-compose.yml +31 -37
- package/src/runtime/express/Express.js +32 -27
- package/src/runtime/lampp/Lampp.js +22 -70
- package/src/runtime/nginx/Nginx.js +1 -1
- package/src/runtime/wp/Wp.js +16 -48
- package/src/server/{catalog.js → build/catalog.js} +15 -5
- package/src/server/build/coverage.js +117 -0
- package/src/server/build/execution.js +402 -0
- package/src/server/build/package.js +465 -0
- package/src/server/build/testing.js +528 -0
- package/src/server/{dns.js → network/dns.js} +241 -14
- package/src/server/network/forward-proxy.js +541 -0
- package/src/server/{middlewares.js → network/middlewares.js} +59 -4
- package/src/server/network/node-capability.js +98 -0
- package/src/server/{peer.js → network/peer.js} +3 -3
- package/src/server/{proxy.js → network/proxy.js} +7 -13
- package/src/server/network/router.js +356 -0
- package/src/server/{tls.js → network/tls.js} +2 -2
- package/src/server/network/underpost-compression.js +186 -0
- package/src/server/{underpost-gateway.js → network/underpost-gateway.js} +26 -16
- package/src/server/{underpost-ingress.js → network/underpost-ingress.js} +19 -3
- package/src/server/{cri.js → ops/cri.js} +2 -2
- package/src/server/ops/cron.js +949 -0
- package/src/server/ops/event-notification.js +284 -0
- package/src/server/{logger.js → ops/logger.js} +108 -23
- package/src/server/ops/monitoring.js +1724 -0
- package/src/server/ops/systemd.js +259 -0
- package/src/server/{conf.js → runtime/conf.js} +521 -520
- package/src/server/runtime/config-scope.js +215 -0
- package/src/server/runtime/environment.js +149 -0
- package/src/server/{process.js → runtime/process.js} +153 -13
- package/src/server/{runtime-status.js → runtime/runtime-status.js} +155 -16
- package/src/server/{runtime.js → runtime/runtime.js} +12 -8
- package/src/server/{start.js → runtime/start.js} +128 -39
- package/src/server/{auth.js → security/auth.js} +7 -8
- package/src/server/security/container-storage.js +382 -0
- package/src/server/{crypto.js → security/crypto.js} +1 -1
- package/src/server/security/selinux.js +185 -0
- package/src/server/{backup.js → storage/backup.js} +17 -8
- package/src/server/{data-query.js → storage/data-query.js} +1 -1
- package/src/server/{downloader.js → storage/downloader.js} +2 -2
- package/src/server/storage/repository.js +68 -0
- package/src/server.js +4 -7
- package/src/ws/IoInterface.js +1 -1
- package/src/ws/IoServer.js +1 -1
- package/src/ws/core/core.ws.connection.js +1 -1
- package/src/ws/core/core.ws.emit.js +1 -1
- package/src/ws/core/core.ws.server.js +1 -1
- package/src/ws/default/default.ws.connection.js +1 -1
- package/src/ws/default/default.ws.emit.js +1 -1
- package/src/ws/default/default.ws.server.js +1 -1
- package/test/e2e/event-e2e-public-ingress-down.js +45 -0
- package/test/e2e/event-e2e-wireguard-server-down.js +38 -0
- package/test/e2e/event-e2e-wireguard-spoke-down.js +40 -0
- package/test/{api.test.js → integration/app/api.test.js} +33 -14
- package/test/integration/app/cyberia/cyberia-cli-plain-reads.test.js +30 -0
- package/test/{cyberia-instance-conf-defaults.test.js → integration/app/cyberia/cyberia-instance-conf-defaults.test.js} +2 -1
- package/test/integration/app/cyberia/cyberia-load.test.js +467 -0
- package/test/integration/app/cyberia/fallback-world-capture.test.js +253 -0
- package/test/integration/app/cyberia/object-layer-item-id.test.js +327 -0
- package/test/{shape-generator.test.js → integration/app/cyberia/shape-generator.test.js} +1 -1
- package/test/integration/infra/1-security/config-scope.test.js +305 -0
- package/test/integration/infra/1-security/container-storage.test.js +356 -0
- package/test/integration/infra/1-security/in-pod-cli-surface.test.js +86 -0
- package/test/integration/infra/1-security/secret-onboarding.test.js +930 -0
- package/test/integration/infra/1-security/selinux.test.js +69 -0
- package/test/{sops-secret-store.test.js → integration/infra/1-security/sops-secret-store.test.js} +415 -61
- package/test/integration/infra/1-security/systemd-service.test.js +70 -0
- package/test/integration/infra/1-security/underpost-config-secret.test.js +367 -0
- package/test/integration/infra/2-network/dns-firewall.test.js +566 -0
- package/test/integration/infra/2-network/node-capability.test.js +182 -0
- package/test/integration/infra/2-network/wireguard-cli.test.js +1163 -0
- package/test/integration/infra/2-network/wireguard-edge.test.js +1731 -0
- package/test/{cluster-instances.test.js → integration/infra/3-cluster/cluster-instances.test.js} +11 -15
- package/test/{deploy-node-placement.test.js → integration/infra/3-cluster/deploy-node-placement.test.js} +3 -3
- package/test/integration/infra/3-cluster/docker-compose-stack.test.js +313 -0
- package/test/integration/infra/4-ingress/deploy-routes.test.js +379 -0
- package/test/integration/infra/4-ingress/gateway-static-assets.test.js +453 -0
- package/test/{instance-traffic-plan.test.js → integration/infra/4-ingress/instance-traffic-plan.test.js} +10 -6
- package/test/{underpost-gateway.test.js → integration/infra/4-ingress/underpost-gateway.test.js} +47 -6
- package/test/{underpost-ingress.test.js → integration/infra/4-ingress/underpost-ingress.test.js} +56 -4
- package/test/integration/infra/5-observability/cron-jobs.test.js +652 -0
- package/test/{deploy-monitor.test.js → integration/infra/5-observability/deploy-monitor.test.js} +29 -31
- package/test/integration/infra/5-observability/event-notification.test.js +197 -0
- package/test/integration/infra/5-observability/event-remediation.test.js +502 -0
- package/test/integration/infra/5-observability/event-targets.test.js +1174 -0
- package/test/integration/infra/5-observability/monitoring-stack.test.js +902 -0
- package/test/support/shell-harness.js +73 -0
- package/test/unit/build-template.test.js +97 -0
- package/test/unit/build-workflow-offline.test.js +132 -0
- package/test/unit/catalog.test.js +71 -0
- package/test/unit/client-build-docs.test.js +334 -0
- package/test/unit/conf-loading.test.js +303 -0
- package/test/unit/conf-resolution.test.js +979 -0
- package/test/unit/coverage-artifact.test.js +130 -0
- package/test/{crypto.test.js → unit/crypto.test.js} +1 -1
- package/test/unit/deploy-env-resolution.test.js +38 -0
- package/test/unit/deploy-log-table.test.js +447 -0
- package/test/unit/execution-profiles.test.js +219 -0
- package/test/unit/fleet-sync-source.test.js +149 -0
- package/test/unit/logger-redaction.test.js +112 -0
- package/test/unit/package.test.js +403 -0
- package/test/unit/prepare-host.test.js +299 -0
- package/test/unit/process-environment.test.js +18 -0
- package/test/unit/propagation-message.test.js +78 -0
- package/test/unit/redeploy-plan.test.js +24 -0
- package/test/unit/release-bump.test.js +474 -0
- package/test/unit/ssh-output-redaction.test.js +28 -0
- package/test/unit/start-options.test.js +46 -0
- package/test/unit/test-tiers.test.js +193 -0
- package/vitest.config.js +58 -0
- package/.nycrc +0 -9
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +0 -48
- package/manifests/mongodb/pv-pvc.yaml +0 -59
- package/scripts/link-local-underpost-cli.sh +0 -6
- package/src/api/user/user.build.js +0 -16
- package/src/cli/env.js +0 -177
- package/src/client/components/core/Blockchain.js +0 -41
- package/src/client/components/core/Blog.js +0 -9
- package/src/client/components/core/KeyboardAvoidance.js +0 -145
- package/src/client/public/default/assets/background/dark.jpg +0 -0
- package/src/client/public/default/assets/background/white0-min.jpg +0 -0
- package/src/client/public/default/assets/background/white0.jpg +0 -0
- package/src/client/public/doc/favicon.ico +0 -0
- package/src/client/public/doc/sitemap +0 -148
- package/src/server/cron.js +0 -476
package/src/cli/index.js
CHANGED
|
@@ -2,8 +2,11 @@ import dotenv from 'dotenv';
|
|
|
2
2
|
import fs from 'fs-extra';
|
|
3
3
|
|
|
4
4
|
import { Command } from 'commander';
|
|
5
|
-
import { getNpmRootPath, getUnderpostRootPath
|
|
5
|
+
import { deployEnvFactory, getNpmRootPath, getUnderpostRootPath } from '../server/runtime/environment.js';
|
|
6
6
|
import { commitData } from '../client/components/core/CommonJs.js';
|
|
7
|
+
import { registerDomainCommand } from './domains.js';
|
|
8
|
+
import { TEST_TIERS, testSuiteNames } from '../server/build/testing.js';
|
|
9
|
+
import { EXECUTION_PROFILES, profileFromOptionsFactory, setExecutionProfile } from '../server/build/execution.js';
|
|
7
10
|
|
|
8
11
|
import Underpost from '../index.js';
|
|
9
12
|
|
|
@@ -16,19 +19,38 @@ const program = new Command();
|
|
|
16
19
|
|
|
17
20
|
program.name('underpost').description(`underpost ci/cd cli ${Underpost.version}`).version(Underpost.version);
|
|
18
21
|
|
|
22
|
+
// One gate for every command. The profile decides which classes of side effect this run
|
|
23
|
+
// may cause; `src/server/runtime/process.js` enforces it under all 1400+ call sites, so a
|
|
24
|
+
// command never has to be taught that its environment is unreachable.
|
|
25
|
+
program.option(
|
|
26
|
+
'--profile <profile>',
|
|
27
|
+
`Execution profile. One of: ${Object.keys(EXECUTION_PROFILES).join(', ')}.\n` +
|
|
28
|
+
Object.values(EXECUTION_PROFILES)
|
|
29
|
+
.map((profile) => ` ${profile.name.padEnd(16)} ${profile.description}`)
|
|
30
|
+
.join('\n'),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Resolved before any action runs, from the root flag, the subcommand's own options, or a
|
|
34
|
+
// legacy bypass flag standing in for a profile. Writing it to the environment is what
|
|
35
|
+
// carries it into nested `underpost` invocations.
|
|
36
|
+
program.hook('preAction', (command, actionCommand) => {
|
|
37
|
+
const profile = profileFromOptionsFactory({ ...command.opts(), ...actionCommand.opts() });
|
|
38
|
+
if (profile) setExecutionProfile(profile);
|
|
39
|
+
});
|
|
40
|
+
|
|
19
41
|
program
|
|
20
42
|
.command('new')
|
|
21
43
|
.argument('[app-name]', 'The name of the new project.')
|
|
22
44
|
.option('--deploy-id <deploy-id>', 'Create deploy ID conf env files')
|
|
23
45
|
.option('--sub-conf <sub-conf>', 'Create sub conf env files')
|
|
24
|
-
.option('--cluster', '
|
|
46
|
+
.option('--cluster', 'Initialize the base cluster deploy folder engine-private/deploy from ./conf.js')
|
|
25
47
|
.option('--build-repos', 'Create deploy ID repositories')
|
|
26
48
|
.option('--build', 'Build the deployment to pwa-microservices-template (requires --deploy-id)')
|
|
27
49
|
.option('--clean-template', 'Clean the build directory (pwa-microservices-template)')
|
|
28
50
|
.option('--sync-conf', 'Sync configuration to private repositories (requires --deploy-id)')
|
|
29
51
|
.option(
|
|
30
52
|
'--sync-start',
|
|
31
|
-
"Sync start scripts in deploy ID package.json with root package.json (use 'dd' as --deploy-id to sync all dd.
|
|
53
|
+
"Sync start scripts in deploy ID package.json with root package.json (use 'dd' as --deploy-id to sync all dd.routes)",
|
|
32
54
|
)
|
|
33
55
|
.option('--purge', 'Remove deploy ID conf and all related repositories (requires --deploy-id)')
|
|
34
56
|
.option('--dev', 'Sets the development cli context')
|
|
@@ -51,8 +73,14 @@ program
|
|
|
51
73
|
.option('--merge-zip <build-prefix>', 'Merge split ZIP parts back into a single ZIP file for the given build prefix')
|
|
52
74
|
.option('--lite-build', 'Skip full build (default is full build)')
|
|
53
75
|
.option('--icons-build', 'Build icons')
|
|
76
|
+
.option('--ssr', 'Rebuild only SSR views defined in conf.ssr.json, leaving client assets untouched')
|
|
77
|
+
.option(
|
|
78
|
+
'--env <env>',
|
|
79
|
+
'Target environment for the build (e.g. "production", "development"). Falls back to --dev, then NODE_ENV.',
|
|
80
|
+
)
|
|
81
|
+
.option('--dev', 'Sets the development cli context (shorthand for --env development).')
|
|
54
82
|
.description('Builds client assets, single replicas, and/or syncs environment ports.')
|
|
55
|
-
.action(Underpost.
|
|
83
|
+
.action(Underpost.client.callback);
|
|
56
84
|
|
|
57
85
|
program
|
|
58
86
|
.command('start')
|
|
@@ -64,7 +92,11 @@ program
|
|
|
64
92
|
.option('--run', 'Starts application servers and monitors their health.')
|
|
65
93
|
.option('--build', 'Triggers the client-side application build process.')
|
|
66
94
|
.option('--underpost-quickly-install', 'Uses Underpost Quickly Install for dependency installation.')
|
|
67
|
-
.option('--skip-pull-base', 'Skips cloning
|
|
95
|
+
.option('--skip-pull-repo-base', 'Skips cloning the engine source repository, uses current workspace code directly.')
|
|
96
|
+
.option(
|
|
97
|
+
'--skip-pull-private-repo',
|
|
98
|
+
'Skips cloning the private configuration repository, uses the engine-private already in the workspace.',
|
|
99
|
+
)
|
|
68
100
|
.option('--skip-full-build', 'Skips the full client bundle build during deployment.')
|
|
69
101
|
.option(
|
|
70
102
|
'--pull-bundle',
|
|
@@ -115,7 +147,7 @@ program
|
|
|
115
147
|
.option('--hashes <hashes>', 'Comma-separated list of specific file hashes of commits.')
|
|
116
148
|
.option('--extension <extension>', 'specific file extensions of commits.')
|
|
117
149
|
.option('--changelog', 'Print the plain changelog of the last N commits (see --from-n-commit, default 1).')
|
|
118
|
-
.option('--changelog-build', 'Builds a CHANGELOG.md
|
|
150
|
+
.option('--changelog-build', 'Builds a CHANGELOG.md from the latest five versions')
|
|
119
151
|
.option('--changelog-min-version <version>', 'Sets the minimum version limit for --changelog-build (default: 2.85.0)')
|
|
120
152
|
.option(
|
|
121
153
|
'--changelog-no-hash',
|
|
@@ -126,6 +158,12 @@ program
|
|
|
126
158
|
'Print the sanitized, commit-ready changelog message of the last N commits (see --from-n-commit, default 1). Empty when there are no tagged entries.',
|
|
127
159
|
)
|
|
128
160
|
.option('--from-n-commit <n>', 'Number of latest commits to include in --changelog/--changelog-msg (default: 1).')
|
|
161
|
+
.option(
|
|
162
|
+
'--propagate-msg',
|
|
163
|
+
'Prints the changelog payload carried by the propagation chain, read from the PROPAGATED_MESSAGE ' +
|
|
164
|
+
'environment variable and stripped of the commit subject wrapper. Falls back to --changelog-msg ' +
|
|
165
|
+
'over the last N commits (see --from-n-commit) when nothing was propagated.',
|
|
166
|
+
)
|
|
129
167
|
.option('--unpush', 'With --log, automatically sets range to unpushed commits ahead of remote.')
|
|
130
168
|
.option('-b', 'Shows the current Git branch name.')
|
|
131
169
|
.option('-p [branch]', 'Shows the reflog for the specified branch.')
|
|
@@ -143,7 +181,7 @@ program
|
|
|
143
181
|
'--switch-repo <url>',
|
|
144
182
|
'Switches the git remote (origin) to <url> and force-pulls the target branch, overwriting the current working tree (discards local commits and tracked changes). Accepts a full URL or "owner/repo".',
|
|
145
183
|
)
|
|
146
|
-
.option('--target-branch <branch>', 'Target branch for --switch-repo (default:
|
|
184
|
+
.option('--target-branch <branch>', 'Target branch for --switch-repo (default: remote default branch).')
|
|
147
185
|
.description('Manages commits to a GitHub repository, supporting various commit types and options.')
|
|
148
186
|
.action(Underpost.repo.commit);
|
|
149
187
|
|
|
@@ -156,24 +194,6 @@ program
|
|
|
156
194
|
.description('Pushes committed changes from a local repository to a remote GitHub repository.')
|
|
157
195
|
.action(Underpost.repo.push);
|
|
158
196
|
|
|
159
|
-
program
|
|
160
|
-
.command('env')
|
|
161
|
-
.argument(
|
|
162
|
-
'[deploy-id]',
|
|
163
|
-
`The deployment configuration ID. Use 'clean' to restore default environment settings. Use 'root' to load underpost root env. Use 'current' to get plain current deploy Id.`,
|
|
164
|
-
)
|
|
165
|
-
.argument('[env]', 'Optional: The environment to set (e.g., "production", "development"). Defaults to "production".')
|
|
166
|
-
.argument('[subConf]', 'Optional: The sub configuration to set.')
|
|
167
|
-
.description('Sets environment variables and configurations related to a specific deployment ID.')
|
|
168
|
-
.action((deployId, env, subConf) => {
|
|
169
|
-
if (deployId === 'root') {
|
|
170
|
-
const underpostRootDeployId = Underpost.env.get('DEPLOY_ID');
|
|
171
|
-
if (underpostRootDeployId) deployId = underpostRootDeployId;
|
|
172
|
-
}
|
|
173
|
-
if (env) process.env.NODE_ENV = env;
|
|
174
|
-
loadConf(deployId, subConf);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
197
|
program
|
|
178
198
|
.command('static')
|
|
179
199
|
.option('--page <ssr-component-path>', 'Build custom static pages.')
|
|
@@ -221,19 +241,6 @@ program
|
|
|
221
241
|
.description(`Manages static build of page, bundles, and documentation with comprehensive customization options.`)
|
|
222
242
|
.action(Underpost.static.callback);
|
|
223
243
|
|
|
224
|
-
program
|
|
225
|
-
.command('config')
|
|
226
|
-
.argument('operator', `The configuration operation to perform. Options: ${Object.keys(Underpost.env).join(', ')}.`)
|
|
227
|
-
.argument('[key]', 'Optional: The specific configuration key to manage.')
|
|
228
|
-
.argument('[value]', 'Optional: The value to set for the configuration key.')
|
|
229
|
-
.option('--plain', 'Prints the configuration value in plain text.')
|
|
230
|
-
.option('--filter <keyword>', 'Filters the list by matching key or value (only for list operation).')
|
|
231
|
-
.option('--deploy-id <deploy-id>', 'Sets the deployment configuration ID for the operation context.')
|
|
232
|
-
.option('--build', 'Sets the build context for the operation.')
|
|
233
|
-
.option('--copy', 'Copies the configuration value to the clipboard (only for get operation).')
|
|
234
|
-
.description(`Manages Underpost configurations using various operators.`)
|
|
235
|
-
.action((...args) => Underpost.env[args[0]](args[1], args[2], args[3]));
|
|
236
|
-
|
|
237
244
|
program
|
|
238
245
|
.command('root')
|
|
239
246
|
.description('Displays the root path of the npm installation.')
|
|
@@ -254,6 +261,15 @@ program
|
|
|
254
261
|
.option('--ban-egress-clear', 'Clears all banned egress IP addresses.')
|
|
255
262
|
.option('--ban-both-add', 'Adds IP addresses to both banned ingress and egress lists.')
|
|
256
263
|
.option('--ban-both-remove', 'Removes IP addresses from both banned ingress and egress lists.')
|
|
264
|
+
.option('--block-all-egress', 'Blocks all outbound traffic from this host (keeps established/related connections).')
|
|
265
|
+
.option('--unblock-all-egress', 'Unblocks all outbound traffic and restores default ACCEPT policy.')
|
|
266
|
+
.option('--block-all-ingress', 'Blocks all new inbound traffic to this host (keeps established/related connections).')
|
|
267
|
+
.option('--unblock-all-ingress', 'Unblocks all inbound traffic and restores default ACCEPT policy.')
|
|
268
|
+
.option(
|
|
269
|
+
'--block-ingress-port <ports>',
|
|
270
|
+
'Blocks new inbound traffic on comma-separated TCP ports, leaving the management path reachable.',
|
|
271
|
+
)
|
|
272
|
+
.option('--unblock-ingress-port <ports>', 'Withdraws the port rules --block-ingress-port installed.')
|
|
257
273
|
.option('--mac', 'Prints the MAC address of the main network interface.')
|
|
258
274
|
.description('Displays the current public machine IP addresses.')
|
|
259
275
|
.action(Underpost.dns.ipDispatcher);
|
|
@@ -291,8 +307,9 @@ program
|
|
|
291
307
|
'Exposes enabled ready services (e.g. MongoDB 4.4, Valkey) to the host/public network via their NodePort Service manifest.',
|
|
292
308
|
)
|
|
293
309
|
.option(
|
|
294
|
-
'--node-
|
|
295
|
-
'Pins the just-deployed
|
|
310
|
+
'--node-name <k8s-node-name>',
|
|
311
|
+
'Pins the just-deployed workload (MongoDB 4.4 / Valkey StatefulSets, the observability Deployments) ' +
|
|
312
|
+
'to the given Kubernetes node once it is ready, via a kubernetes.io/hostname nodeSelector.',
|
|
296
313
|
)
|
|
297
314
|
.option('--cert-manager', "Initializes the cluster with a Let's Encrypt production ClusterIssuer.")
|
|
298
315
|
.option('--dedicated-gpu', 'Initializes the cluster with dedicated GPU base resources and environment settings.')
|
|
@@ -309,10 +326,15 @@ program
|
|
|
309
326
|
'--control-plane-endpoint <endpoint>',
|
|
310
327
|
'Sets custom control plane endpoint for kubeadm cluster initialization (defaults to "localhost:6443").',
|
|
311
328
|
)
|
|
312
|
-
.option(
|
|
329
|
+
.option(
|
|
330
|
+
'--grafana',
|
|
331
|
+
'Initializes the cluster with the observability stack (Prometheus, Alertmanager, Blackbox Exporter, Grafana). ' +
|
|
332
|
+
'Equivalent to --prom; both converge the one stack.',
|
|
333
|
+
)
|
|
313
334
|
.option(
|
|
314
335
|
'--prom [hosts]',
|
|
315
|
-
'Initializes the cluster with
|
|
336
|
+
'Initializes the cluster with the observability stack. Scrape targets are derived from each deploy conf.server.json; ' +
|
|
337
|
+
'the optional comma-separated hosts are scraped at /metrics in addition to them.',
|
|
316
338
|
)
|
|
317
339
|
.option('--dev', 'Initializes a development-specific cluster configuration.')
|
|
318
340
|
.option('--list-pods', 'Displays detailed information about all pods.')
|
|
@@ -421,69 +443,41 @@ program
|
|
|
421
443
|
.description('Manages application deployments, defaulting to deploying development pods.')
|
|
422
444
|
.action(Underpost.deploy.callback);
|
|
423
445
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
'
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
'
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
)
|
|
459
|
-
.option(
|
|
460
|
-
'--keep-recipients <age-public-keys>',
|
|
461
|
-
'Comma-separated recipients to retain while --prune-recipients revokes the rest (e.g. the CI/CD key).',
|
|
462
|
-
)
|
|
463
|
-
.option(
|
|
464
|
-
'--purge <secret-name>',
|
|
465
|
-
'Emergency removal: deletes the live Kubernetes Secret and takes its encrypted manifest out of the store.',
|
|
466
|
-
)
|
|
467
|
-
.option(
|
|
468
|
-
'--force',
|
|
469
|
-
'Confirms the irreversible variant: deletes the manifest instead of archiving it (--purge), ' +
|
|
470
|
-
'revokes recipients (--rotate --prune-recipients), or replaces an existing manifest (--encrypt).',
|
|
471
|
-
)
|
|
472
|
-
.option('--dry-run', 'Reports what --apply, --rotate, or --purge would do without changing anything.')
|
|
473
|
-
.description(`Manages secrets for various platforms.`)
|
|
474
|
-
.action((platform, options) => {
|
|
475
|
-
// Host tooling install is platform-independent, so it resolves before any platform lookup.
|
|
476
|
-
if (options.installTools) return Underpost.secret.sops.installTooling();
|
|
477
|
-
if (options.globalClean) return Underpost.secret.globalSecretClean();
|
|
478
|
-
if (options.rotate) return Underpost.secret[platform].rotate(options.recipient, options);
|
|
479
|
-
if (options.purge) return Underpost.secret[platform].purge(options.purge, options);
|
|
480
|
-
if (options.encrypt) return Underpost.secret[platform].encrypt(options.encrypt, options.namespace, options);
|
|
481
|
-
if (options.apply) return Underpost.secret[platform].apply(options.namespace, options);
|
|
482
|
-
if (options.createFromFile) return Underpost.secret[platform].createFromEnvFile(options.createFromFile);
|
|
483
|
-
if (options.createFromEnv) return Underpost.secret[platform].createFromContainerEnv();
|
|
484
|
-
if (options.list) return Underpost.secret[platform].list();
|
|
485
|
-
if (options.init) return Underpost.secret[platform].init();
|
|
486
|
-
});
|
|
446
|
+
// The four domains are registered from one factory, so their action list and their option list
|
|
447
|
+
// exist exactly once. Adding a verb or a flag here adds it to all four; there is no place to add
|
|
448
|
+
// one to a single domain.
|
|
449
|
+
for (const domain of [
|
|
450
|
+
{
|
|
451
|
+
name: 'secret',
|
|
452
|
+
description: 'Workload secret store: SOPS/Age encrypted credentials projected as Kubernetes Secrets.',
|
|
453
|
+
api: () => Underpost.secret,
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
// The only store-owning domain: `host get|set|delete|list` reads and writes the host
|
|
457
|
+
// configuration store this domain already owns end to end, so there is no second command
|
|
458
|
+
// addressing the same file. Container status is not here — it is `underpost state`.
|
|
459
|
+
name: 'host',
|
|
460
|
+
description: 'Host configuration: the node-level operational environment shared by the cluster.',
|
|
461
|
+
api: () => Underpost.host,
|
|
462
|
+
store: true,
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
name: 'app',
|
|
466
|
+
description: "Application environment: one deployment's runtime configuration.",
|
|
467
|
+
api: () => Underpost.app,
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
// The runtime monitoring / telemetry layer. Unlike the other three it has no durable
|
|
471
|
+
// source — an observation is only true of a running container — so its `load` collects from
|
|
472
|
+
// the live workload and its `publish` exports off-cluster. Its store is the container state
|
|
473
|
+
// store, never the host domain's: different owner, different lifetime.
|
|
474
|
+
name: 'state',
|
|
475
|
+
description: 'Runtime state: live container execution state, health and metrics, exported off-cluster.',
|
|
476
|
+
api: () => Underpost.state,
|
|
477
|
+
store: true,
|
|
478
|
+
},
|
|
479
|
+
])
|
|
480
|
+
registerDomainCommand(program, domain);
|
|
487
481
|
|
|
488
482
|
program
|
|
489
483
|
.command('image')
|
|
@@ -542,7 +536,6 @@ program
|
|
|
542
536
|
)
|
|
543
537
|
.option('--all-pods', 'Target all matching pods instead of just the first one.')
|
|
544
538
|
.option('--primary-pod', 'Automatically detect and use MongoDB primary pod (MongoDB only).')
|
|
545
|
-
.option('--primary-pod-ensure <pod-name>', 'Ensure setup of MongoDB replica set primary pod before operations.')
|
|
546
539
|
.option('--stats', 'Display database statistics (collection/table names with document/row counts).')
|
|
547
540
|
.option('--collections <collections>', 'Comma-separated list of database collections to operate on.')
|
|
548
541
|
.option('--out-path <out-path>', 'Specifies a custom output path for backups.')
|
|
@@ -592,19 +585,27 @@ program
|
|
|
592
585
|
|
|
593
586
|
program
|
|
594
587
|
.command('cron')
|
|
595
|
-
.argument(
|
|
588
|
+
.argument(
|
|
589
|
+
'[deploy-list]',
|
|
590
|
+
'A comma-separated list of deployment IDs (e.g., "default-a,default-b"). In manifest modes its first entry is the manifest owner deploy-id.',
|
|
591
|
+
)
|
|
596
592
|
.argument(
|
|
597
593
|
'[job-list]',
|
|
598
|
-
`A comma-separated list of job IDs. Options: ${Underpost.cron.getJobsIDs()}. Defaults to all available jobs.`,
|
|
594
|
+
`A comma-separated list of job IDs. Options: ${Underpost.cron.getJobsIDs()}. Defaults to all available jobs, and restricts which jobs are generated in manifest modes.`,
|
|
599
595
|
)
|
|
600
596
|
.option('--generate-k8s-cronjobs', 'Generates Kubernetes CronJob YAML manifests from cron configuration.')
|
|
601
|
-
.option('--apply', '
|
|
597
|
+
.option('--apply', 'Generates and applies K8s CronJob manifests to the cluster via kubectl (never runs jobs).')
|
|
602
598
|
.option(
|
|
603
|
-
'--setup-start
|
|
604
|
-
'Updates deploy-
|
|
599
|
+
'--setup-start',
|
|
600
|
+
'Updates deploy-list package.json start script and generates+applies its K8s CronJob manifests.',
|
|
605
601
|
)
|
|
606
602
|
.option('--namespace <namespace>', 'Kubernetes namespace for the CronJob resources (default: "default").')
|
|
607
603
|
.option('--image <image>', 'Custom container image for the CronJob pods.')
|
|
604
|
+
.option(
|
|
605
|
+
'--node-name <node-name>',
|
|
606
|
+
'Pins the CronJob pods to this node via a kubernetes.io/hostname nodeSelector. ' +
|
|
607
|
+
'With --apply, defaults to this machine when the cluster knows it as a node, because the pods mount its checkout.',
|
|
608
|
+
)
|
|
608
609
|
.option('--git', 'Pass --git flag to cron job execution.')
|
|
609
610
|
.option('--cmd <cmd>', 'Optional pre-script commands to run before cron execution.')
|
|
610
611
|
.option('--dev', 'Use local ./ base path instead of global underpost installation.')
|
|
@@ -614,7 +615,7 @@ program
|
|
|
614
615
|
.option('--dry-run', 'Preview cron jobs without executing them.')
|
|
615
616
|
.option(
|
|
616
617
|
'--create-job-now',
|
|
617
|
-
'
|
|
618
|
+
'Creates a Job from each CronJob on the cluster now (implies manifest mode; combine with --apply to publish first).',
|
|
618
619
|
)
|
|
619
620
|
.description('Manages cron jobs: execute jobs directly or generate and apply K8s CronJob manifests.')
|
|
620
621
|
.action(Underpost.cron.callback);
|
|
@@ -633,21 +634,14 @@ program
|
|
|
633
634
|
.description('Manages file storage, defaulting to file upload operations.')
|
|
634
635
|
.action(Underpost.fs.callback);
|
|
635
636
|
|
|
636
|
-
program
|
|
637
|
-
.command('test')
|
|
638
|
-
.argument('[deploy-list]', 'A comma-separated list of deployment IDs (e.g., "default-a,default-b").')
|
|
639
|
-
.description('Manages and runs tests, defaulting to the current Underpost default test suite.')
|
|
640
|
-
.option('--itc', 'Executes tests within the container execution context.')
|
|
641
|
-
.option('--sh', 'Copies the container entrypoint shell command to the clipboard.')
|
|
642
|
-
.option('--logs', 'Displays container logs for test debugging.')
|
|
643
|
-
.option('--pod-name <pod-name>', 'Optional: Specifies the pod name for test execution.')
|
|
644
|
-
.option('--pod-status <pod-status>', 'Optional: Filters tests by pod status.')
|
|
645
|
-
.option('--kind-type <kind-type>', 'Optional: Specifies the Kind cluster type for tests.')
|
|
646
|
-
.action(Underpost.test.callback);
|
|
647
|
-
|
|
648
637
|
program
|
|
649
638
|
.command('monitor')
|
|
650
|
-
.argument(
|
|
639
|
+
.argument(
|
|
640
|
+
'[deploy-id]',
|
|
641
|
+
'The deployment configuration ID to monitor. With the observability flags it selects which deploys are scraped; ' +
|
|
642
|
+
'"dd" covers every deploy in dd.routes.',
|
|
643
|
+
'dd',
|
|
644
|
+
)
|
|
651
645
|
.argument(
|
|
652
646
|
'[env]',
|
|
653
647
|
'Optional: The environment to monitor (e.g., "development", "production"). Defaults to "development".',
|
|
@@ -667,12 +661,104 @@ program
|
|
|
667
661
|
.option('--versions <deployment-versions>', 'Specifies the deployment versions to monitor. eg. "blue,green", "green"')
|
|
668
662
|
.option('--ready-deployment', 'Run in ready deployment monitor mode.')
|
|
669
663
|
.option('--promote', 'Promotes the deployment after monitoring.')
|
|
670
|
-
.
|
|
664
|
+
.option(
|
|
665
|
+
'--observability',
|
|
666
|
+
'Deploys or converges the cluster observability stack (Prometheus, Alertmanager, Blackbox Exporter, Grafana), ' +
|
|
667
|
+
'ensuring the Gateway API metrics source and local-path storage provisioner are ready.',
|
|
668
|
+
)
|
|
669
|
+
.option(
|
|
670
|
+
'--sync-prom',
|
|
671
|
+
'Regenerates the scrape configuration, alert rules and Alertmanager route from the live deploy configuration ' +
|
|
672
|
+
'and event registry, applies Grafana admin credentials, then reloads or rolls only the affected component.',
|
|
673
|
+
)
|
|
674
|
+
.option('--events <event-ids>', 'Comma-separated event ids to provision; empty provisions every registered event.')
|
|
675
|
+
.option(
|
|
676
|
+
'--webhook-url <url>',
|
|
677
|
+
'URL Alertmanager delivers events to (defaults to the node address of `event --serve`).',
|
|
678
|
+
)
|
|
679
|
+
.option('--extra-targets <targets>', 'Comma-separated additional "host:port" scrape targets.')
|
|
680
|
+
.option(
|
|
681
|
+
'--metrics-server',
|
|
682
|
+
'Installs the Kubernetes metrics-server (kubectl top / HPA resource API). Skipped on K3s, which bundles its own, unless --force.',
|
|
683
|
+
)
|
|
684
|
+
.option(
|
|
685
|
+
'--cockpit',
|
|
686
|
+
'Installs and enables the Cockpit KVM dashboard on this host (cockpit, cockpit-machines, libvirt) and opens its firewall service.',
|
|
687
|
+
)
|
|
688
|
+
.option('--cockpit-stop', 'Stops and disables the Cockpit KVM dashboard and closes its firewall service.')
|
|
689
|
+
.option(
|
|
690
|
+
'--grafana-host <host>',
|
|
691
|
+
'Publishes Grafana at https://<host>/grafana through the edge Gateway that already serves that hostname.',
|
|
692
|
+
)
|
|
693
|
+
.option('--node-port', "Publishes Grafana on the node's LAN address (port 32300).")
|
|
694
|
+
.option('--expose-grafana', 'Republishes Grafana with --grafana-host / --node-port without redeploying the stack.')
|
|
695
|
+
.option(
|
|
696
|
+
'--webhook-token',
|
|
697
|
+
'Prints the shared event webhook token, to persist as UNDERPOST_EVENT_TOKEN in the cron deploy env.',
|
|
698
|
+
)
|
|
699
|
+
.option(
|
|
700
|
+
'--node-name <k8s-node-name>',
|
|
701
|
+
'Pins every monitoring workload to this node; moving Grafana deletes and recreates its node-local data.',
|
|
702
|
+
)
|
|
703
|
+
.option('--kubeadm', 'Treats the cluster as kubeadm when resolving node and host addresses.')
|
|
704
|
+
.option('--kind', 'Treats the cluster as Kind (Docker nodes) when resolving node and host addresses.')
|
|
705
|
+
.option('--k3s', 'Treats the cluster as K3s when resolving node and host addresses.')
|
|
706
|
+
.option('--force', 'Confirms an install that would replace a bundled component (e.g. --metrics-server on K3s).')
|
|
707
|
+
.option('--dev', 'Sets the development cli context (scrapes over HTTP, defaults the cluster type to Kind).')
|
|
708
|
+
.description('Manages health server monitoring, the cluster observability stack, and host dashboards.')
|
|
671
709
|
.action(Underpost.monitor.callback);
|
|
672
710
|
|
|
711
|
+
program
|
|
712
|
+
.command('event')
|
|
713
|
+
.argument('[event-id]', `The operational event to dispatch. Options: ${Object.keys(Underpost.event.EVENTS)}.`)
|
|
714
|
+
.option(
|
|
715
|
+
'--deploy',
|
|
716
|
+
'Merges the event into the set already deployed in the cluster and republishes the monitoring configuration.',
|
|
717
|
+
)
|
|
718
|
+
.option('--undeploy', 'Removes the event from the deployed set and republishes without it.')
|
|
719
|
+
.option(
|
|
720
|
+
'--suspend-events <state-file>',
|
|
721
|
+
'Saves the exact deployed event set and temporarily republishes observability without event probes or alerts.',
|
|
722
|
+
)
|
|
723
|
+
.option(
|
|
724
|
+
'--resume-events <state-file>',
|
|
725
|
+
'Restores and resynchronizes the exact event set saved by --suspend-events, then removes the state file.',
|
|
726
|
+
)
|
|
727
|
+
.option('--serve', 'Runs the Alertmanager webhook receiver in the foreground (use --service to supervise it).')
|
|
728
|
+
.option(
|
|
729
|
+
'--service',
|
|
730
|
+
'Installs the receiver on a WireGuard control node as the underpost-event systemd unit. ' +
|
|
731
|
+
'It remains available while the tunnel is down.',
|
|
732
|
+
)
|
|
733
|
+
.option('--service-stop', 'Stops, disables and removes the underpost-event systemd unit.')
|
|
734
|
+
.option('--service-status', 'Reports whether the underpost-event unit is active and enabled.')
|
|
735
|
+
.option('--list', 'Lists the registered events with their resolved probe targets.')
|
|
736
|
+
.option('--port <port>', 'Listening port for --serve and the generated unit (default: 39099).')
|
|
737
|
+
.option('--cooldown-ms <ms>', 'Minimum interval between two dispatches of one event in --serve (default: 300000).')
|
|
738
|
+
.option(
|
|
739
|
+
'--spoke <spoke-id>',
|
|
740
|
+
'Spoke to remediate when dispatching wireguard-spoke-down by hand; a webhook takes it from the alert labels.',
|
|
741
|
+
)
|
|
742
|
+
.option(
|
|
743
|
+
'--nodes <node-names>',
|
|
744
|
+
'Comma-separated node documents to act on — hubs for wireguard-server-down, peers for wireguard-spoke-down. ' +
|
|
745
|
+
'Empty covers every registered hub, or every peer of this node hub.',
|
|
746
|
+
)
|
|
747
|
+
.option('--namespace <namespace>', 'Kubernetes namespace holding the observability stack. Defaults to "default".')
|
|
748
|
+
.option('--webhook-url <url>', 'URL Alertmanager delivers to, written into the generated route with --deploy.')
|
|
749
|
+
.option('--dev', 'Sets the development cli context.')
|
|
750
|
+
.option('--dry-run', 'Reports the remediation the event would run without executing it.')
|
|
751
|
+
.option('--no-notify', 'Skips the operational alert declared in engine-private/deploy/conf.event.json.')
|
|
752
|
+
.option(
|
|
753
|
+
'--e2e-test',
|
|
754
|
+
'Rehearses the event against the live edge: breaks the real subject, waits for the probe to fail, ' +
|
|
755
|
+
'runs the remediation, and verifies the notification was actually sent.',
|
|
756
|
+
)
|
|
757
|
+
.description('Dispatches operational events and provisions the monitoring rules that trigger them.')
|
|
758
|
+
.action(Underpost.event.callback);
|
|
759
|
+
|
|
673
760
|
program
|
|
674
761
|
.command('ssh')
|
|
675
|
-
.option('--deploy-id <deploy-id>', 'Sets deploy id context for ssh operations.')
|
|
676
762
|
.option('--generate', 'Generates new ssh credential and stores it in current private keys file storage.')
|
|
677
763
|
.option('--user <user>', 'Sets custom ssh user')
|
|
678
764
|
.option('--password <password>', 'Sets custom ssh password')
|
|
@@ -691,11 +777,162 @@ program
|
|
|
691
777
|
.option('--key-test', 'Tests the SSH key using ssh-keygen.')
|
|
692
778
|
.option('--stop', 'Stops the SSH service.')
|
|
693
779
|
.option('--status', 'Checks the status of the SSH service.')
|
|
694
|
-
.
|
|
695
|
-
|
|
696
|
-
|
|
780
|
+
.description(
|
|
781
|
+
'Manages cluster scoped SSH credentials and sessions for remote access to cluster nodes or services. ' +
|
|
782
|
+
'Users are registered in engine-private/deploy/conf.users.json and keys are stored in engine-private/deploy/users/<user>.',
|
|
783
|
+
)
|
|
697
784
|
.action(Underpost.ssh.callback);
|
|
698
785
|
|
|
786
|
+
// `underpost wireguard` and `underpost haproxy` are two entrypoints onto one
|
|
787
|
+
// subsystem: the L3 transport and the gateway in front of it are configured from
|
|
788
|
+
// the same deploy state, so they share a single option set and a single action
|
|
789
|
+
// rather than drifting into two half-overlapping command surfaces.
|
|
790
|
+
const edgeCommandFactory = (name, description) =>
|
|
791
|
+
program
|
|
792
|
+
.command(name)
|
|
793
|
+
.option(
|
|
794
|
+
'--deploy-id <deploy-id>',
|
|
795
|
+
'Deploy IDs whose conf.server.json/conf.instances.json define the routes. ' +
|
|
796
|
+
'Accepts one id or a comma-separated list; defaults to "dd", every deploy in dd.routes, ' +
|
|
797
|
+
'because the edge holds one pair of map files for the whole cluster.',
|
|
798
|
+
)
|
|
799
|
+
.option('--interface <name>', 'WireGuard interface name (default: "wg0").')
|
|
800
|
+
.option('--wireguard-install', 'Installs the wireguard-tools, haproxy and iptables host packages.')
|
|
801
|
+
.option('--wireguard-setup', 'Generates keys, builds the interface config, and applies local network rules.')
|
|
802
|
+
.option('--node-config', 'Writes a node identity under deploy/nodes, named after the machine it describes.')
|
|
803
|
+
.option(
|
|
804
|
+
'--node-name <node-name>',
|
|
805
|
+
'Node record to write; defaults to this hostname, which is what runtime commands resolve their identity by.',
|
|
806
|
+
)
|
|
807
|
+
.option('--node-role <role>', 'Machine role: control, worker, or hub.')
|
|
808
|
+
.option('--hub-host <ipv4>', 'Static public IPv4 key of the hub topology this node belongs to.')
|
|
809
|
+
.option('--port <port>', 'WireGuard UDP listening port (default: 51820).')
|
|
810
|
+
.option(
|
|
811
|
+
'--cidr <cidr>',
|
|
812
|
+
'Hub interface address on a hub; overlay subnet routed through the hub on control and worker nodes.',
|
|
813
|
+
)
|
|
814
|
+
.option('--peer-ip <ip>', 'Tunnel address used by --peer-add or to update the selected node during setup.')
|
|
815
|
+
.option('--peer-id <peer-id>', 'Topology peer represented by a control or worker node identity.')
|
|
816
|
+
.option('--public-key <key>', 'Public key used by off-host topology authoring or --peer-add.')
|
|
817
|
+
.option('--peer-add <peer-id>', 'Registers a spoke and applies it to the running hub without a restart.')
|
|
818
|
+
.option('--peer-remove <peer-id>', 'Removes a peer from the selected topology and running hub.')
|
|
819
|
+
.option('--allowed-ips <cidrs>', 'Comma-separated CIDRs routed to the spoke (e.g. "10.0.0.2/32,192.168.10.0/24").')
|
|
820
|
+
.option('--hosts <hosts>', 'Comma-separated hostnames bound to the spoke, overriding instance resolution.')
|
|
821
|
+
.option('--instances <instances>', 'Comma-separated conf.instances.json ids bound to the spoke.')
|
|
822
|
+
.option(
|
|
823
|
+
'--management-host <host>',
|
|
824
|
+
'Stable LAN or management address used to repair this peer when its tunnel address is unavailable.',
|
|
825
|
+
)
|
|
826
|
+
.option('--default', 'Marks the spoke as the fallback for hostnames that match no other binding.')
|
|
827
|
+
.option('--haproxy-setup', 'Installs HAProxy, publishes the current routes, and enables the daemon.')
|
|
828
|
+
.option('--haproxy-sync', 'Recompiles the SNI/Host maps from deploy config and hot-reloads HAProxy.')
|
|
829
|
+
.option(
|
|
830
|
+
'--status',
|
|
831
|
+
'Prints the whole edge context without changing anything: role, interface, tunnel address, ' +
|
|
832
|
+
'public key, daemon states, peers with their bindings and link health, and the resolved routing.',
|
|
833
|
+
)
|
|
834
|
+
.option(
|
|
835
|
+
'--build-conf',
|
|
836
|
+
'Writes only engine-private/deploy/conf.wireguard.json and touches no host state. ' +
|
|
837
|
+
'Combine with --wireguard-setup / --peer-add / --peer-remove to author the topology off-box; ' +
|
|
838
|
+
'alone it normalizes and validates the existing topology.',
|
|
839
|
+
)
|
|
840
|
+
.option(
|
|
841
|
+
'--forward-proxy-server',
|
|
842
|
+
'Ensures the hub HTTP/CONNECT forward proxy runs as the underpost-forward-proxy systemd service, ' +
|
|
843
|
+
'bound to the tunnel address only (default port 1080), and returns. Authenticates every request with ' +
|
|
844
|
+
'FORWARD_PROXY_API_KEY, so spokes can reach the internet through the VPS public address. Idempotent: ' +
|
|
845
|
+
're-running converges on the one service and restarts it only when the unit actually changed.',
|
|
846
|
+
)
|
|
847
|
+
.option(
|
|
848
|
+
'--forward-proxy-server-host <host>',
|
|
849
|
+
'Address the forward proxy binds, overriding the selected hub tunnel address.',
|
|
850
|
+
)
|
|
851
|
+
.option('--forward-proxy-server-port <port>', 'Port the forward proxy binds (default: 1080).')
|
|
852
|
+
.option(
|
|
853
|
+
'--ssh-forward-port <port>',
|
|
854
|
+
'Publishes the default spoke SSH port on this public TCP port of the hub, so CI with no fixed ' +
|
|
855
|
+
'address can reach the cluster node (e.g. 2222). "0" closes it. Stored in hub topology.',
|
|
856
|
+
)
|
|
857
|
+
.option(
|
|
858
|
+
'--sync',
|
|
859
|
+
'Brings every registered node engine checkout up to date over its SSH identity: clean, pull, fix and install.',
|
|
860
|
+
)
|
|
861
|
+
.option(
|
|
862
|
+
'--nodes <node-names>',
|
|
863
|
+
'Comma-separated node documents --sync, --cmd, --node-exporter and --connect-uri act on. ' +
|
|
864
|
+
'Empty covers every hub and every peer of this node hub.',
|
|
865
|
+
)
|
|
866
|
+
.option(
|
|
867
|
+
'--connect-uri',
|
|
868
|
+
'Prints the SSH command that reaches each node named by --nodes, joining the node document under ' +
|
|
869
|
+
'engine-private/deploy/nodes to the management address it is registered under in ' +
|
|
870
|
+
'engine-private/deploy/conf.users.json. Empty --nodes lists the whole fleet.',
|
|
871
|
+
)
|
|
872
|
+
.option('--copy', 'Copies the --connect-uri output to the clipboard instead of printing it.')
|
|
873
|
+
.option(
|
|
874
|
+
'--cmd <command-list>',
|
|
875
|
+
'Comma-separated custom commands to run on the selected nodes over their SSH identity. ' +
|
|
876
|
+
'Given with --sync, only these run in place of the sync steps.',
|
|
877
|
+
)
|
|
878
|
+
.option(
|
|
879
|
+
'--node-exporter',
|
|
880
|
+
'Provisions the host metrics collector as a systemd service on the selected hub nodes, bound to their ' +
|
|
881
|
+
'tunnel address, so machines outside the cluster report hardware metrics like every cluster node.',
|
|
882
|
+
)
|
|
883
|
+
.option(
|
|
884
|
+
'--repo-engine <repo>',
|
|
885
|
+
'Engine repository --sync pulls from, as owner/repo or a clone URL. Defaults to the configured account engine.',
|
|
886
|
+
)
|
|
887
|
+
.option(
|
|
888
|
+
'--repo-engine-private <repo>',
|
|
889
|
+
'Private engine repository --sync pulls from, as owner/repo or a clone URL. ' +
|
|
890
|
+
'Defaults to the configured private repo derived from --repo-engine.',
|
|
891
|
+
)
|
|
892
|
+
.option('--wireguard-start', 'Enables and starts wg-quick@<interface> and the QUIC forward.')
|
|
893
|
+
.option('--wireguard-restart', 'Restarts wg-quick@<interface> and restores the hub QUIC forward.')
|
|
894
|
+
.option('--wireguard-stop', 'Tears down the interface and removes its transient packet rules.')
|
|
895
|
+
.option('--check', 'Waits for an active interface and a fresh handshake with its required peer.')
|
|
896
|
+
.option('--check-timeout <seconds>', 'Maximum wait for --check (default: 30).')
|
|
897
|
+
.option('--expected-role <role>', 'Refuses restart/check unless this host has the expected node role.')
|
|
898
|
+
.option('--expected-id <peer-id>', 'Refuses restart/check unless this node represents the expected peer id.')
|
|
899
|
+
.option('--wireguard-reset', 'Removes generated host state, keeping keys, topology and node identity.')
|
|
900
|
+
.option('--wireguard-reinstall', 'Full purge, package reinstall and re-key; updates the selected topology key.')
|
|
901
|
+
.option('--dry-run', 'Prints the files and commands the run would apply, without touching the host.')
|
|
902
|
+
.description(description)
|
|
903
|
+
.action(Underpost.wireguard.callback);
|
|
904
|
+
|
|
905
|
+
edgeCommandFactory(
|
|
906
|
+
'wireguard',
|
|
907
|
+
'Manages the WireGuard L3 hub-and-spoke transport and the HAProxy edge gateway in front of it.',
|
|
908
|
+
);
|
|
909
|
+
edgeCommandFactory(
|
|
910
|
+
'haproxy',
|
|
911
|
+
'Manages the HAProxy edge gateway over the WireGuard transport (same subsystem as `underpost wireguard`).',
|
|
912
|
+
);
|
|
913
|
+
|
|
914
|
+
program
|
|
915
|
+
.command('vultr')
|
|
916
|
+
.argument('[deploy-list]', 'A comma-separated list of deployment IDs, logged for attribution.')
|
|
917
|
+
.option('--instance-id <instance-id>', 'Vultr instance id to meter (default: VULTR_INSTANCE_ID).')
|
|
918
|
+
.option('--api-key <api-key>', 'Vultr API key (default: VULTR_API_KEY). Prefer the environment over this flag.')
|
|
919
|
+
.option(
|
|
920
|
+
'--threshold <ratio>',
|
|
921
|
+
'Fraction of the plan quota that triggers the egress block; "0.80" and "80" are both accepted (default: 0.80).',
|
|
922
|
+
)
|
|
923
|
+
.option('--metric <metric>', '"total" (incoming + outgoing, default) or "outgoing" for egress alone.')
|
|
924
|
+
.option('--month <yyyy-mm>', 'Billing month to sum (default: the current UTC month).')
|
|
925
|
+
.option('--all-dates', 'Sum every daily bucket the API returns instead of scoping to one month.')
|
|
926
|
+
.option('--host <ip>', 'Edge VPS to block (default: VULTR_VPS_IP, then DEFAULT_SSH_HOST).')
|
|
927
|
+
.option('--user <user>', 'SSH user on the edge VPS (default: VULTR_SSH_USER, then DEFAULT_SSH_USER, then "root").')
|
|
928
|
+
.option('--key-path <path>', 'SSH private key (default: VULTR_SSH_KEY_PATH, then DEFAULT_SSH_KEY_PATH).')
|
|
929
|
+
.option('--port <port>', 'SSH port on the edge VPS (default: VULTR_SSH_PORT, then DEFAULT_SSH_PORT, then 22).')
|
|
930
|
+
.option('--force', 'Re-apply the egress block even if it was already applied for this cycle.')
|
|
931
|
+
.option('--auto-unblock', 'Restore egress automatically once consumption falls back under the threshold.')
|
|
932
|
+
.option('--dry-run', 'Reports the consumption and the action it would take, without touching the edge VPS.')
|
|
933
|
+
.description('Meters the edge VPS bandwidth against its Vultr plan quota and blocks egress before overage accrues.')
|
|
934
|
+
.action(Underpost.vultr.callback);
|
|
935
|
+
|
|
699
936
|
program
|
|
700
937
|
.command('run')
|
|
701
938
|
.argument('<runner-id>', `The runner ID to run. Options: ${Underpost.run.RUNNERS}.`)
|
|
@@ -730,6 +967,12 @@ program
|
|
|
730
967
|
.option('--volume-mount-path <volume-mount-path>', 'Optional: Specifies the volume mount path for test execution.')
|
|
731
968
|
.option('--volume-type <volume-type>', 'Optional: Specifies the volume type for test execution.')
|
|
732
969
|
.option('--image-name <image-name>', 'Optional: Specifies the image name for test execution.')
|
|
970
|
+
.option('--image <image>', 'Container image the deployment pulls and runs (sync).')
|
|
971
|
+
.option('--runtime-image <name>', 'src/runtime/<name> image family the cluster runner brings up (default "express").')
|
|
972
|
+
.option(
|
|
973
|
+
'--versions <deployment-versions>',
|
|
974
|
+
'Comma-separated blue/green deployment versions (sync); unset resolves the next colour.',
|
|
975
|
+
)
|
|
733
976
|
.option('--container-name <container-name>', 'Optional: Specifies the container name for test execution.')
|
|
734
977
|
.option('--namespace <namespace>', 'Optional: Specifies the namespace for test execution.')
|
|
735
978
|
.option('--tty', 'Enables TTY for the container in deploy-job.')
|
|
@@ -769,7 +1012,7 @@ program
|
|
|
769
1012
|
.option('--cmd-cron-jobs <cmd-cron-jobs>', 'Pre-script commands to run before cron job execution.')
|
|
770
1013
|
.option(
|
|
771
1014
|
'--deploy-id-cron-jobs <deploy-id-cron-jobs>',
|
|
772
|
-
'
|
|
1015
|
+
'Cron deploy-id to set up during sync; defaults to dd.cron, "none" skips cron setup entirely.',
|
|
773
1016
|
)
|
|
774
1017
|
.option('--timezone <timezone>', 'Sets the timezone for the runner execution.')
|
|
775
1018
|
.option('--kubeadm', 'Sets the kubeadm cluster context for the runner execution.')
|
|
@@ -807,6 +1050,11 @@ program
|
|
|
807
1050
|
'Omits the QUIC/HTTP3 listener config and the Alt-Svc advertisement from Gateway API manifests.',
|
|
808
1051
|
)
|
|
809
1052
|
.option('--quic-port <port>', 'UDP port advertised for QUIC/HTTP3 in generated Gateway API manifests (default 443).')
|
|
1053
|
+
.option(
|
|
1054
|
+
'--repo-engine-private <repo>',
|
|
1055
|
+
'Private configuration repository the pull runner checks out, as owner/repo or a clone URL. ' +
|
|
1056
|
+
'Defaults to the private repo derived from the engine source.',
|
|
1057
|
+
)
|
|
810
1058
|
.option('--disable-private-conf-update', 'Disables updates to private configuration during execution.')
|
|
811
1059
|
.option('--logs', 'Streams logs during the runner execution.')
|
|
812
1060
|
.option('--monitor-status <status>', 'Sets the status to monitor for pod/resource (default: "Running").')
|
|
@@ -855,6 +1103,33 @@ program
|
|
|
855
1103
|
.description('Runs specified scripts using various runners.')
|
|
856
1104
|
.action(Underpost.run.callback);
|
|
857
1105
|
|
|
1106
|
+
program
|
|
1107
|
+
.command('test')
|
|
1108
|
+
.argument(
|
|
1109
|
+
'[suite]',
|
|
1110
|
+
`A comma-separated list of suites or tiers to run. Suites: ${testSuiteNames().join(', ')}. ` +
|
|
1111
|
+
`Tiers: ${TEST_TIERS.map(({ name }) => name).join(', ')}. Defaults to every tier, in tier order.`,
|
|
1112
|
+
'',
|
|
1113
|
+
)
|
|
1114
|
+
.option('--itc', 'Runs in this execution context instead of dispatching into deployment pods.')
|
|
1115
|
+
.option('--deploy-list <deploy-list>', 'A comma-separated list of deployment IDs to run the suite inside.')
|
|
1116
|
+
.option('--grep <pattern>', 'Runs only tests whose name matches the pattern.')
|
|
1117
|
+
.option('--watch', 'Keeps the runner open and re-runs affected suites on change.')
|
|
1118
|
+
.option('--no-coverage', 'Skips coverage instrumentation and reporters.')
|
|
1119
|
+
.option('--allure', 'Writes Allure results for the cluster dashboard alongside the run.')
|
|
1120
|
+
.option('--dashboard', 'Applies the Allure dashboard to the cluster and exits.')
|
|
1121
|
+
.option('--job', 'Runs the selected suite on the cluster as a Kubernetes Job (requires --image).')
|
|
1122
|
+
.option('--image <image>', 'Image carrying the engine and its dependencies, for --job.')
|
|
1123
|
+
.option('--node-name <node-name>', 'Pins the --job pod to this node.')
|
|
1124
|
+
.option('--host <host>', 'Hostname to route the --dashboard sub-path on.')
|
|
1125
|
+
.option('--namespace <namespace>', 'Kubernetes namespace for --dashboard, --job and --deploy-list.')
|
|
1126
|
+
.option('--dry-run', 'Renders the --dashboard or --job manifests without applying them.')
|
|
1127
|
+
.option('--pod-name <pod-name>', 'Waits for this cluster object to reach --pod-status instead of running tests.')
|
|
1128
|
+
.option('--pod-status <pod-status>', 'Status --pod-name waits for (default: "Running").')
|
|
1129
|
+
.option('--kind-type <kind-type>', 'Kind --pod-name queries (default: "pods").')
|
|
1130
|
+
.description('Runs the test tiers locally, inside deployment pods, or as a cluster Job with Allure reporting.')
|
|
1131
|
+
.action(Underpost.test.callback);
|
|
1132
|
+
|
|
858
1133
|
program
|
|
859
1134
|
.command('docker-compose')
|
|
860
1135
|
.argument('[target]', 'Optional service name for --logs, --shell, --restart, or --build.')
|
|
@@ -1026,15 +1301,15 @@ program
|
|
|
1026
1301
|
.option('--control <ip>', 'Control-plane IP the worker node joins (used with --worker for kubeadm infra setup).')
|
|
1027
1302
|
.option(
|
|
1028
1303
|
'--ssh-key-dir <dir>',
|
|
1029
|
-
'Directory holding the SSH key pair used for commissioning/orchestration (expects <dir>/id_rsa and <dir>/id_rsa.pub). Overrides the workflow "sshKeyDir"; defaults to engine-private/deploy. Supports a leading ~.',
|
|
1304
|
+
'Directory holding the SSH key pair used for commissioning/orchestration (expects <dir>/id_rsa and <dir>/id_rsa.pub). Overrides the workflow "sshKeyDir"; defaults to engine-private/deploy/users/<user> for a non-root --user, otherwise engine-private/deploy. Supports a leading ~.',
|
|
1030
1305
|
)
|
|
1031
1306
|
.option(
|
|
1032
1307
|
'--deploy-id <deploy-id>',
|
|
1033
|
-
'Deployment ID
|
|
1308
|
+
'Deployment ID used to resolve the private engine repo cloned onto the node (engine-<suffix>-private.',
|
|
1034
1309
|
)
|
|
1035
1310
|
.option(
|
|
1036
1311
|
'--user <user>',
|
|
1037
|
-
'SSH user
|
|
1312
|
+
'SSH user whose cluster scoped key pair is used (engine-private/deploy/users/<user>/id_rsa) and the login user on an existing control-plane (defaults to root, whose key is engine-private/deploy/id_rsa). Mirrors the ssh command --user.',
|
|
1038
1313
|
)
|
|
1039
1314
|
.option(
|
|
1040
1315
|
'--engine-repo <url>',
|
|
@@ -1099,6 +1374,23 @@ program
|
|
|
1099
1374
|
)
|
|
1100
1375
|
.action(Underpost.baremetal.callback);
|
|
1101
1376
|
|
|
1377
|
+
program
|
|
1378
|
+
.command('package')
|
|
1379
|
+
.argument(
|
|
1380
|
+
'[deploy-id]',
|
|
1381
|
+
'Deploy id, or a comma-separated list, to act on. Defaults to every deploy id in the private configuration tree.',
|
|
1382
|
+
)
|
|
1383
|
+
.option('--sync', 'Regenerates each deploy manifest from the engine manifest and the deploy catalog (default).')
|
|
1384
|
+
.option('--install', 'Installs the dependencies the deploy catalog pins into this checkout.')
|
|
1385
|
+
.option('--rename <name>', "Renames this checkout's package, in its manifest and its lockfile.")
|
|
1386
|
+
.option('--set-repo <owner/repo>', "Points this checkout's package at a repository.")
|
|
1387
|
+
.option('--dry-run', 'For --sync: resolves the manifests without writing them.')
|
|
1388
|
+
.description(
|
|
1389
|
+
"Generates the package manifests a deploy id owns, from the engine manifest and the deploy's " +
|
|
1390
|
+
'product catalog, and installs the dependencies that catalog pins.',
|
|
1391
|
+
)
|
|
1392
|
+
.action(Underpost.package.callback);
|
|
1393
|
+
|
|
1102
1394
|
program
|
|
1103
1395
|
.command('release')
|
|
1104
1396
|
.argument('[version]', 'The new version string to set (e.g., "3.1.4"). Defaults to current version.')
|