@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/cluster.js
CHANGED
|
@@ -4,18 +4,31 @@
|
|
|
4
4
|
* @namespace UnderpostCluster
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { clusterTypeFactory, gatewayApiEnabledFactory,
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
7
|
+
import { clusterTypeFactory, gatewayApiEnabledFactory, resolveReplicaCount } from '../server/runtime/conf.js';
|
|
8
|
+
import { getNpmRootPath, HOST_VOLUME_ROOT } from '../server/runtime/environment.js';
|
|
9
|
+
import { loggerFactory } from '../server/ops/logger.js';
|
|
10
|
+
import { shellExec } from '../server/runtime/process.js';
|
|
11
|
+
import { crictlCommandFactory, resolveCriSocket } from '../server/ops/cri.js';
|
|
12
|
+
import {
|
|
13
|
+
runSELinuxCommands,
|
|
14
|
+
selinuxEnforcingCommandsFactory,
|
|
15
|
+
selinuxPackagesCommandFactory,
|
|
16
|
+
selinuxRestoreconCommandFactory,
|
|
17
|
+
} from '../server/security/selinux.js';
|
|
18
|
+
import ContainerStorageService, {
|
|
19
|
+
containerStorageRootsFactory,
|
|
20
|
+
ensureContainerStorage,
|
|
21
|
+
localPathConfigCommandFactory,
|
|
22
|
+
localPathRootsFactory,
|
|
23
|
+
} from '../server/security/container-storage.js';
|
|
24
|
+
import { UNDERPOST_GATEWAY, seedDefaultStatusPage } from '../server/network/underpost-gateway.js';
|
|
12
25
|
import {
|
|
13
26
|
UNDERPOST_INGRESS,
|
|
14
27
|
gatewayBackendFactory,
|
|
15
28
|
underpostIngressConfFactory,
|
|
16
29
|
underpostIngressHostMapFactory,
|
|
17
30
|
underpostIngressManifestsFactory,
|
|
18
|
-
} from '../server/underpost-ingress.js';
|
|
31
|
+
} from '../server/network/underpost-ingress.js';
|
|
19
32
|
import { MONGODB_DEFAULT_REPLICA_COUNT } from '../db/mongo/MongooseDB.js';
|
|
20
33
|
import { MongoBootstrap } from '../db/mongo/MongoBootstrap.js';
|
|
21
34
|
import os from 'os';
|
|
@@ -24,17 +37,32 @@ import Underpost from '../index.js';
|
|
|
24
37
|
|
|
25
38
|
const logger = loggerFactory(import.meta);
|
|
26
39
|
|
|
27
|
-
// Pinned Gateway API control plane. The CRD release and the implementation are
|
|
28
|
-
// upgraded together, and the pairing is not free choice: Envoy Gateway builds
|
|
29
|
-
// against one `sigs.k8s.io/gateway-api` version (v1.8.3 -> v1.5.1) and reads
|
|
30
|
-
// fields the older CRD schemas do not define, which the API
|
|
31
|
-
// server silently strips. Check the implementation's go.mod before moving
|
|
32
|
-
// either pin.
|
|
33
40
|
const GATEWAY_API_RELEASE = 'v1.5.1';
|
|
34
41
|
const ENVOY_GATEWAY_VERSION = 'v1.8.3';
|
|
35
|
-
// Namespace the upstream Contour render deploys into, and the only one where an
|
|
36
|
-
// `app=envoy` selector resolves to its DaemonSet.
|
|
37
42
|
const CONTOUR_NAMESPACE = 'projectcontour';
|
|
43
|
+
const LOCAL_PATH_PROVISIONER_MANIFEST =
|
|
44
|
+
'https://cdn.jsdelivr.net/gh/rancher/local-path-provisioner@master/deploy/local-path-storage.yaml';
|
|
45
|
+
const K3S_SELINUX_PATHS = [
|
|
46
|
+
'/usr/local/bin/k3s',
|
|
47
|
+
'/etc/rancher',
|
|
48
|
+
'/var/lib/rancher',
|
|
49
|
+
'/var/lib/kubelet',
|
|
50
|
+
'/var/lib/cni',
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
// `semanage` and `restorecon` come from separate packages and neither is guaranteed on a minimal
|
|
54
|
+
// Rocky install. Installed before anything tries to register a mapping, because a missing
|
|
55
|
+
// `semanage` would otherwise turn every persistent labeling command into a hard failure.
|
|
56
|
+
const ensureSELinuxTooling = () =>
|
|
57
|
+
shellExec(
|
|
58
|
+
`if [ -f /etc/redhat-release ] && command -v dnf >/dev/null 2>&1 && { ! command -v restorecon >/dev/null 2>&1 || ! command -v semanage >/dev/null 2>&1; }; then ${selinuxPackagesCommandFactory()}; fi`,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const enforceSELinux = (paths = []) => {
|
|
62
|
+
ensureSELinuxTooling();
|
|
63
|
+
const commands = selinuxEnforcingCommandsFactory({ restorePaths: paths });
|
|
64
|
+
runSELinuxCommands(commands, { execute: shellExec });
|
|
65
|
+
};
|
|
38
66
|
|
|
39
67
|
/**
|
|
40
68
|
* @class UnderpostCluster
|
|
@@ -90,9 +118,10 @@ class UnderpostCluster {
|
|
|
90
118
|
* @param {boolean} [options.nodePort=false] - Expose enabled ready services (e.g. MongoDB 4.4, Valkey)
|
|
91
119
|
* to the host/public network via their NodePort Service manifest. The node port value lives directly
|
|
92
120
|
* in each manifest (mongodb-4.4/mongodb-nodeport.yaml, valkey/valkey-nodeport.yaml).
|
|
93
|
-
* @param {string} [options.
|
|
94
|
-
* to a specific Kubernetes node by name (e.g.
|
|
95
|
-
* `kubernetes.io/hostname` nodeSelector patch once
|
|
121
|
+
* @param {string} [options.nodeName=''] - Pin the just-deployed StatefulSet (MongoDB 4.4 / Valkey)
|
|
122
|
+
* and the observability workloads to a specific Kubernetes node by name (e.g.
|
|
123
|
+
* 'localhost.localdomain'). Applied via a `kubernetes.io/hostname` nodeSelector patch once
|
|
124
|
+
* the workload reports Ready.
|
|
96
125
|
* @memberof UnderpostCluster
|
|
97
126
|
*/
|
|
98
127
|
async init(
|
|
@@ -132,7 +161,7 @@ class UnderpostCluster {
|
|
|
132
161
|
hosts: '',
|
|
133
162
|
replicas: '',
|
|
134
163
|
nodePort: false,
|
|
135
|
-
|
|
164
|
+
nodeName: '',
|
|
136
165
|
},
|
|
137
166
|
) {
|
|
138
167
|
if (options.initHost) return Underpost.cluster.initHost();
|
|
@@ -210,6 +239,12 @@ class UnderpostCluster {
|
|
|
210
239
|
logger.info(
|
|
211
240
|
`Detected existing ${runtime.type} cluster (${runtime.ready ? 'Ready' : 'NotReady'}); skipping initialization.`,
|
|
212
241
|
);
|
|
242
|
+
// Initialization is skipped, but the labeling invariant is not: the node directories
|
|
243
|
+
// backing PersistentVolumes outlive the bring-up that created them, and a policy update,
|
|
244
|
+
// a full relabel or a directory recreated by kubelet resets them to the policy default.
|
|
245
|
+
// Re-asserting it costs a `semanage` lookup and a `restorecon` pass, mutates no workload,
|
|
246
|
+
// and never changes SELinux mode.
|
|
247
|
+
Underpost.cluster.ensureContainerStorageContexts();
|
|
213
248
|
}
|
|
214
249
|
|
|
215
250
|
// --- Kubeadm/Kind/K3s Cluster Initialization ---
|
|
@@ -227,8 +262,11 @@ class UnderpostCluster {
|
|
|
227
262
|
// balancer. The platform exposes services explicitly via Project
|
|
228
263
|
// Contour / Envoy and NodePort services (see --node-port); leaving the
|
|
229
264
|
// K3s built-ins enabled would bind the same host ports and conflict.
|
|
230
|
-
shellExec(
|
|
265
|
+
shellExec(
|
|
266
|
+
`curl -sfL https://get.k3s.io | sh -s - $(if command -v selinuxenabled >/dev/null 2>&1 && selinuxenabled; then printf '%s' '--selinux'; fi) --disable=traefik --disable=servicelb`,
|
|
267
|
+
);
|
|
231
268
|
logger.info('K3s installation completed.');
|
|
269
|
+
runSELinuxCommands([selinuxRestoreconCommandFactory(K3S_SELINUX_PATHS)], { execute: shellExec });
|
|
232
270
|
|
|
233
271
|
Underpost.cluster.chown('k3s');
|
|
234
272
|
|
|
@@ -240,6 +278,7 @@ class UnderpostCluster {
|
|
|
240
278
|
} else if (options.kubeadm) {
|
|
241
279
|
Underpost.cluster.config();
|
|
242
280
|
Underpost.cluster.natSetup({ underpostRoot });
|
|
281
|
+
Underpost.cluster.ensureContainerStorageContexts({ controlPlane: true });
|
|
243
282
|
logger.info('Initializing Kubeadm control plane...');
|
|
244
283
|
// Set default values if not provided
|
|
245
284
|
const podNetworkCidr = options.podNetworkCidr || '192.168.0.0/16';
|
|
@@ -267,11 +306,13 @@ class UnderpostCluster {
|
|
|
267
306
|
// Untaint control plane node to allow scheduling pods
|
|
268
307
|
const nodeName = os.hostname();
|
|
269
308
|
shellExec(`kubectl taint nodes ${nodeName} node-role.kubernetes.io/control-plane:NoSchedule-`);
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
);
|
|
309
|
+
// The CNI lands asynchronously, and the node stays NotReady until it
|
|
310
|
+
// does. Block here so the deploy steps that follow (MongoDB and the
|
|
311
|
+
// application workloads) schedule onto a node that can actually run
|
|
312
|
+
// them, instead of racing the Calico rollout.
|
|
313
|
+
logger.info('Waiting for the node to become Ready (Calico rollout)...');
|
|
314
|
+
shellExec(`kubectl wait --for=condition=Ready node --all --timeout=300s`);
|
|
315
|
+
Underpost.cluster.ensureLocalPathProvisioner();
|
|
275
316
|
} else {
|
|
276
317
|
Underpost.cluster.config();
|
|
277
318
|
Underpost.cluster.natSetup({ underpostRoot });
|
|
@@ -322,36 +363,19 @@ class UnderpostCluster {
|
|
|
322
363
|
shellExec(`node ${underpostRoot}/bin/deploy kubeflow-spark-operator${options.kubeadm ? ' kubeadm' : ''}`);
|
|
323
364
|
}
|
|
324
365
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (options.prom) {
|
|
339
|
-
shellExec(`kubectl delete deployment prometheus --ignore-not-found`);
|
|
340
|
-
shellExec(`kubectl delete configmap prometheus-config --ignore-not-found`);
|
|
341
|
-
shellExec(`kubectl delete service prometheus --ignore-not-found`);
|
|
342
|
-
// Prometheus server host: http://<prometheus-cluster-ip>:9090
|
|
343
|
-
const yaml = `${fs.readFileSync(`${underpostRoot}/manifests/prometheus/deployment.yaml`, 'utf8').replace(
|
|
344
|
-
'- targets: []',
|
|
345
|
-
`- targets: [${options.prom
|
|
346
|
-
.split(',')
|
|
347
|
-
.map((host) => `'${host}'`)
|
|
348
|
-
.join(',')}]`,
|
|
349
|
-
)}`;
|
|
350
|
-
console.log(yaml);
|
|
351
|
-
shellExec(`kubectl apply -f - -n ${options.namespace} <<'EOF'
|
|
352
|
-
${yaml}
|
|
353
|
-
EOF
|
|
354
|
-
`);
|
|
366
|
+
// Grafana and Prometheus are two faces of one stack, so either flag
|
|
367
|
+
// converges the whole of it — including Alertmanager and the Blackbox
|
|
368
|
+
// Exporter, which the alert rules and probes are useless without. The
|
|
369
|
+
// scrape configuration is rendered from the deploy configuration and the
|
|
370
|
+
// event registry by the monitor CLI; `--prom [hosts]` only adds hosts
|
|
371
|
+
// that configuration does not name.
|
|
372
|
+
if (options.grafana || options.prom) {
|
|
373
|
+
await Underpost.monitor.deployObservability({
|
|
374
|
+
namespace: options.namespace,
|
|
375
|
+
dev: options.dev,
|
|
376
|
+
nodeName: options.nodeName,
|
|
377
|
+
hosts: typeof options.prom === 'string' ? options.prom : options.hosts,
|
|
378
|
+
});
|
|
355
379
|
}
|
|
356
380
|
|
|
357
381
|
if (options.valkey) {
|
|
@@ -363,11 +387,11 @@ EOF
|
|
|
363
387
|
// The node port (32079) is set directly in the manifest.
|
|
364
388
|
if (valkeyReady && options.nodePort)
|
|
365
389
|
shellExec(`kubectl apply -f ${underpostRoot}/manifests/valkey/valkey-nodeport.yaml -n ${options.namespace}`);
|
|
366
|
-
if (valkeyReady && options.
|
|
390
|
+
if (valkeyReady && options.nodeName)
|
|
367
391
|
Underpost.cluster.pinToNode({
|
|
368
392
|
name: 'valkey-service',
|
|
369
393
|
namespace: options.namespace,
|
|
370
|
-
node: options.
|
|
394
|
+
node: options.nodeName,
|
|
371
395
|
});
|
|
372
396
|
if (valkeyReady && serviceHost)
|
|
373
397
|
Underpost.cluster.syncServiceConnectionEnv({
|
|
@@ -384,32 +408,32 @@ EOF
|
|
|
384
408
|
// Encrypted store first; when no manifest exists the secret is seeded from its origin
|
|
385
409
|
// seed path below. A manifest that exists but fails validation raises rather than
|
|
386
410
|
// silently seeding stale credentials.
|
|
387
|
-
if (!Underpost.secret.
|
|
388
|
-
|
|
389
|
-
`sudo kubectl create secret generic mariadb-secret --from-file=username=/home/dd/engine/engine-private/mariadb-username --from-file=password=/home/dd/engine/engine-private/mariadb-password --dry-run=client -o yaml | kubectl apply -f - -n ${options.namespace}`,
|
|
390
|
-
);
|
|
411
|
+
if (!Underpost.secret.applyIfPresent('mariadb-secret', options.namespace))
|
|
412
|
+
Underpost.secret.applyFromOriginSeed('mariadb-secret', options.namespace);
|
|
391
413
|
shellExec(`kubectl delete statefulset mariadb-statefulset -n ${options.namespace} --ignore-not-found`);
|
|
392
414
|
|
|
393
415
|
if (options.pullImage) Underpost.cluster.pullImage('mariadb:latest', options);
|
|
416
|
+
// The StatefulSet's volumeClaimTemplate is dynamically provisioned, so the data lands in
|
|
417
|
+
// a subdirectory of the local-path root and inherits that root's label.
|
|
418
|
+
Underpost.cluster.ensureContainerStorageContexts({ extraPaths: ['/data/mariadb'] });
|
|
394
419
|
shellExec(`kubectl apply -f ${underpostRoot}/manifests/mariadb/storage-class.yaml -n ${options.namespace}`);
|
|
395
420
|
shellExec(`kubectl apply -k ${underpostRoot}/manifests/mariadb -n ${options.namespace}`);
|
|
396
421
|
}
|
|
397
422
|
if (options.mysql) {
|
|
398
|
-
if (!Underpost.secret.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
423
|
+
if (!Underpost.secret.applyIfPresent('mysql-secret', options.namespace))
|
|
424
|
+
Underpost.secret.applyFromOriginSeed('mysql-secret', options.namespace);
|
|
425
|
+
// The data directory is prepared, not opened up: a world-writable host path plus the
|
|
426
|
+
// operator's ownership was standing in for the SELinux label the container actually
|
|
427
|
+
// needed. `container_file_t` is what lets mysqld write here; 0755 root-owned is enough,
|
|
428
|
+
// because the image's entrypoint chowns the tree to its own uid on first start.
|
|
429
|
+
Underpost.cluster.ensureContainerStorageContexts({ extraPaths: ['/data/mysql'] });
|
|
405
430
|
shellExec(`kubectl apply -k ${underpostRoot}/manifests/mysql -n ${options.namespace}`);
|
|
406
431
|
}
|
|
407
432
|
if (options.postgresql) {
|
|
408
433
|
if (options.pullImage) Underpost.cluster.pullImage('postgres:latest', options);
|
|
409
|
-
if (!Underpost.secret.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
);
|
|
434
|
+
if (!Underpost.secret.applyIfPresent('postgres-secret', options.namespace))
|
|
435
|
+
Underpost.secret.applyFromOriginSeed('postgres-secret', options.namespace);
|
|
436
|
+
Underpost.cluster.ensureContainerStorageContexts({ extraPaths: ['/data/postgresql'] });
|
|
413
437
|
shellExec(`kubectl apply -k ${underpostRoot}/manifests/postgresql -n ${options.namespace}`);
|
|
414
438
|
}
|
|
415
439
|
if (options.mongodb4) {
|
|
@@ -453,11 +477,11 @@ EOF
|
|
|
453
477
|
shellExec(
|
|
454
478
|
`kubectl apply -f ${underpostRoot}/manifests/mongodb-4.4/mongodb-nodeport.yaml -n ${options.namespace}`,
|
|
455
479
|
);
|
|
456
|
-
if (options.
|
|
480
|
+
if (options.nodeName)
|
|
457
481
|
Underpost.cluster.pinToNode({
|
|
458
482
|
name: statefulSetName,
|
|
459
483
|
namespace: options.namespace,
|
|
460
|
-
node: options.
|
|
484
|
+
node: options.nodeName,
|
|
461
485
|
});
|
|
462
486
|
if (serviceHost)
|
|
463
487
|
Underpost.cluster.syncServiceConnectionEnv({
|
|
@@ -691,13 +715,107 @@ EOF
|
|
|
691
715
|
return { type, ready, nodes };
|
|
692
716
|
},
|
|
693
717
|
|
|
718
|
+
/**
|
|
719
|
+
* @method discoverLocalPathRoots
|
|
720
|
+
* @description Reads the node directories the local-path provisioner writes into, from its
|
|
721
|
+
* live ConfigMap. Every dynamically provisioned claim in this platform (Grafana, Prometheus,
|
|
722
|
+
* Alertmanager, IPFS, MariaDB) becomes a subdirectory of one of them, so the root has to be
|
|
723
|
+
* discovered rather than assumed — a wrong guess leaves those claims carrying the `/opt`
|
|
724
|
+
* policy default (`usr_t`), which no `container_t` pod can write.
|
|
725
|
+
* @returns {string[]} Configured node paths; empty when no provisioner is reachable.
|
|
726
|
+
* @memberof UnderpostCluster
|
|
727
|
+
*/
|
|
728
|
+
discoverLocalPathRoots() {
|
|
729
|
+
for (const namespace of ContainerStorageService.LOCAL_PATH_NAMESPACES) {
|
|
730
|
+
const config = `${
|
|
731
|
+
shellExec(localPathConfigCommandFactory({ namespace }), {
|
|
732
|
+
stdout: true,
|
|
733
|
+
silent: true,
|
|
734
|
+
silentOnError: true,
|
|
735
|
+
disableLog: true,
|
|
736
|
+
}) || ''
|
|
737
|
+
}`.trim();
|
|
738
|
+
const roots = localPathRootsFactory(config);
|
|
739
|
+
if (roots.length > 0) return roots;
|
|
740
|
+
}
|
|
741
|
+
return [];
|
|
742
|
+
},
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* @method ensureContainerStorageContexts
|
|
746
|
+
* @description Makes SELinux compatibility an invariant of the storage lifecycle rather than
|
|
747
|
+
* a one-time bring-up step: creates the node directories this platform hands to containers
|
|
748
|
+
* (only when missing, so live data trees keep their ownership and mode), registers the
|
|
749
|
+
* persistent `container_file_t` mapping for each, and restores the trees.
|
|
750
|
+
*
|
|
751
|
+
* Idempotent and safe to call on every deploy. Never relabels paths outside the discovered
|
|
752
|
+
* set, and never changes SELinux mode.
|
|
753
|
+
* @param {object} [options]
|
|
754
|
+
* @param {boolean} [options.controlPlane=false] - Also cover the kubeadm control-plane trees
|
|
755
|
+
* bind-mounted into containers (`/etc/kubernetes`, `/var/lib/etcd`, `/var/lib/calico`).
|
|
756
|
+
* @param {string[]} [options.extraPaths=[]] - Additional node directories to include.
|
|
757
|
+
* @returns {string[]} The roots that were prepared.
|
|
758
|
+
* @memberof UnderpostCluster
|
|
759
|
+
*/
|
|
760
|
+
ensureContainerStorageContexts(options = {}) {
|
|
761
|
+
const roots = containerStorageRootsFactory({
|
|
762
|
+
localPathRoots: Underpost.cluster.discoverLocalPathRoots(),
|
|
763
|
+
extraPaths: options.extraPaths || [],
|
|
764
|
+
controlPlane: options.controlPlane === true,
|
|
765
|
+
});
|
|
766
|
+
logger.info('Preparing container-mounted host storage', { roots });
|
|
767
|
+
// HOST_VOLUME_ROOT is the one root the deploy flow writes into unprivileged (it lives in the
|
|
768
|
+
// operator's home tree and receives each hostPath volume's contents), so it is created owned
|
|
769
|
+
// by the invoking user. The rest stay root-owned: their subdirectories are chowned by each
|
|
770
|
+
// workload's own init container, which is the single owner of that concern.
|
|
771
|
+
const { uid, gid } = os.userInfo();
|
|
772
|
+
const operatorRoots = roots.filter((root) => root === HOST_VOLUME_ROOT);
|
|
773
|
+
const systemRoots = roots.filter((root) => root !== HOST_VOLUME_ROOT);
|
|
774
|
+
if (systemRoots.length > 0) ensureContainerStorage(systemRoots, { execute: shellExec });
|
|
775
|
+
if (operatorRoots.length > 0)
|
|
776
|
+
ensureContainerStorage(operatorRoots, { execute: shellExec, owner: `${uid}:${gid}` });
|
|
777
|
+
return roots;
|
|
778
|
+
},
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* @method ensureLocalPathProvisioner
|
|
782
|
+
* @description Ensures dynamic local-path PVC provisioning is available.
|
|
783
|
+
* @returns {string} Namespace containing the ready provisioner.
|
|
784
|
+
* @memberof UnderpostCluster
|
|
785
|
+
*/
|
|
786
|
+
ensureLocalPathProvisioner() {
|
|
787
|
+
const locations = ['local-path-storage', 'kube-system'];
|
|
788
|
+
let namespace = locations.find((candidate) =>
|
|
789
|
+
`${
|
|
790
|
+
shellExec(`kubectl get deployment local-path-provisioner -n ${candidate} -o name`, {
|
|
791
|
+
stdout: true,
|
|
792
|
+
silent: true,
|
|
793
|
+
silentOnError: true,
|
|
794
|
+
disableLog: true,
|
|
795
|
+
}) || ''
|
|
796
|
+
}`.trim(),
|
|
797
|
+
);
|
|
798
|
+
|
|
799
|
+
if (!namespace) {
|
|
800
|
+
logger.info('Installing local-path-provisioner');
|
|
801
|
+
shellExec(`kubectl apply -f ${LOCAL_PATH_PROVISIONER_MANIFEST}`);
|
|
802
|
+
namespace = 'local-path-storage';
|
|
803
|
+
}
|
|
804
|
+
shellExec(`kubectl rollout status deployment/local-path-provisioner -n ${namespace} --timeout=5m`);
|
|
805
|
+
// The provisioner's root exists (or is about to) only now, and its helper pod creates each
|
|
806
|
+
// claim directory by inheriting that root's label. Prepare it here so the first dynamically
|
|
807
|
+
// provisioned claim already lands on `container_file_t` instead of `/opt`'s `usr_t`.
|
|
808
|
+
Underpost.cluster.ensureContainerStorageContexts();
|
|
809
|
+
return namespace;
|
|
810
|
+
},
|
|
811
|
+
|
|
694
812
|
/**
|
|
695
813
|
* @method pinToNode
|
|
696
814
|
* @description Pins a workload to a specific Kubernetes node by patching its
|
|
697
815
|
* pod template with a `kubernetes.io/hostname` nodeSelector. General-purpose;
|
|
698
|
-
* currently used to place the MongoDB 4.4 / Valkey StatefulSets
|
|
699
|
-
* node (`--node-
|
|
700
|
-
* target node.
|
|
816
|
+
* currently used to place the MongoDB 4.4 / Valkey StatefulSets and the
|
|
817
|
+
* observability Deployments on a chosen node (`--node-name`). The patch
|
|
818
|
+
* triggers a rolling reschedule onto the target node.
|
|
701
819
|
* @param {object} params
|
|
702
820
|
* @param {string} [params.kind='statefulset'] - Workload kind to patch.
|
|
703
821
|
* @param {string} params.name - Workload name.
|
|
@@ -1198,11 +1316,13 @@ EOF
|
|
|
1198
1316
|
}
|
|
1199
1317
|
}
|
|
1200
1318
|
const liveConf = canHotReload
|
|
1201
|
-
? `${
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1319
|
+
? `${
|
|
1320
|
+
execIngress('cat /tmp/nginx.conf', {
|
|
1321
|
+
stdout: true,
|
|
1322
|
+
silent: true,
|
|
1323
|
+
silentOnError: true,
|
|
1324
|
+
}) || ''
|
|
1325
|
+
}`
|
|
1206
1326
|
: '';
|
|
1207
1327
|
const shouldHotReload = canHotReload && liveConf.trimEnd() !== `${conf}`.trimEnd();
|
|
1208
1328
|
|
|
@@ -1222,10 +1342,10 @@ EOF
|
|
|
1222
1342
|
{ silent: true },
|
|
1223
1343
|
);
|
|
1224
1344
|
} catch (error) {
|
|
1225
|
-
execIngress(
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
);
|
|
1345
|
+
execIngress(`sh -c 'cp /tmp/nginx.previous.conf /tmp/nginx.conf && nginx -s reload -c /tmp/nginx.conf'`, {
|
|
1346
|
+
silent: true,
|
|
1347
|
+
silentOnError: true,
|
|
1348
|
+
});
|
|
1229
1349
|
throw error;
|
|
1230
1350
|
}
|
|
1231
1351
|
}
|
|
@@ -1241,10 +1361,10 @@ EOF
|
|
|
1241
1361
|
`);
|
|
1242
1362
|
} catch (error) {
|
|
1243
1363
|
if (shouldHotReload)
|
|
1244
|
-
execIngress(
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
);
|
|
1364
|
+
execIngress(`sh -c 'cp /tmp/nginx.previous.conf /tmp/nginx.conf && nginx -s reload -c /tmp/nginx.conf'`, {
|
|
1365
|
+
silent: true,
|
|
1366
|
+
silentOnError: true,
|
|
1367
|
+
});
|
|
1248
1368
|
throw error;
|
|
1249
1369
|
}
|
|
1250
1370
|
if (shouldHotReload)
|
|
@@ -1257,18 +1377,16 @@ EOF
|
|
|
1257
1377
|
// ready replica that made canHotReload true. Do not let the caller delete
|
|
1258
1378
|
// the old route kind until the replacement edge is actually Available.
|
|
1259
1379
|
if (!canHotReload || changesNode)
|
|
1260
|
-
shellExec(
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
);
|
|
1380
|
+
shellExec(`kubectl rollout status deployment/${UNDERPOST_INGRESS.name} -n ${namespace} --timeout=5m`, {
|
|
1381
|
+
silent: true,
|
|
1382
|
+
});
|
|
1264
1383
|
else if (shouldHotReload)
|
|
1265
1384
|
// `nginx -s reload` returns after signalling the master. Give it one
|
|
1266
1385
|
// scheduling turn to start the new workers before the caller removes
|
|
1267
1386
|
// the old stack's route object.
|
|
1268
1387
|
shellExec('sleep 1', { silent: true });
|
|
1269
1388
|
shellExec(
|
|
1270
|
-
`kubectl wait --for=condition=Available deployment/${UNDERPOST_INGRESS.name} ` +
|
|
1271
|
-
`-n ${namespace} --timeout=5m`,
|
|
1389
|
+
`kubectl wait --for=condition=Available deployment/${UNDERPOST_INGRESS.name} ` + `-n ${namespace} --timeout=5m`,
|
|
1272
1390
|
{ silent: true },
|
|
1273
1391
|
);
|
|
1274
1392
|
execIngress('nginx -t -c /tmp/nginx.conf', { silent: true });
|
|
@@ -1350,26 +1468,27 @@ EOF
|
|
|
1350
1468
|
config(options = { underpostRoot: '.' }) {
|
|
1351
1469
|
const { underpostRoot } = options;
|
|
1352
1470
|
console.log('Applying host configuration: SELinux, Docker, Containerd, and Sysctl settings.');
|
|
1353
|
-
//
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1471
|
+
// Label before enforcing, never after: flipping the mode first would put the host into
|
|
1472
|
+
// Enforcing with the storage trees still carrying the policy default, and every pod that
|
|
1473
|
+
// mounts one would start failing for real instead of only logging a denial.
|
|
1474
|
+
//
|
|
1475
|
+
// Registered on every run, not only at first cluster creation: the node directories backing
|
|
1476
|
+
// PersistentVolumes are recreated by resets, by `DirectoryOrCreate`, and by the local-path
|
|
1477
|
+
// helper pod long after `kubeadm init` ran, and each of those inherits the policy default
|
|
1478
|
+
// unless the mapping is already in the store.
|
|
1479
|
+
ensureSELinuxTooling();
|
|
1480
|
+
Underpost.cluster.ensureContainerStorageContexts();
|
|
1481
|
+
enforceSELinux(['/var/lib/kubelet', '/var/lib/containerd']);
|
|
1360
1482
|
|
|
1361
1483
|
// Enable and start Docker and Kubelet services
|
|
1362
1484
|
shellExec(`sudo systemctl enable --now docker`); // Docker might not be needed for K3s
|
|
1363
1485
|
shellExec(`sudo systemctl enable --now kubelet`); // Kubelet might not be needed for K3s (K3s uses its own agent)
|
|
1364
1486
|
|
|
1365
|
-
// Configure containerd for
|
|
1366
|
-
// This is crucial for kubelet/k3s to interact correctly with containerd
|
|
1487
|
+
// Configure containerd for systemd cgroups and SELinux labeling.
|
|
1367
1488
|
shellExec(`containerd config default | sudo tee /etc/containerd/config.toml > /dev/null`);
|
|
1368
1489
|
shellExec(`sudo sed -i -e "s/SystemdCgroup = false/SystemdCgroup = true/g" /etc/containerd/config.toml`);
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
// `sudo sed -i '/SystemdCgroup = true/a selinux_disabled = true' /etc/containerd/config.toml`,
|
|
1372
|
-
// );
|
|
1490
|
+
shellExec(`sudo sed -i -e "s/enable_selinux = false/enable_selinux = true/g" /etc/containerd/config.toml`);
|
|
1491
|
+
runSELinuxCommands([selinuxRestoreconCommandFactory('/etc/containerd')], { execute: shellExec });
|
|
1373
1492
|
// Restart docker after containerd config changes. Rocky 9 uses systemctl,
|
|
1374
1493
|
// not the legacy service command.
|
|
1375
1494
|
shellExec(`sudo systemctl restart docker || sudo service docker restart || true`);
|
|
@@ -1400,7 +1519,7 @@ EOF
|
|
|
1400
1519
|
* This applies only what K3s genuinely requires, and every step is guarded
|
|
1401
1520
|
* so it is a no-op when the relevant tooling is absent (e.g. minimal images
|
|
1402
1521
|
* without SELinux userspace):
|
|
1403
|
-
* - SELinux
|
|
1522
|
+
* - SELinux remains Enforcing.
|
|
1404
1523
|
* - swap off (Kubernetes best practice).
|
|
1405
1524
|
* - br_netfilter + bridge/forward sysctls (pod networking).
|
|
1406
1525
|
* - inotify limits.
|
|
@@ -1415,16 +1534,11 @@ EOF
|
|
|
1415
1534
|
// forever (the upstream unit ships TimeoutStartSec=0).
|
|
1416
1535
|
shellExec(`if systemctl is-active --quiet firewalld; then sudo systemctl disable --now firewalld; fi`);
|
|
1417
1536
|
|
|
1418
|
-
//
|
|
1419
|
-
//
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
});
|
|
1424
|
-
shellExec(
|
|
1425
|
-
`if [ -f /etc/selinux/config ]; then sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config; fi`,
|
|
1426
|
-
{ silentOnError: true },
|
|
1427
|
-
);
|
|
1537
|
+
// Storage labeling precedes the Enforcing flip, so the mode is never activated over trees
|
|
1538
|
+
// that still carry the policy default.
|
|
1539
|
+
ensureSELinuxTooling();
|
|
1540
|
+
Underpost.cluster.ensureContainerStorageContexts();
|
|
1541
|
+
enforceSELinux(K3S_SELINUX_PATHS);
|
|
1428
1542
|
|
|
1429
1543
|
// Disable swap. `swapoff -a` is a no-op without swap; the sed only edits
|
|
1430
1544
|
// fstab when a swap line is present.
|
|
@@ -1697,17 +1811,12 @@ fi`);
|
|
|
1697
1811
|
if (options.removeVolumeHostPaths) Underpost.cluster._cleanHostPathPvs();
|
|
1698
1812
|
else logger.info(' -> Skipping (pass --remove-volume-host-paths to enable).');
|
|
1699
1813
|
|
|
1700
|
-
logger.info('Phase 2/7: SELinux
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
);
|
|
1705
|
-
|
|
1706
|
-
`if command -v restorecon >/dev/null 2>&1 && [ -d /var/lib/kubelet ]; then sudo restorecon -Rv /var/lib/kubelet; fi`,
|
|
1707
|
-
);
|
|
1708
|
-
shellExec(
|
|
1709
|
-
`if command -v restorecon >/dev/null 2>&1 && [ -d /var/lib/containerd ]; then sudo restorecon -Rv /var/lib/containerd; fi`,
|
|
1710
|
-
);
|
|
1814
|
+
logger.info('Phase 2/7: Enforcing SELinux and restoring runtime contexts...');
|
|
1815
|
+
// The hostPath cleanup above emptied the volume trees; re-asserting the mapping here means
|
|
1816
|
+
// a rebuild starts from correctly labeled storage instead of inheriting the policy default.
|
|
1817
|
+
ensureSELinuxTooling();
|
|
1818
|
+
Underpost.cluster.ensureContainerStorageContexts();
|
|
1819
|
+
enforceSELinux(['/var/lib/kubelet', '/var/lib/containerd']);
|
|
1711
1820
|
|
|
1712
1821
|
logger.info('Phase 3/7: Stopping host kubelet and container runtimes (kubeadm-scope only)...');
|
|
1713
1822
|
shellExec(`if systemctl is-active --quiet kubelet; then sudo systemctl stop kubelet; fi`);
|
|
@@ -1909,7 +2018,7 @@ EOF`);
|
|
|
1909
2018
|
|
|
1910
2019
|
// SOPS and Age for Git-native encrypted secret manifests. Owned by UnderpostSecret so the
|
|
1911
2020
|
// same idempotent install backs `underpost secret --install-tools`.
|
|
1912
|
-
Underpost.secret.
|
|
2021
|
+
Underpost.secret.installTooling();
|
|
1913
2022
|
|
|
1914
2023
|
// Install snap
|
|
1915
2024
|
shellExec(`sudo yum install -y snapd`);
|
|
@@ -1981,10 +2090,8 @@ EOF`);
|
|
|
1981
2090
|
shellExec(`sudo rm -f /etc/sysctl.d/99-k8s-ipforward.conf`);
|
|
1982
2091
|
shellExec(`sudo rm -f /etc/sysctl.d/99-k8s.conf`);
|
|
1983
2092
|
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
// shellExec(`sudo setenforce 1`);
|
|
1987
|
-
// shellExec(`sudo sed -i 's/^SELINUX=permissive$/SELINUX=enforcing/' /etc/selinux/config`);
|
|
2093
|
+
console.log('Keeping SELinux in enforcing mode...');
|
|
2094
|
+
enforceSELinux();
|
|
1988
2095
|
|
|
1989
2096
|
console.log('Uninstall process completed.');
|
|
1990
2097
|
},
|