Compare commits

..
635 Commits
Author SHA1 Message Date
mbecker20 4aebd5ed92 fix confirm update showing entries which have not changed 2026-03-15 16:44:51 -07:00
mbecker20 a9352ad90b improve deployment network, restart, termination signal config 2026-03-15 15:26:47 -07:00
mbecker20 37bd221609 improve procedure config UI including run stack service 2026-03-15 15:20:26 -07:00
mbecker20 bf5975bb93 fix repo Links config 2026-03-15 01:36:18 -07:00
mbecker20 d7706a32c1 Fix Pull repo 2026-03-14 17:34:35 -07:00
mbecker20 dea9c49772 add missing Repo header Info 2026-03-14 17:15:12 -07:00
mbecker20 95666e69d8 sidebar more compact 2026-03-13 04:17:20 -07:00
mbecker20 cbc008fc89 improve tabs 2026-03-13 04:02:19 -07:00
mbecker20 445fa42a01 improve batch execs 2026-03-13 03:05:19 -07:00
mbecker20 2c2b0eda8f better api key create 2026-03-13 02:25:06 -07:00
mbecker20 15eefa3385 Fix api key modal too thin 2026-03-13 01:49:20 -07:00
mbecker20 cb9bc80346 confirm modal better responsiveness 2026-03-13 01:36:40 -07:00
mbecker20 8c682c091f better responsive confirm save width 2026-03-13 01:17:23 -07:00
mbecker20 ca021a3979 km cli needs to install crypto provider for tls ws 2026-03-10 16:24:51 -07:00
mbecker20 1480c3b020 better maxheight for mobile friendly tabs 2026-03-09 03:13:40 -07:00
mbecker20 42f452fdda rename resource invalidates 2026-03-08 22:38:41 -07:00
mbecker20 8ded07dfe5 improve mobile friendly tabs width, and onboardng key copy 2026-03-08 21:53:00 -07:00
mbecker20 d51c1cb1e7 fix init admin user 2026-03-08 07:48:20 -07:00
mbecker20 b5f184b286 proper base64url decode 2026-03-05 11:37:15 -08:00
mbecker20 294ef20019 deploy 2.0.0-dev-124 2026-03-05 11:28:54 -08:00
mbecker20 3efcaa0740 confirm action / save modals don't need ConfirmButton 2026-03-05 11:06:03 -08:00
mbecker20 b5b680dd1d Deploy / DeployStack updates invalidate corresponding list query 2026-03-05 10:40:19 -08:00
mbecker20 bf5ac8b6ac deploy 2.0.0-dev-123 2026-03-05 10:32:39 -08:00
mbecker20 dcccc878c8 mogh auth 1.2.11 2026-03-05 10:27:37 -08:00
mbecker20 1c87fba8f5 mogh auth server 1.2.10 2026-03-05 10:04:25 -08:00
mbecker20 2fc35b3c2d debug level core <> periphery auth identifiers logs 2026-03-05 00:10:30 -08:00
mbecker20 2012fd1dd9 deploy 2.0.0-dev-122 2026-03-04 19:37:13 -08:00
mbecker20 550c0339d6 read request are trace 2026-03-04 19:36:34 -08:00
mbecker20 50cf2f2d50 fmt 2026-03-04 16:31:13 -08:00
mbecker20 b223fefec6 notification green contents written success 2026-03-04 16:19:44 -08:00
mbecker20 7fe56f72ae setters use maps instead of mutations 2026-03-04 16:14:57 -08:00
mbecker20 0a9bc397ca config sidebar save 2026-03-04 15:58:09 -08:00
mbecker20 a03fceba7f thinner topbar 2026-03-04 10:46:45 -08:00
mbecker20 1bf1574c2a rename for clarity 2026-03-03 12:40:25 -08:00
mbecker20 83d90e0a16 improve disk usage hover card styling 2026-03-02 20:39:50 -08:00
mbecker20 304ffbf01d Add hoverable disk info 2026-03-02 20:32:34 -08:00
mbecker20 07787d6fa1 "never" -> "Never" 2026-03-02 19:59:30 -08:00
mbecker20 5d04142a99 fix sidebar margin right 2026-02-27 14:21:15 -08:00
mbecker20 aecba3be9f refine lg screen size view 2026-02-27 14:19:28 -08:00
mbecker20 4c4e5b62e0 taller data table and blue omnisearch 2026-02-27 13:10:46 -08:00
mbecker20 62f0ca9093 tweaks for lg size 2026-02-27 03:39:01 -08:00
mbecker20 3d43e2419f Update / Alert table filter selector formatted 2026-02-27 02:06:35 -08:00
mbecker20 d4081c2d6b single delete terminal 2026-02-26 18:52:39 -08:00
mbecker20 d397cb4ea4 fix terminal height - same as logs 2026-02-26 18:35:03 -08:00
mbecker20 0c96e24cd4 fix some wrapping stuff in tables and tag text disappear 2026-02-26 18:15:39 -08:00
mbecker20 1c90e768ef fix login github / google icon color 2026-02-26 16:55:01 -08:00
mbecker20 be73f20fd5 improve login styling 2026-02-26 16:47:15 -08:00
mbecker20 330178dbb8 standard api key modal size 2026-02-26 16:30:03 -08:00
mbecker20 c8c01307a0 improve profile delete styling 2026-02-26 16:27:42 -08:00
mbecker20 2e80adff2d deploy 2.0.0-dev-121 2026-02-26 16:13:04 -08:00
mbecker20 ef5a0982cb post link redirect should be to profile 2026-02-26 15:56:37 -08:00
mbecker20 9ffa40022d topbar user dropdown shows user avatar if available 2026-02-26 15:49:03 -08:00
mbecker20 15eaeab68d deploy 2.0.0-dev-120 2026-02-26 15:06:15 -08:00
mbecker20 89ea5ad5a4 stack and deployment state color include update available. Ensure server version mismatch color applied everywhere 2026-02-26 15:02:37 -08:00
mbecker20 c05dde3678 add close button to update / alert details drawer 2026-02-26 14:43:24 -08:00
mbecker20 a17a1005c7 smaller more consistent gaps 2026-02-26 14:38:36 -08:00
mbecker20 d13314eb98 stack stopped and deployment exited warning instead of critical 2026-02-26 14:25:31 -08:00
mbecker20 f41a61116a fix batch executions width 2026-02-26 14:24:58 -08:00
mbecker20 13fbcae105 edit swarm join command 2026-02-26 14:09:01 -08:00
mbecker20 71c437962f ensure section headers consistent spacing 2026-02-26 14:06:57 -08:00
mbecker20 e4147ccdaf rename ConfigSwitch onChange -> onCheckedChange 2026-02-26 13:41:51 -08:00
mbecker20 5089375211 improve tab styling 2026-02-26 13:38:07 -08:00
mbecker20 e489812af4 Fix config input issue 2026-02-26 13:37:32 -08:00
mbecker20 7373ff8d0e execution buttons disabled when loading 2026-02-26 12:53:58 -08:00
mbecker20 4e1cd32f3f Select Template 2026-02-25 19:31:28 -08:00
mbecker20 57211746f1 hide actions when none 2026-02-25 19:21:48 -08:00
mbecker20 5e153fb02b dashboard active styling 2026-02-25 19:21:22 -08:00
mbecker20 b28a413005 procedure / action webhook branch mobile style 2026-02-25 17:46:22 -08:00
mbecker20 691671abbd Load Average is first historical stat 2026-02-25 17:43:54 -08:00
mbecker20 504e81c2f7 improve login no auth configured and passkey pending 2026-02-25 17:36:02 -08:00
mbecker20 0a479a0f4a bump chef rust version 2026-02-25 16:08:55 -08:00
mbecker20 6a05779ceb deploy 2.0.0-dev-118 2026-02-25 16:07:05 -08:00
mbecker20 acd27ba058 bump rust version to 1.93.1 and dep versions 2026-02-25 16:06:37 -08:00
Maxwell BeckerandGitHub 96c4ae9fc5 2.0.0 UI (#1220)
* new ui using mantine

* resources page

* prog on resource page

* resources and resource layouts

* confirm button and modal

* tweaks

* update details

* topbar updates

* add skeletons for resource implementations

* add resource tables

* add tags to recents cards

* resource page table scrolling

* table component + tags filter

* export toml

* New Resource button

* Fix update details capture closing

* tweaks

* omni search

* refine config

* config tweaks

* implement more configs / resource selector

* add profile page

* provider / account selectors

* container table page

* build config

* deployment config

* fix deployment build version selector

* fix secrets selector

* resource sync config

* mobile topbar and updates

* update details fz sm

* stack config

* terminals page

* create terminal in prog

* create terminal menu

* finish create terminal menu

* terminal pages working

* stack tabs / info

* add executions

* add server header info

* confirm pubkey modal

* improve resource header styling

* FileSource component

* stack service table, move icons.ts

* basic procedure config

* tweak procedure config

* container / image pages

* network / volume pages

* clean up docker resource pages

*  basic log / terminal ui

* reusable log section

* styling

* clean up resource components

* delete in resource header

* log auto select stderr

* fix some bgs

* stack logs with service selector

* stack terminals

* add deployment executions

* use correct icon

* useResource hooks

* build info

* build info

* tweaks

* server tabs

* fix terminal section target

* prog on server tabs

* server stats

* light theme

* start on historical stats

* stack service page

* resource sync tabs

* sync tabs

* more topbar icons

* add settings basic

* add topbar alerts

* tweak stream selector behavior

* tweak alert icon topbar

* improve styling smaller screen

* schedules page and other progress

* onboarding keys

* improve schedule page descriptions

* improve update notifications

* schedule timezone selector

* tag color selector

* finish settings / providers

* use shared-text-update component so settings tables aren't janky

* updates page

* refine updates page

* alert page

* standardize borders

* theme and swarm

* swarm tabs

* swarm node page

* swarm config page

* swarm pages

* swarm task and secret pages

* swarm stack page

* fix stack log service selector in swarm mode

* standard inspect section

* swarm inspect tab

* server and swarm resources tab

* add disable confirm dialog (modal) option for executions

* stack update available indicator

* deployment update available

* add template switch to resource headers

* ResourceHeader + rename

* set editing name onclick

* repo tabs

* server stats table

* refine a bit

* refine deployment / stack header info

* show server stats dashboard. dashboard tables

* action last run in config

* SettingsUsers page

* user page etc

* manage api key

* user base permissions

* color the table multi select

* user group page

* UserAddUserGroup

* active includes deployments / stacks

* improve small screen view

* fix docker pages execution showing

* clean up

* rename frontend to UI

* align profile page styling

* config maintenance windows

* finish maintenance windows

* builder config

* add batch execute dropdown / confirm menu

* batch execute styling

* deploy 2.0.0-dev-117

* improve stats card light theme

* add update page

* improve mobile

* terminal group nowrap

* mobile improvements

* allow unused again

* improve mobile font sizing

* improve mobile updates / alerts

* mobile tabs

* alert page

* add server version mismatch color

* new resource, clearable selector

* Fix build show info tab

* copy resources

* keyboard shortcuts

* server resource header version mismatch

* fix type errors

* container page server multi select

* confirm button clear timeout

* hash compare force uses first 8 for short hash

* fix log height

* copy webhooks

* responsive tweaks

* add icons to server stat sections

* add historical server stats charts

* server stat current card shows usage numbers

* refine current stats more

* fix shortcuts interfering with monaco brave

* clean up unused

* remove v1 frontend
2026-02-25 15:28:23 -08:00
mbecker20 5c99958cba only send auto updated alert after verifying the deploy was successful 2026-02-15 18:38:01 -08:00
mbecker20 7288f067c5 deploy 2.0.0-dev-116 2026-02-11 10:20:39 -08:00
mbecker20 5d0f7de9fb Stack check for update prefers check against deployed service image 2026-02-11 10:20:09 -08:00
mbecker20 4129abcfd0 add new config value to example config 2026-01-27 23:26:44 -08:00
mbecker20 4275e903eb deploy 2.0.0-dev-115 2026-01-27 23:19:49 -08:00
mbecker20 c57c321cbb configure session allow cross site 2026-01-27 23:19:20 -08:00
mbecker20 9a7d49b35e bump mogh server and auth 2026-01-27 22:51:05 -08:00
mbecker20 d6aaef24cd bump rust to 1.93.0 2026-01-27 13:42:20 -08:00
mbecker20 3dce84c1f5 deploy 2.0.0-dev-114 2026-01-27 12:58:57 -08:00
mbecker20 8b16f97caf check update available against all digests for image 2026-01-27 12:58:32 -08:00
mbecker20 c98a809db4 serve static ui index.html with ETag / no-cache 2026-01-25 12:36:40 -08:00
mbecker20 c066b4fe16 mogh_server = "1.2.0" 2026-01-25 11:26:17 -08:00
mbecker20 b54fa235bc dev-113 2026-01-24 12:48:38 -08:00
mbecker20 05fd1aba2c batch check for updates, add check to table multi select actions 2026-01-24 12:48:13 -08:00
mbecker20 1a5290e124 cleanup 2026-01-24 11:33:49 -08:00
mbecker20 538e11ef3b dev 112 2026-01-24 11:33:22 -08:00
mbecker20 9208e9bf86 skip auto update for images with pinned digest 2026-01-24 11:30:41 -08:00
mbecker20 31640e3df8 fix require to import 2026-01-24 01:06:15 -08:00
mbecker20 42751d1b90 fix tailwind config module 2026-01-24 01:04:31 -08:00
mbecker20 673ab5c17d bump node version in all the dockerfiles 2026-01-24 01:01:05 -08:00
mbecker20 ad00f38758 bump frontend node version 2026-01-24 00:59:42 -08:00
mbecker20 b2459b5a64 align dashboard icon with sidebar 2026-01-24 00:58:23 -08:00
mbecker20 5923dd0e22 use mogh auth for passkey conversion 2026-01-24 00:45:32 -08:00
mbecker20 51294edd73 bump ts types and fix SwarmConfig type name conflict 2026-01-23 20:26:43 -08:00
mbecker20 baf77bf701 add api docs link 2026-01-23 14:59:22 -08:00
mbecker20 ddd99dc85d deploy 2.0.0-dev-111 2026-01-23 14:39:36 -08:00
mbecker20 a4c902282d improve swarm service / stack state inference 2026-01-23 14:39:00 -08:00
mbecker20 d7a2d4aadc clean up dangling action api keys on startup 2026-01-23 11:37:50 -08:00
mbecker20 c930468811 fix Action import from terminal 2026-01-23 03:11:47 -08:00
mbecker20 27efc81451 stack level terminal page 2026-01-23 03:07:57 -08:00
mbecker20 e44bd324f7 finish version upgrades page, and use prism theme oneLight and oneDark 2026-01-23 02:10:16 -08:00
mbecker20 b64c7e7289 deploy 2.0.0-dev-110 2026-01-23 01:10:32 -08:00
mbecker20 5c1a17fc91 improve config styling a bit more 2026-01-23 01:10:06 -08:00
mbecker20 50c3d77aed improve config quick links styling 2026-01-23 00:50:51 -08:00
mbecker20 bba1e3ae0c typegen 2026-01-23 00:24:27 -08:00
mbecker20 fc26fede66 add back legacy Action "exec" method calling convention 2026-01-23 00:23:54 -08:00
mbecker20 9cee723a1a deploy 2.0.0-dev-109 2026-01-22 19:12:55 -08:00
mbecker20 b922e86d29 deploy 2.0.0-dev-108 2026-01-22 18:38:12 -08:00
mbecker20 85dd3c0fe9 cache latest image digests and use this for image update alerting / auto update 2026-01-22 18:37:43 -08:00
mbecker20 4e3ecf7e6c clean up 2026-01-21 03:38:48 -08:00
mbecker20 18ffe635c8 remove user api, mogh auth handles api keys 2026-01-21 02:24:21 -08:00
mbecker20 8758c9ff8b gen types 2026-01-20 03:08:43 -08:00
mbecker20 5da48ece82 fmt and bump mogh auth 2026-01-20 02:58:45 -08:00
mbecker20 9a48edc43f add the write openapi definitions 2026-01-19 23:49:12 -08:00
mbecker20 93430f6dc3 more write openapi 2026-01-19 23:34:18 -08:00
mbecker20 d893ae9241 most of write openapi 2026-01-19 23:02:48 -08:00
mbecker20 24ed3cfcb1 server / stack exec openapi 2026-01-19 22:18:41 -08:00
mbecker20 36ee7ed72e most of execute openapi 2026-01-19 22:10:16 -08:00
mbecker20 5895fb843e modularize openapi structs 2026-01-19 20:50:08 -08:00
mbecker20 98f53020fb add most basic read apis 2026-01-19 19:33:18 -08:00
mbecker20 1d10873e77 improve toml comment 2026-01-19 18:03:36 -08:00
mbecker20 f5ee42029f review / fix some openapi definitions 2026-01-19 17:57:59 -08:00
mbecker20 525402f6f2 add openapi definitions to most read apis 2026-01-19 17:42:04 -08:00
mbecker20 9f877cc188 move openapi definition into client lib under feature gate 2026-01-19 15:41:38 -08:00
mbecker20 69d6b8e6ec remove the patch 2026-01-19 01:24:50 -08:00
mbecker20 526bcc1907 deploy 2.0.0-dev-107 2026-01-19 01:22:59 -08:00
mbecker20 f7badf5579 define set logging module targets so log level becomes useful 2026-01-19 01:18:50 -08:00
mbecker20 86fd7a155d try deno npm: style dep 2026-01-19 00:25:11 -08:00
mbecker20 628afc3baa deploy 2.0.0-dev-106 2026-01-18 23:37:19 -08:00
mbecker20 04f944fcc2 use full mogh dep names 2026-01-18 23:36:52 -08:00
mbecker20 f39447b513 move to mogh_resolver 2026-01-18 22:56:13 -08:00
mbecker20 612acd02ad remove derive_variants, strum's "EnumDiscriminants" covers it 2026-01-18 22:30:54 -08:00
mbecker20 90557ae514 fix cors options 2026-01-18 19:35:21 -08:00
mbecker20 0c292f7157 deploy 2.0.0-dev-105 2026-01-18 18:16:32 -08:00
mbecker20 673ee05fe9 tmp back to 104 2026-01-18 18:16:30 -08:00
mbecker20 94b5bd6660 use public ts mogh auth client 2026-01-18 16:52:49 -08:00
mbecker20 be40110004 use mogh_auth embedded api 2026-01-18 16:31:45 -08:00
mbecker20 2d4a34b820 move to mogh deps 2026-01-17 23:22:58 -08:00
mbecker20 2feb08725b fix_ws_address adds 'ws://' to direct IPs instead of 'wss://' which won't work 2026-01-06 10:14:10 -08:00
mbecker20 161393805f refactor openapi -> utoipa feature 2026-01-05 12:45:52 -08:00
mbecker20 f4b692080d remove user_id from jwt response -- its encoded transparently in jwt 2026-01-05 12:38:17 -08:00
mbecker20 e1c6c866a2 docs.html 2025-12-30 14:33:34 -08:00
mbecker20 7106328390 add authentication to openapi docs 2025-12-30 14:32:29 -08:00
mbecker20 338acba5c6 start utoipa openapi support 2025-12-30 13:02:27 -08:00
mbecker20 dcf6f2431e tweak 2025-12-29 22:31:19 -08:00
mbecker20 58b520e651 improve OIDC client init to only as needed 2025-12-29 11:22:49 -08:00
mbecker20 8be0846733 bump axum-extra 2025-12-28 10:15:00 -08:00
mbecker20 5b651f2527 tweak 2025-12-27 15:11:13 -08:00
mbecker20 026ba4fca8 use User constructor 2025-12-27 02:14:16 -08:00
mbecker20 4bca07d4ba update deps 2025-12-27 01:47:54 -08:00
mbecker20 9091f14711 update password refetch user 2025-12-26 02:07:44 -08:00
mbecker20 8b78bb838e fix alert error messages - reference correct alerter type 2025-12-26 01:57:23 -08:00
mbecker20 d384f7ca78 update to v2 docs 2025-12-24 00:46:07 -08:00
mbecker20 48475b55d5 Periphery GetLatestImageDigest + RollbackSwarmService 2025-12-21 00:58:57 -08:00
mbecker20 64d7959c75 bump deps 2025-12-21 00:57:46 -08:00
mbecker20 d1856c2325 deploy 2.0.0-dev-104 2025-12-20 12:30:03 -08:00
mbecker20 61b7fcdb0a onboarding key fix_existing_servers / priviledged 2025-12-20 12:29:24 -08:00
mbecker20 2693f13829 deploy 2.0.0-dev-103 2025-12-19 12:22:51 -08:00
mbecker20 7fea06861b improve swarm node page 2025-12-19 12:22:20 -08:00
mbecker20 abd155193a join swarm command 2025-12-19 12:10:25 -08:00
mbecker20 7a4de0343d config / secret has service and task tables 2025-12-18 15:30:37 -08:00
mbecker20 c638e3876e deploy 2.0.0-dev-102 2025-12-18 14:52:04 -08:00
mbecker20 fc4ea40b9c task links to configs / secrets 2025-12-18 13:43:16 -08:00
mbecker20 62b84328d8 link attached configs / secrets in status 2025-12-18 13:29:38 -08:00
mbecker20 a5ee0de394 tweaks 2025-12-18 02:32:08 -08:00
mbecker20 bf0ab26d22 improve swarm deployments 2025-12-18 01:36:31 -08:00
mbecker20 0dd2ade574 fix config / secret rotation 2025-12-17 12:59:08 -08:00
mbecker20 f0172c2721 move inspect to swarm tabs top level 2025-12-15 22:55:37 -08:00
mbecker20 363d330868 similar but inherently limited swarm secret management 2025-12-15 22:49:45 -08:00
mbecker20 2843711796 swarm config create / edit / delete 2025-12-15 17:04:03 -08:00
mbecker20 4f044ccde8 Service aware config rotation 2025-12-14 14:42:53 -08:00
mbecker20 9be21b54bd fix deployment / stack toml when swarm attached 2025-12-14 00:06:12 -08:00
mbecker20 057ecbcfef add load passkey frontend indicator screen 2025-12-13 23:43:13 -08:00
mbecker20 e91d63f262 deploy 2.0.0-dev-101 2025-12-13 18:37:39 -08:00
mbecker20 3b799edb30 improve the swarm tables 2025-12-13 18:37:14 -08:00
mbecker20 41c7faf48d add resources tab to swarms 2025-12-13 11:21:24 -08:00
mbecker20 e1d745aee0 status colors for swarm resources 2025-12-13 11:12:26 -08:00
mbecker20 01df3add41 Fix task state check 2025-12-13 01:01:22 -08:00
mbecker20 577973841b better api / onboarding key shape 2025-12-12 23:59:42 -08:00
mbecker20 3e5311f413 user profile mobile 2025-12-12 18:30:00 -08:00
mbecker20 46e99783f2 deploy 2.0.0-dev-100 2025-12-12 18:00:28 -08:00
mbecker20 a6590804a7 skip 2fa for third party logins 2025-12-12 18:00:03 -08:00
mbecker20 bd752b7c72 deploy 2.0.0-dev-99 2025-12-12 17:08:45 -08:00
mbecker20 de83b3a5a0 user link multiple primary login methods 2025-12-12 17:08:03 -08:00
mbecker20 c91963fdbb fix table_borders in cli config 2025-12-11 01:03:43 -08:00
mbecker20andMaxwell Becker 973aae82fd improve 2fa ux 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker c3626e0949 cli support clearing users 2fa methods 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 5ba96a58e4 binaries use bookworm 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker c6a1cf2867 deploy 2.0.0-dev-98 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker bd39aec1fd support passkey 2fa 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 079895a64d fix imports in permissions module 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 5af1c646a5 deploy 2.0.0-dev-97 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 747e03b5c4 Fix incorrect permissions query due to resource RBAC update query filter. Align logic with Alert resource RBAC filter. Re #1011 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 78c6761eca add swarm specific permission config 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker a949891d26 apply login credential lock (for demo users) to 2FA 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 9d256e420a improve totp enrollment dialog closing, fix redirect away from /login when using two factor 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker b460504b5a deploy 2.0.0-dev-96 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker e60316f2c1 TOTP 2FA with third party logins 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker c45e3eab16 deploy 2.0.0-dev-95 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker ec12f63272 double recovery code length 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker f2f77b4eb6 totp unenroll 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 677a65f8b0 local login TOTP 2fa support 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker a5a1090177 deploy 2.0.0-dev-94 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker ccb18fc88a fix server auto rotate keys default for sync 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 0ca583fe5e deploy Deployments to swarms 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 4013cd3f1e dev-93 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 5854a7de99 Deployment as swarm service 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 8c52232852 swarm stack deploy and destroy 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker fb9e5b1860 ts types 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker a1c00a8d32 implement the swarm resource associations for stack / deployment targeting swarm 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 775f5bf703 more stack / deployment deploy on swarm 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker effe737ffe periphery swarm stack deploy 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 436959cbcd docker service create 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 9957287443 remove buttons for swarm resources 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker c77de8683c swarm stack logs and Remove 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 087bcb7044 improve swarm stack page 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 0dfcaaf06a add swarm remove executions to procedure UI excluded types 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 6624a821a5 deploy 2.0.0-dev-92 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker c32af84e02 remove swarm entities apis 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 9d9add7b34 Uppercase server docker ops logs 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker db099dbe1e improve config with tall linkto sidebars 2025-12-10 21:39:56 -08:00
mbecker20andMaxwell Becker 413a8abc84 default rate limit attempts to 5 per 15 sec 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 36243e83c1 KL-4 must fallback to axum extracted IP for cases not using reverse proxy 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 076113a1de KL-4: Align log consistency 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker c998edaa73 KL-1: core_allowed_origins example config should be empty 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 4de32b08e5 KL-8 modify action state internal behavior comments 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 262999c58f KL-7 Improve typescript safety: disable allow any 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker be57f52e6e KL-6 Improve error handling in startup paths 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 3591789316 KL-6 Improve alert cache error handling 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 83f2bd65fe KL-6 Remove monitoring_interval panic 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 5e5cdb81f8 KL-5 ext: Tighten the skew tolerance re https://curity.io/resources/learn/jwt-best-practices/?utm_source=chatgpt.com#9-dealing-with-time-based-claims 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 721038a1df KL-5 JWT clock skew tolerance 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 7de98ad519 cargo clippy and bump to rust 1.91.1 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 8c62f2b5c5 KL-4 ext 2: Improve rate limiting / attempt state conveyance with response 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 85787781ee KL-4 ext: Remove brute-force compromising credential failure reasons to improve auth rate limiter effectiveness 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 25e2d4e926 KL-4 Authentication rate limiting 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker b9b8d45cbc KL-2/3 Input validation for local auth, service users, api keys, and variables 2025-12-10 21:34:30 -08:00
mbecker20andMaxwell Becker 2f2e863dbf KL-1 Configurable CORS support 2025-12-10 21:34:30 -08:00
mbecker20 a3a01f1625 add schemas for swarm commands 2025-11-27 23:47:22 -08:00
mbecker20 aec8fa2bf1 task view page with logs 2025-11-23 23:45:28 -08:00
mbecker20 7ff2dba82f swarm service page with logs 2025-11-23 12:48:23 -08:00
mbecker20 9c86b2d239 swarm service logs api 2025-11-23 00:43:59 -08:00
mbecker20 b1fec7c663 docker swarm stack read apis 2025-11-22 16:05:51 -08:00
mbecker20 8341c6b802 sward resources use list items 2025-11-22 02:41:49 -08:00
mbecker20 73285c4374 move swarm to list item + inspect on pages 2025-11-21 14:34:20 -08:00
mbecker20 32d48cdb02 swarm configs view 2025-11-21 13:21:14 -08:00
mbecker20 8e081fd09c swarm config apis 2025-11-21 12:55:37 -08:00
mbecker20 04531f1dea Explore swarm info 2025-11-20 13:00:29 -08:00
mbecker20 80f439d472 basic swarm 2025-11-19 18:02:50 -08:00
mbecker20 d5e03d6d16 prog on swarm 2025-11-19 01:48:43 -08:00
mbecker20 a9f55bb8e6 fix Terminals permissions when no perm on Server 2025-11-17 15:44:14 -08:00
mbecker20 9e765f93f5 bump deps 2025-11-17 15:43:56 -08:00
mbecker20 b3aa8e906f add context to onboarding login error and error messages sent over the communication websocket in general 2025-11-17 13:23:44 -08:00
mbecker20 03fe442aa0 in prog 2025-11-17 12:59:08 -08:00
ChanningHeandGitHub d268009a6a validate compose_cmd_wrapper for required placeholder and add interpolation support (#977) 2025-11-12 10:09:15 -08:00
mbecker20 f0697e812a shift + N open new variable dialog 2025-11-11 14:22:56 -08:00
mbecker20 78766463d6 create variable Enter submit 2025-11-11 14:18:28 -08:00
mbecker20 0fa1edba2c deploy 2.0.0-dev-90 2025-11-11 14:13:55 -08:00
mbecker20 bbd968cac3 bump toml pretty with fix syncing procedure executions with multiline batch patterns 2025-11-11 14:13:25 -08:00
mbecker20 5f24fc1be3 deploy 2.0.0-dev-89 2025-11-11 00:44:49 -08:00
mbecker20 7ecd2b0b0b improve cmd wrapper with comment removal support 2025-11-11 00:43:54 -08:00
mbecker20 7bf44d2e04 fix some broken tabs 2025-11-11 00:35:24 -08:00
mbecker20 24e0672384 dashboard resets page title 2025-11-11 00:18:16 -08:00
mbecker20 04f081631f deploy 2.0.0-dev-88 2025-11-11 00:16:07 -08:00
mbecker20 b1af956b63 fix dashboard pie chart code splitting issue 2025-11-11 00:05:32 -08:00
mbecker20 370712b29f gen served client types 2025-11-11 00:05:02 -08:00
mbecker20 2b6c552964 canius lite update 2025-11-11 00:04:52 -08:00
mbecker20 434a1d8ea9 clippy lint 2025-11-11 00:04:39 -08:00
ChanningHeandGitHub 0b7f28360f Add optional command wrapper for Docker Compose in StackConfig (#973) 2025-11-10 23:59:09 -08:00
ChanningHeandGitHub 3c8ef0ab29 Add track option for Additional Env Files (#955) 2025-11-10 23:47:07 -08:00
mbecker20 930b2423c3 deploy 2.0.0-dev-87 2025-11-07 10:33:23 -08:00
mbecker20 546747b5f2 add timeout to dns ip resolve, only use ipv4 2025-11-07 10:32:55 -08:00
mbecker20 c6df866755 better aws builder config organization 2025-11-07 10:04:45 -08:00
mbecker20 ea5e684915 better useUserTargetPermissions 2025-11-06 22:18:31 -08:00
mbecker20 64db8933de RefreshBuildCache after build 2025-11-04 00:27:34 -08:00
mbecker20 7a5580de57 builder uppercase login 2025-11-04 00:06:46 -08:00
mbecker20 b1656bb174 log about enabling user linger 2025-11-03 10:29:50 -08:00
Badal SinghandGitHub 559ce103da Update setup-periphery.py (#958) 2025-11-03 09:57:49 -08:00
mbecker20 75e278a57b builder fix partial_default 2025-10-30 00:41:27 -07:00
mbecker20 430f3ddc34 fix omni search container double select on same name 2025-10-29 00:02:32 -07:00
mbecker20 6c30c202e9 add Terminals to omni search 2025-10-28 23:59:41 -07:00
mbecker20 c5401de1c5 tweak user level tab view 2025-10-28 11:42:29 -07:00
mbecker20 7a3d9e0ef6 tweak description 2025-10-28 00:32:39 -07:00
mbecker20 595e3ece42 deploy 2.0.0-dev-86 2025-10-27 21:05:13 -07:00
mbecker20 a3bc895755 fix terminal disconnect 2025-10-27 21:04:46 -07:00
mbecker20 3e3def03ec terminal init properly lexes init command 2025-10-27 21:01:15 -07:00
mbecker20 bc672d9649 deploy 2.0.0-dev-85 2025-10-27 20:01:18 -07:00
mbecker20 ea6dee4d51 clippy lint 2025-10-27 19:13:43 -07:00
mbecker20 b985f18c74 deploy 2.0.0-dev-84 2025-10-27 19:12:54 -07:00
mbecker20 45909b2f04 pid1 reaper doesn't work, init: true should be required in compose 2025-10-27 19:06:50 -07:00
mbecker20 2b5a54ce89 deploy 2.0.0-dev-83 2025-10-27 18:31:56 -07:00
mbecker20 a18f33b95e formalize the terminal message variants 2025-10-27 18:31:30 -07:00
mbecker20 f35b00ea95 bump clap dependency 2025-10-27 16:18:30 -07:00
mbecker20 70fab08520 clean up terminal modules 2025-10-27 16:17:20 -07:00
mbecker20 0331780a5f rename variables shell -> command 2025-10-27 11:08:57 -07:00
mbecker20 06cdfd2bbc Terminal -> Terminals tabs 2025-10-27 02:53:06 -07:00
mbecker20 1555202569 Create Terminal don't auto set request after changed 2025-10-27 02:42:06 -07:00
mbecker20 5139622aad deploy 2.0.0-dev-82 2025-10-27 02:28:48 -07:00
mbecker20 61ce2ee3db improve new terminal 2025-10-27 02:04:15 -07:00
mbecker20 3171c14f2b comment on spawn process reaper 2025-10-27 01:41:06 -07:00
mbecker20 521db748d8 deploy 2.0.0-dev-81 2025-10-27 01:27:42 -07:00
mbecker20 35bf224080 deploy 2.0.0-dev-80 2025-10-27 01:21:44 -07:00
mbecker20 e0b31cfe51 CreateTerminal only shows resources which are actually available to connect to 2025-10-27 00:44:56 -07:00
mbecker20 0a890078b0 deploy 2.0.0-dev-79 2025-10-27 00:38:08 -07:00
mbecker20 df97ced7a4 deploy 2.0.0-dev-78 2025-10-27 00:03:26 -07:00
mbecker20 d4e5e2e6d8 add execute_<>_terminal convenience methods 2025-10-26 23:35:17 -07:00
mbecker20 19aa60dcb5 deploy 2.0.0-dev-77 2025-10-26 23:21:15 -07:00
mbecker20 fc19c53e6f deploy 2.0.0-dev-76 2025-10-26 23:00:59 -07:00
mbecker20 4f0af960db Big Terminal refactor + most commands run directly / bypass 'sh -c "..."' 2025-10-26 23:00:35 -07:00
mbecker20 e2ec5258fb add "New" kb shortcut 2025-10-23 23:55:24 -07:00
mbecker20 49b6545a02 reorder cli command list 2025-10-23 23:53:10 -07:00
mbecker20 0aabaa9e62 deploy 2.0.0-dev-75 2025-10-23 12:23:10 -07:00
mbecker20 dc65986eab binaries still built with bullseye for compat, but final images use trixie 2025-10-23 12:22:50 -07:00
mbecker20 1d8f28437d km attach <CONTAINER> 2025-10-23 12:22:02 -07:00
mbecker20 c1502e89c2 deploy 2.0.0-dev-74 2025-10-23 11:51:40 -07:00
mbecker20 0bd15fc442 ResourceQuery.names supports names or ids 2025-10-23 11:23:37 -07:00
mbecker20 5a3621b02e km exec 2025-10-23 01:55:50 -07:00
mbecker20 38192e2dac deploy 2.0.0-dev-73 2025-10-23 00:56:15 -07:00
mbecker20 5d271d5547 use Ping timeout to handle reconnect if for some reason network cuts but ws doesn't receive Close 2025-10-23 00:55:51 -07:00
mbecker20 11fb67a35b ssh use cancel token so stdout.write_all isn't cancelled mid-write, which leads to undefined behavior 2025-10-23 00:14:17 -07:00
mbecker20 a80499dcc4 improve stack config files responsive 2025-10-22 19:02:30 -07:00
mbecker20 8c76b8487f alert responsive, better Server terminal disabled 2025-10-22 13:48:08 -07:00
mbecker20 2b32d9042a deploy 2.0.0-dev-72 2025-10-22 01:00:19 -07:00
mbecker20 dc48f1f2ca deploy 2.0.0-dev-71 2025-10-22 00:50:02 -07:00
mbecker20 8e7b7bdcf1 deploy 2.0.0-dev-70 2025-10-22 00:44:54 -07:00
mbecker20 f11d64f72e add 'init' param to make 'execute_terminal' in single call possible 2025-10-22 00:44:33 -07:00
mbecker20 2ffae85180 dashboard table section headers link to resources page 2025-10-22 00:03:12 -07:00
mbecker20 bd79d0f1e0 km ssh <SERVER> [COMMAND] -n [NAME] 2025-10-21 23:55:36 -07:00
mbecker20 e890b1f675 deploy 2.0.0-dev-69 2025-10-21 23:32:18 -07:00
mbecker20 3b7de25c30 Shift + X - Terminals, Shift + N - New (Resource, Terminal) 2025-10-21 16:11:27 -07:00
mbecker20 793bb99f31 nav to terminal on create 2025-10-21 16:00:50 -07:00
mbecker20 d465c9f273 deploy 2.0.0-dev-68 2025-10-21 15:51:38 -07:00
mbecker20 ce641a8974 terminal page 2025-10-21 15:51:18 -07:00
mbecker20 1b89ceb122 deploy 2.0.0-dev-67 2025-10-21 02:50:21 -07:00
mbecker20 2dbc011d26 remove unneeded log on client terminal disconnect 2025-10-21 02:33:19 -07:00
mbecker20 246da88ae1 deploy 2.0.0-dev-66 2025-10-21 02:29:12 -07:00
mbecker20 a8c16f64b1 km ssh 2025-10-21 02:28:42 -07:00
mbecker20 a5b711a348 stack tabs localstorage increment 2025-10-20 20:35:08 -07:00
mbecker20 9666e9ad83 Fix monitoring table with proper server version component 2025-10-20 03:01:07 -07:00
mbecker20 7479640c73 add hover information for mysterious server header icons 2025-10-20 02:53:18 -07:00
mbecker20 4823825035 give websocket indicator info on hover 2025-10-20 02:35:12 -07:00
mbecker20 23897a7acf clippy 2025-10-20 02:16:52 -07:00
mbecker20 20d5588b5c deploy 2.0.0-dev-65 2025-10-20 02:15:15 -07:00
mbecker20 f7e15ccde5 progress on terminals page 2025-10-20 02:14:51 -07:00
mbecker20 cf7623b1fc combine all resources / table view into dashboard 2025-10-20 01:40:27 -07:00
mbecker20 d3c464c05d start Terminals management page 2025-10-20 00:42:45 -07:00
mbecker20 5c9d416aa4 prog on docs update 2025-10-19 23:33:41 -07:00
mbecker20 aabcd88312 update connect-servers docs 2025-10-19 23:07:50 -07:00
mbecker20 9d2624c6bc clarify root directory in periphery config file 2025-10-19 23:07:19 -07:00
mbecker20 ee11fb0b6c clean up setup script 2025-10-19 23:07:02 -07:00
mbecker20 45adfbddd0 mounting custom CA 2025-10-19 23:06:48 -07:00
mbecker20 d26d035dc6 clean up docs intro 2025-10-19 22:03:17 -07:00
mbecker20 e673ba0adf deploy 2.0.0-dev-64 2025-10-19 21:48:15 -07:00
mbecker20 f876facfa7 improve git status message / failure propogation 2025-10-19 21:47:29 -07:00
mbecker20 3a47d57478 container class px-[1.2rem] 2025-10-19 20:31:40 -07:00
mbecker20 a707028277 responsive tweaks 2025-10-19 20:07:30 -07:00
mbecker20 0c6276c677 fix Resources / Containers mobile 2025-10-19 19:51:28 -07:00
mbecker20 fc9c6706f1 keep more descriptive settings header mobile 2025-10-19 13:24:44 -07:00
mbecker20 7674269ce9 fix user dropdown not showing username mobile 2025-10-19 13:11:34 -07:00
mbecker20 3b511c5adc improve server terminal mobile responsiveness 2025-10-19 13:00:30 -07:00
mbecker20 87221a10e9 fix mobile ContainerTerminal responsiveness 2025-10-19 12:56:11 -07:00
mbecker20 450cb6a148 fix stack config files mobile responsiveness 2025-10-19 12:46:51 -07:00
mbecker20 f252cefb21 responsive server docker tab 2025-10-19 12:37:26 -07:00
mbecker20 7855e9d688 run dkf 2025-10-19 12:30:59 -07:00
mbecker20 feb263c15f more type safe tabs 2025-10-19 12:27:55 -07:00
mbecker20 4f8d1c22cc rest of tabs also use mobile friendly 2025-10-19 12:11:11 -07:00
mbecker20 60bd47834e deploy 2.0.0-dev-63 2025-10-19 11:48:09 -07:00
mbecker20 4d632a6b61 improve resources mobile tabs responsiveness 2025-10-19 11:47:47 -07:00
mbecker20 381dd76723 deploy 2.0.0-dev-62 2025-10-19 01:37:10 -07:00
mbecker20 077e28a5fe fix ConfigList too wide on mobile 2025-10-19 01:36:50 -07:00
mbecker20 6b02aaed7d hide core pubkey copy if origin not https 2025-10-19 01:28:45 -07:00
mbecker20 e466944c05 improve mobile settings view 2025-10-19 01:24:41 -07:00
mbecker20 8ff94b7465 deploy 2.0.0-dev-61 2025-10-19 00:35:26 -07:00
mbecker20 b17df5ed7b show host public ip 2025-10-19 00:34:52 -07:00
mbecker20 207dc30206 cli is distroless, no shell / update-ca-certificates 2025-10-18 22:12:44 -07:00
mbecker20 c3eb386bdb fix copy entrypoint 2025-10-18 22:07:16 -07:00
mbecker20 4279e46892 deploy 2.0.0-dev-60 2025-10-18 12:59:19 -07:00
mbecker20 8d3d2fee12 use entrypoint scripts to make update-ca-certificates consistent when using custom CMD 2025-10-18 12:58:55 -07:00
mbecker20 1df36c4266 deploy 2.0.0-dev-59 2025-10-18 11:36:07 -07:00
mbecker20 36f7ad33c7 core and periphery images auto run update-ca-certificates on start, only need to mount in. 2025-10-18 11:35:45 -07:00
mbecker20 ec34b2c139 deploy 2.0.0-dev-58 2025-10-18 11:02:11 -07:00
mbecker20 d14c28d1f2 new otel instrumentation 2025-10-18 11:01:47 -07:00
mbecker20 68f7a0e9ce all info menu to top of settings 2025-10-18 00:45:59 -07:00
mbecker20 50f0376f0a Add Core title and public key to top of Settings 2025-10-18 00:01:41 -07:00
mbecker20 bbd53747ad fix km ps -h description 2025-10-17 17:17:18 -07:00
mbecker20 6a2adf1f83 tweak logs 2025-10-16 01:06:37 -07:00
mbecker20 128b15b94f deploy 2.0.0-dev-57 2025-10-16 00:59:46 -07:00
mbecker20 8d74b377b7 more otel refinements 2025-10-16 00:59:20 -07:00
mbecker20 d7e972e5c6 stack ui doesn't show project missing when deploying 2025-10-15 23:49:26 -07:00
mbecker20 e5cb4aac5a Fix: Webhook triggered checks linked repo branch for build, stack, sync 2025-10-15 18:06:43 -07:00
mbecker20 d0f62f8326 rework tracing events / improve opentelemetry output 2025-10-15 01:41:18 -07:00
mbecker20 47c4091a4b onboarding key uses recognizable key 2025-10-14 16:57:35 -07:00
mbecker20 973480e2b3 remove all the unnecessary instrument debug 2025-10-14 00:33:53 -07:00
mbecker20 b9e1cc87d2 remove instrument from validate_cancel_repo_build 2025-10-13 23:52:55 -07:00
mbecker20 05d20c8603 deploy 2.0.0-dev-56 2025-10-13 22:05:07 -07:00
mbecker20 fe2d68a001 fix config loading 2025-10-13 22:04:42 -07:00
mbecker20 26fd5b2a6d deploy 2.0.0-dev-55 2025-10-13 20:30:40 -07:00
mbecker20 76457bcb61 apply env / shell interpolation as *final* config loading stage, to include env vars. 2025-10-13 20:26:13 -07:00
mbecker20 ebd2c2238d bump deps 2025-10-13 19:51:05 -07:00
mbecker20 b7fc1bef7b refine default env 2025-10-13 13:53:12 -07:00
mbecker20 50b9f2e1bf deploy 2.0.0-dev-54 2025-10-13 13:06:23 -07:00
mbecker20 41ce86f6ab deploy 2.0.0-dev-53 2025-10-12 20:00:47 -07:00
mbecker20 7a21c01e52 tweak 2025-10-12 19:59:09 -07:00
mbecker20 e63e282510 small clean up 2025-10-12 19:56:15 -07:00
mbecker20 5456b36c18 deploy 2.0.0-dev-52 2025-10-12 13:55:39 -07:00
mbecker20 fcfb58a7e9 periphery with server disabled can initialize core public key file 2025-10-12 13:55:15 -07:00
mbecker20 2203004a74 move periphery in memory state to state.rs 2025-10-12 13:15:52 -07:00
mbecker20 996fb49823 periphery server_enabled /version route 2025-10-12 12:56:29 -07:00
mbecker20 35d22c77a2 Core add non authed /version route 2025-10-12 12:55:14 -07:00
mbecker20 44ab89600f Simpllify Option + Result into one encoding layer 2025-10-12 03:24:00 -07:00
mbecker20 0900e48cb8 ntfy / pushover url interpolation 2025-10-12 01:34:07 -07:00
mbecker20 c530a46a27 deploy 2.0.0-dev-51 2025-10-12 01:09:35 -07:00
mbecker20 f69c8db3ea pass through whether Periphery docker daemon connection is ok 2025-10-12 01:08:45 -07:00
mbecker20 48f2f651e1 periphery runs with logs if couldn't connect to docker daemon 2025-10-12 01:05:20 -07:00
mbecker20 bdb5b4185e rename some websocket fields 2025-10-12 00:28:55 -07:00
mbecker20 42a7b8c19b move connection queries to periphery_client 2025-10-12 00:08:59 -07:00
mbecker20 ded17e4840 more encoding refine 2025-10-12 00:05:16 -07:00
mbecker20 80fb1e6889 more on encoding 2025-10-11 14:11:07 -07:00
mbecker20 1dc861f538 fix periphery keys init when config.private_key is not explicitly defined. 2025-10-11 12:00:29 -07:00
mbecker20 3da63395fd fix EncodedOption docs 2025-10-10 00:32:05 -07:00
mbecker20 c40cbc4d77 deploy 2.0.0-dev-50 2025-10-09 23:40:42 -07:00
mbecker20 05e352e88c attach working 2025-10-09 23:28:27 -07:00
mbecker20 5884c09fb8 fix fe 2025-10-09 22:05:36 -07:00
mbecker20 f8add38043 backend for container attach 2025-10-09 21:53:26 -07:00
mbecker20 501f734e8b deploy 2.0.0-dev-49 2025-10-09 20:13:17 -07:00
mbecker20 de62732ac8 bump jwt lib 2025-10-09 20:12:51 -07:00
mbecker20 bfa61058cd remove github only managed repo webhooks feature. Not well implemented or documented, also provider specific. 2025-10-09 20:06:06 -07:00
mbecker20 72ca6d9910 deploy 2.0.0-dev-48 2025-10-09 19:36:47 -07:00
mbecker20 4d1ac32ad3 clippy 2025-10-09 18:24:50 -07:00
mbecker20 927e5959fa move encoded message schemas between core / periphery into periphery_client 2025-10-09 18:23:44 -07:00
mbecker20 37ccc6e1ef isolate encoding out of transport 2025-10-09 18:11:49 -07:00
mbecker20 deaa8754f3 slowly better ergonomics 2025-10-09 17:29:05 -07:00
mbecker20 dd8ac67c72 clippy and fmt 2025-10-09 16:26:06 -07:00
mbecker20 be4457c9cf deploy 2.0.0-dev-47 2025-10-09 15:41:06 -07:00
mbecker20 1868421815 strictly typed transport bytes encoding 2025-10-09 15:40:42 -07:00
mbecker20 366f7a12b4 Enumerated transport message types 2025-10-08 20:36:16 -07:00
mbecker20 75119370df standardize key rotation with wrapper 2025-10-08 17:45:45 -07:00
mbecker20 9e85b9d4c8 deploy 2.0.0-dev-46 2025-10-08 03:59:22 -07:00
mbecker20 8afbbf23dc deploy 2.0.0-dev-45 2025-10-08 02:48:24 -07:00
mbecker20 770a1116a1 fix: RotateCoreKeys also needs to store the new keys in mem 2025-10-08 02:48:01 -07:00
mbecker20 0b4aebbc24 periphery refresh panics if server_enabled, and core public key fails to parse. 2025-10-08 02:32:52 -07:00
mbecker20 f1696e26e4 deploy 2.0.0-dev-44 2025-10-08 02:11:38 -07:00
mbecker20 1a7b682301 RotateCoreKeys api 2025-10-08 02:11:17 -07:00
mbecker20 b0110b05aa deploy 2.0.0-dev-43 2025-10-08 00:02:34 -07:00
mbecker20 561b490f26 write files potentially containing secrets as 0600 2025-10-07 23:59:53 -07:00
mbecker20 cac1f0b42e align server standard and monitoring tables 2025-10-07 19:41:57 -07:00
mbecker20 28886fb304 fix typos 2025-10-07 14:32:00 -07:00
mbecker20 fb84d4cf7d deploy 2.0.0-dev-42 2025-10-07 01:59:04 -07:00
mbecker20 31e9624556 auto_rotate_keys config 2025-10-07 01:58:13 -07:00
mbecker20 3864bb7115 onboarding key expiry view 2025-10-07 01:16:28 -07:00
mbecker20 cea8601246 remove deleted server from onboarding key copy server 2025-10-07 00:44:36 -07:00
mbecker20 a546364bf3 deploy 2.0.0-dev-41 2025-10-07 00:29:33 -07:00
mbecker20 c8c62ea562 core public keys improve refresh 2025-10-07 00:27:47 -07:00
mbecker20 845e8780c7 improve server stats UI 2025-10-06 23:45:26 -07:00
mbecker20 db60347566 deploy 2.0.0-dev-40 2025-10-06 22:12:40 -07:00
mbecker20 c3ea0239d6 fix passkey support 2025-10-06 22:12:15 -07:00
mbecker20 e9d13449bf improve ws trait ergonomics 2025-10-06 20:02:06 -07:00
mbecker20 2daa92a639 working with safer transport message api 2025-10-06 19:16:03 -07:00
mbecker20 6473080078 deploy 2.0.0-dev-39 2025-10-06 03:14:15 -07:00
mbecker20 d3957f65dc schedule alert send before not after 2025-10-06 03:13:48 -07:00
mbecker20 cb34969f1e move skip label to be built into images 2025-10-06 03:07:11 -07:00
mbecker20 55a0a8cd05 deploy 2.0.0-dev-38 2025-10-06 02:38:42 -07:00
mbecker20 89f08372c6 CloseAlert 2025-10-06 02:38:16 -07:00
mbecker20 6a3ce2d426 config log some errors 2025-10-06 02:13:36 -07:00
mbecker20 4928378d46 fmt 2025-10-06 02:03:03 -07:00
mbecker20 eea222cfba simplify periphery config by removing option 2025-10-06 02:02:31 -07:00
mbecker20 6e9cc2dc77 deploy 2.0.0-dev-37 2025-10-06 01:40:24 -07:00
mbecker20 55d45084d0 comment 2025-10-06 01:40:00 -07:00
mbecker20 9657a44049 Improve config toml / yaml / json interpolation support 2025-10-06 01:38:48 -07:00
mbecker20 51fa9ae3c2 update setup script readme 2025-10-06 00:29:35 -07:00
mbecker20 5fd256444e improve the setup script 2025-10-05 23:53:21 -07:00
mbecker20 059716f178 deploy 2.0.0-dev-36 2025-10-05 18:23:43 -07:00
mbecker20 0bee1fe2c5 fix: connect and connect insecure are swapped 2025-10-05 18:20:29 -07:00
mbecker20 1e58c1a958 deploy 2.0.0-dev-35 2025-10-05 17:45:16 -07:00
mbecker20 ed1431db0a improve v1 downgrade 2025-10-05 17:43:46 -07:00
mbecker20 dc769ff159 document periphery_public_key 2025-10-05 17:39:11 -07:00
mbecker20 098f23ac4c configure Core -> Periphery insecure_tls 2025-10-05 17:36:07 -07:00
mbecker20 03f577d22f forgiving periphery public key parsing 2025-10-05 17:02:08 -07:00
mbecker20 95ca217362 deploy 2.0.0-dev-34 2025-10-05 16:52:33 -07:00
mbecker20 6d61045764 support KOMODO_PERIPHERY_PUBLIC_KEY 2025-10-05 16:52:00 -07:00
mbecker20 34e075eaf3 periphery support core_tls_insecure_skip_verify 2025-10-05 16:12:04 -07:00
mbecker20 232dc0bb4e deploy 2.0.0-dev-33 2025-10-05 14:59:23 -07:00
mbecker20 0cc0ee2aab load periphery_public_key 2025-10-05 14:58:52 -07:00
mbecker20 edebe925ff add km maintenance tasks aliases 2025-10-05 14:50:20 -07:00
mbecker20 5fd45bbc7b deploy 2.0.0-dev-32 2025-10-05 14:39:09 -07:00
mbecker20 0a490dadb2 rotation maintenance execution doesn't make individual updates 2025-10-05 14:38:45 -07:00
mbecker20 23847c15bc deploy 2.0.0-dev-31 2025-10-05 14:21:18 -07:00
mbecker20 0d238aee4f onboarding create_builder 2025-10-05 14:20:58 -07:00
mbecker20 98ad6cf5fa create update use uppercase 2025-10-05 13:41:42 -07:00
mbecker20 e35b81630b deploy 2.0.0-dev-30 2025-10-05 13:30:47 -07:00
mbecker20 1215852fe4 onboarding set Server tags 2025-10-05 13:24:38 -07:00
mbecker20 4164b76ff5 onboarded server needs to be enabled 2025-10-05 12:36:04 -07:00
mbecker20 26a9daffeb deploy 2.0.0-dev-29 2025-10-05 05:49:29 -07:00
mbecker20 8bb9f16e9b onboarding save copy server selection 2025-10-05 05:47:51 -07:00
mbecker20 b6eaf76497 Include templates in onboarding selector 2025-10-05 05:44:58 -07:00
mbecker20 073893da0e deploy 2.0.0-dev-28 2025-10-05 05:18:48 -07:00
mbecker20 e71547f1c2 configure server onboarding key 2025-10-05 05:17:56 -07:00
mbecker20 1991627990 move periphery public key to Server info (keep it out of resource sync) 2025-10-05 04:18:59 -07:00
mbecker20 3434d827a3 deploy 2.0.0-dev-27 2025-10-05 02:57:58 -07:00
mbecker20 1ef8b9878a rotate all server keys task 2025-10-05 02:57:27 -07:00
mbecker20 07ddaa8377 tweak 2025-10-05 01:41:44 -07:00
mbecker20 142c08cde4 deploy 2.0.0-dev-26 2025-10-05 01:19:21 -07:00
mbecker20 1aa1422faa periphery private key rotation 2025-10-05 01:18:56 -07:00
mbecker20 1394e8a6b1 Rotate Server private keys 2025-10-05 00:54:56 -07:00
mbecker20 420ee10211 tweaks 2025-10-04 23:59:14 -07:00
mbecker20 e918461dc5 refine onboarding key 2025-10-04 23:36:37 -07:00
mbecker20 4dc9ca27be refactor Periphery onboarding 2025-10-04 16:43:02 -07:00
mbecker20 f49b186f2f consolidate periphery docker apis into single mod 2025-10-04 16:17:32 -07:00
mbecker20 6e039b41f1 deploy 2.0.0-dev-25 2025-10-03 17:51:46 -07:00
mbecker20 e7cd77b022 tweaks 2025-10-03 17:06:14 -07:00
mbecker20 556cbd04c7 server onboarding flow using onboarding key 2025-10-03 17:01:58 -07:00
mbecker20 4e3d181466 default documented setup now uses Periphery -> Core setup 2025-10-03 12:55:06 -07:00
mbecker20 5d4326f46f NOT_FOUND if server not found 2025-10-03 03:17:37 -07:00
mbecker20 4bb486ad0a deploy 2.0.0-dev-24 2025-10-03 02:30:20 -07:00
mbecker20 d29c5112d8 Confirm server public key flow 2025-10-03 02:29:53 -07:00
mbecker20 d41315b8a4 don't navigate to /login for network errors 2025-10-03 01:58:23 -07:00
mbecker20 847404388c deploy 2.0.0-dev-23 2025-10-03 00:48:11 -07:00
mbecker20 eef8ec59b8 deploy 2.0.0-dev-22 2025-10-03 00:19:43 -07:00
mbecker20 9eb32f9ff5 store attempted public keys 2025-10-03 00:13:55 -07:00
mbecker20 859bfe67ef Improve Core side connection handling and fix Periphery -> Core error report 2025-10-02 23:03:58 -07:00
mbecker20 21ea469cd4 add login message 2 sec timeout 2025-10-02 16:00:45 -07:00
mbecker20 7fb902b892 deploy 2.0.0-dev-21 2025-10-02 03:12:59 -07:00
mbecker20 c9c4ac47ee fix clippy 2025-10-02 02:34:23 -07:00
mbecker20 f228cd31f3 deploy 2.0.0-dev-20 2025-10-02 02:33:33 -07:00
mbecker20 4feecb4b97 write key pem files by default when not otherwise provided. 2025-10-02 02:32:13 -07:00
mbecker20 e2680d0942 fix deploy 2025-10-01 21:35:27 -07:00
mbecker20 7422c0730d deploy 2.0.0-dev-19 2025-10-01 21:27:59 -07:00
mbecker20 37ac0dc7e3 update deploy 2025-10-01 21:17:43 -07:00
mbecker20 dccaca1df4 make sure not a config file before include as compose file 2025-10-01 20:32:52 -07:00
mbecker20 886aea4c36 deploy 2.0.0-dev-18 2025-10-01 19:48:40 -07:00
mbecker20 cbca070bae load keys from files 2025-10-01 19:41:32 -07:00
mbecker20 b4bdd401f6 fix unneeded base64 prefix 2025-10-01 02:36:26 -07:00
mbecker20 e546166240 use pkcs8 and spki for private / public key encoding, matching openssl 2025-10-01 02:25:41 -07:00
mbecker20 21689ce0ad periphery support same key gen functions 2025-09-29 23:32:47 -07:00
mbecker20 941787db64 slack client 0.5.0 2025-09-29 12:38:39 -07:00
mbecker20 d4b1aacac3 comment out 2025-09-29 02:21:07 -07:00
mbecker20 30f89461bf deploy 2.0.0-dev-17 2025-09-29 00:57:19 -07:00
mbecker20 a42d1397e9 back to bullseye (for max GLIBC compatibility) 2025-09-29 00:56:19 -07:00
mbecker20 b29313c28f deploy 2.0.0-dev-16 2025-09-29 00:47:17 -07:00
mbecker20 08a246a90c bullseye -> trixie 2025-09-29 00:46:51 -07:00
mbecker20 1a08df28d0 docs and config clean up 2025-09-29 00:06:35 -07:00
mbecker20 a226ffc256 fix json config load from interpolated 2025-09-28 23:20:04 -07:00
mbecker20 b385ee5ec3 start on docs update 2025-09-28 22:59:58 -07:00
mbecker20 c78c34357d remove unnecessary connected to core websocket log 2025-09-28 18:14:57 -07:00
mbecker20 4b7c692f00 deploy 2.0.0-dev-15 2025-09-28 18:02:18 -07:00
mbecker20 1ac98a096e bump async timing util to 1.1.0 to support for timelengths 2025-09-28 17:57:12 -07:00
mbecker20 281a2dc1ce first server configuration works with Periphery -> Core 2025-09-28 14:39:11 -07:00
mbecker20 0fe91378a6 tweak key gen output 2025-09-28 14:12:41 -07:00
mbecker20 11e76d1cf2 deploy 2.0.0-dev-14 2025-09-28 13:10:00 -07:00
mbecker20 a3bcd71105 simplify cache refresh with single periphery call 2025-09-28 13:05:45 -07:00
mbecker20 3ecc56dd76 clean up crypto provider install 2025-09-27 21:40:20 -07:00
mbecker20 7239cbb19b remove extra install crypto provider 2025-09-27 19:37:50 -07:00
mbecker20 a0540f7011 deploy 2.0.0-dev-13 2025-09-27 16:54:00 -07:00
mbecker20 37aea7605e gen types 2025-09-27 14:33:14 -07:00
mbecker20 78be913541 fix stuff after main rebase 2025-09-27 14:26:58 -07:00
mbecker20 c34f5ebf49 update config and compose envs 2025-09-27 14:23:49 -07:00
mbecker20 e5822cefb8 clean up socket handling 2025-09-27 14:23:49 -07:00
mbecker20 4baab194cf centralize the terminal stuff 2025-09-27 14:23:49 -07:00
mbecker20 a896583da6 deploy 2.0.0-dev-12 2025-09-27 14:23:49 -07:00
mbecker20 7b2674c38b deploy 2.0.0-dev-11 2025-09-27 14:23:42 -07:00
mbecker20 d1e32989e3 allow any number of simultaneous inbound / outbound connections (to different Cores) 2025-09-27 14:23:36 -07:00
mbecker20 e802bb3882 periphery support multiple core_public_keys 2025-09-27 14:23:36 -07:00
mbecker20 27a38b1bf5 periphery support multiple simultaneous core connections 2025-09-27 14:23:36 -07:00
mbecker20 2bc8a754be clean up passkey login 2025-09-27 14:23:36 -07:00
mbecker20 7a2a54bec1 dev-10 2025-09-27 14:23:36 -07:00
mbecker20 6a15150d59 don't cleanup server type builders 2025-09-27 14:23:31 -07:00
mbecker20 1b1dca76da deploy 2.0.0-dev-9 2025-09-27 14:23:31 -07:00
mbecker20 a032f0f4ff move system info to server cache 2025-09-27 14:23:25 -07:00
mbecker20 2749d49435 Core -> Periphery connection prefers noise handshake if 'core_public_key' is set 2025-09-27 14:23:25 -07:00
mbecker20 d88e42ef2d add specific server passkey support back 2025-09-27 14:23:25 -07:00
mbecker20 a370e7d121 support passkey auth for Core -> Periphery connection to remove the breaking change 2025-09-27 14:23:25 -07:00
mbecker20 d139ad2b3d always fallback to core config 'periphery_public_key' 2025-09-27 14:23:25 -07:00
mbecker20 8d2d180398 deploy 2.0.0-dev-8 2025-09-27 14:22:48 -07:00
mbecker20 37ca4ca986 fix server update hang 2025-09-27 14:22:42 -07:00
mbecker20 33e73b8543 use warn log 2025-09-27 14:22:42 -07:00
mbecker20 cf6e36e90c periphery server avoid auth fail log spam 2025-09-27 14:22:42 -07:00
mbecker20 9eb8b32f4a create and delete connections on demand 2025-09-27 14:22:42 -07:00
mbecker20 b400add6f1 deploy 2.0.0-dev-7 2025-09-27 14:22:41 -07:00
mbecker20 24adb89d25 execute container exec waits a bit for terminal to init before sending command 2025-09-27 14:22:36 -07:00
mbecker20 4674b2badb deploy 2.0.0-dev-6 2025-09-27 14:22:36 -07:00
mbecker20 65d1a69cb9 Mount ExecuteContainerExec periphery api 2025-09-27 14:22:27 -07:00
mbecker20 0da5718991 store connection channels under the connection 2025-09-27 14:22:27 -07:00
mbecker20 6b26cd120c simplify most of periphery client into bin/core 2025-09-27 14:22:27 -07:00
mbecker20 28e1bb19a4 deploy 2.0.0-dev-5 2025-09-27 14:22:27 -07:00
mbecker20 166107ac07 bail_if_not_connected 2025-09-27 14:22:21 -07:00
mbecker20 d77201880f dashboard Active include GlobalAutoUpdate 2025-09-27 14:22:21 -07:00
mbecker20 1d7629e9b2 Update server address description and placeholders 2025-09-27 14:22:21 -07:00
mbecker20 198f690ca5 Got invalid public key: {public_key} 2025-09-27 14:22:21 -07:00
mbecker20 531c79a144 deploy 2.0.0-dev-4 2025-09-27 14:22:21 -07:00
mbecker20 d685862713 improve Core - Periphery auth error messages 2025-09-27 14:22:09 -07:00
mbecker20 af0f245b5b deploy 2.0.0-dev-3 2025-09-27 14:22:09 -07:00
mbecker20 cba36861b7 deploy 2.0.0-dev-2 2025-09-27 14:22:02 -07:00
mbecker20 2c2c1d47b4 dev-2 2025-09-27 14:22:02 -07:00
mbecker20 3a6b997241 Json and JsonPretty formatting 2025-09-27 14:21:54 -07:00
mbecker20 7122f79b9d add -f json option to key utils (for use with jquery etc. 2025-09-27 14:21:54 -07:00
mbecker20 9bcee8122b tweak 2025-09-27 14:21:54 -07:00
mbecker20 a49c98946e add copy pubkeys 2025-09-27 14:21:54 -07:00
mbecker20 7d222a7241 dev-1 2025-09-27 14:21:54 -07:00
mbecker20 33501dac3e fix Core -> Periphery reconnection 2025-09-27 14:21:44 -07:00
mbecker20 4675dfa736 improve the logging 2025-09-27 14:21:44 -07:00
mbecker20 0be51dc784 move core connection handlers into core binary 2025-09-27 14:21:44 -07:00
mbecker20 52453d1320 set default allowed periphery public key 2025-09-27 14:21:44 -07:00
mbecker20 25da97ac1a basic configure auth 2025-09-27 14:21:44 -07:00
mbecker20 02db5a11d3 pipe through core side private / public key handling 2025-09-27 14:21:44 -07:00
mbecker20 89a5272246 rename passkey -> private_key 2025-09-27 14:21:44 -07:00
mbecker20 ae51ea1ad6 Copy core public key 2025-09-27 14:21:44 -07:00
mbecker20 3bdb4bea16 Core includes public key in CoreInfo 2025-09-27 14:21:44 -07:00
mbecker20 677bb14b5d auth forward error 2025-09-27 14:21:44 -07:00
mbecker20 6700700a80 clean up websocket handlers with many params 2025-09-27 14:21:44 -07:00
mbecker20 996d4aa129 standardize server size header identifier extraction 2025-09-27 14:21:44 -07:00
mbecker20 75894a7282 wire through private keys 2025-09-27 14:21:44 -07:00
mbecker20 2a065edcf1 avoid looping periphery client error 2025-09-27 14:21:44 -07:00
mbecker20 6f3703acfb periphery client makes more sense 2025-09-27 14:21:44 -07:00
mbecker20 59e989ecdf noise library and cli key utilities 2025-09-27 14:21:44 -07:00
mbecker20 951ff34a9e abstract websocket handling implementations on both sides 2025-09-27 14:21:12 -07:00
mbecker20 2d83105500 clean up 2025-09-27 14:21:12 -07:00
mbecker20 3d455f5142 implement noise auth basic 2025-09-27 14:21:12 -07:00
mbecker20 01de8c4a9b use standardized websocket wrappers / traits 2025-09-27 14:21:12 -07:00
mbecker20 d5de338561 outbound connection mode working 2025-09-27 14:21:12 -07:00
mbecker20 58c1afb8ef add login draft for transport 2025-09-27 14:21:12 -07:00
mbecker20 230f357b5a everything over ws working 2025-09-27 14:21:12 -07:00
mbecker20 991c95fff0 execute basically working, still need to clear the response channel upon completion 2025-09-27 14:21:12 -07:00
mbecker20 f6243fe6b1 more cleanup 2025-09-27 14:21:12 -07:00
mbecker20 9feeccba6e container terminal over connection 2025-09-27 14:21:12 -07:00
mbecker20 673c7f3a6b multiplex requests + terminal over single WS 2025-09-27 14:21:12 -07:00
mbecker20 39f900d651 standardize and consolidate logic in transport lib 2025-09-27 14:21:12 -07:00
mbecker20 8a06a0d6ce is work 2025-09-27 14:21:12 -07:00
mbecker20 7789ee4f4a prog 2025-09-27 14:21:12 -07:00
mbecker20 0472b6a7f7 fix after 1.19.4 2025-09-27 14:21:12 -07:00
mbecker20 d1d2227d36 prog 2025-09-27 14:21:11 -07:00
mbecker20 cea7c5fc5e prog on ws connect 2025-09-27 14:21:11 -07:00
293 changed files with 5251 additions and 8564 deletions
+3 -9
View File
@@ -1,6 +1,6 @@
services:
dev:
image: mcr.microsoft.com/devcontainers/rust:1-bookworm
image: mcr.microsoft.com/devcontainers/rust:1-1-bullseye
volumes:
# Mount the root folder that contains .git
- ../:/workspace:cached
@@ -10,19 +10,13 @@ services:
- stacks:/etc/komodo/stacks
command: sleep infinity
ports:
- "9120:9120"
- "9121:9121"
environment:
KOMODO_HOST: http://localhost:9120
KOMODO_FIRST_SERVER: http://localhost:8120
KOMODO_DATABASE_ADDRESS: db
KOMODO_ENABLE_NEW_USERS: true
KOMODO_LOCAL_AUTH: true
KOMODO_JWT_SECRET: a_random_secret
VITE_KOMODO_HOST: http://localhost:9120
KOMODO_CORS_ALLOWED_ORIGINS: http://localhost:5173
KOMODO_CORS_ALLOW_CREDENTIALS: true
PERIPHERY_SSL_ENABLED: false
KOMODO_SESSION_ALLOW_CROSS_SITE: true
links:
- db
# ...
@@ -36,4 +30,4 @@ volumes:
data:
repo-cache:
repos:
stacks:
stacks:
+3 -9
View File
@@ -10,7 +10,7 @@
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "22.12.0"
"version": "20.12.2"
},
"ghcr.io/devcontainers-community/features/deno:1": {
@@ -28,8 +28,7 @@
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [
5173,
9120
9121
],
// Use 'postCreateCommand' to run commands after the container is created.
@@ -37,16 +36,11 @@
"runServices": [
"db"
],
]
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
"remoteEnv": {
// Avoid out of memory error when running `yarn build`
"NODE_OPTIONS": "--max-old-space-size=4096"
}
}
+1 -7
View File
@@ -1,9 +1,3 @@
#!/bin/sh
cargo install typeshare-cli
sudo mkdir -p /etc/komodo/keys
sudo chown -R $(whoami) /etc/komodo
sudo mkdir -p /config/keys
sudo chown -R $(whoami) /config
cargo install typeshare-cli
-56
View File
@@ -1,56 +0,0 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
jobs:
build:
name: Build & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
Generated
+107 -111
View File
@@ -82,9 +82,9 @@ dependencies = [
[[package]]
name = "anstream"
version = "1.0.0"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -103,9 +103,9 @@ checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
version = "1.0.0"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
@@ -138,9 +138,9 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arc-swap"
version = "1.9.0"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a07d1f37ff60921c83bdfc7407723bdefe89b44b98a9b772f225c8f9d67141a6"
checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5"
dependencies = [
"rustversion",
]
@@ -324,9 +324,9 @@ dependencies = [
[[package]]
name = "aws-sdk-ec2"
version = "1.220.0"
version = "1.216.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4d073e665c1303edc348511ec2509b58a2cee148196f72db33aef5cd47c3573"
checksum = "0bcafb17cfb3978dbf5b5a637d101a6212bc080cb33b5881da65f87967aedf67"
dependencies = [
"aws-credential-types",
"aws-runtime",
@@ -576,9 +576,9 @@ dependencies = [
[[package]]
name = "aws-smithy-types"
version = "1.4.7"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d73dbfbaa8e4bc57b9045137680b958d274823509a360abfd8e1d514d40c95c"
checksum = "d2b1117b3b2bbe166d11199b540ceed0d0f7676e36e7b962b5a437a9971eac75"
dependencies = [
"base64-simd",
"bytes",
@@ -653,7 +653,7 @@ dependencies = [
"sha1",
"sync_wrapper",
"tokio",
"tokio-tungstenite 0.28.0",
"tokio-tungstenite",
"tower",
"tower-layer",
"tower-service",
@@ -852,9 +852,9 @@ dependencies = [
[[package]]
name = "bollard"
version = "0.20.2"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee04c4c84f1f811b017f2fbb7dd8815c976e7ca98593de9c1e2afad0f636bff4"
checksum = "227aa051deec8d16bd9c34605e7aaf153f240e35483dd42f6f78903847934738"
dependencies = [
"base64 0.22.1",
"bollard-stubs",
@@ -1064,9 +1064,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.6.0"
version = "4.5.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
dependencies = [
"clap_builder",
"clap_derive",
@@ -1074,9 +1074,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.6.0"
version = "4.5.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
dependencies = [
"anstream",
"anstyle",
@@ -1086,9 +1086,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.6.0"
version = "4.5.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
dependencies = [
"heck",
"proc-macro2",
@@ -1149,7 +1149,7 @@ dependencies = [
[[package]]
name = "command"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"komodo_client",
"shlex",
@@ -1489,7 +1489,7 @@ checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
[[package]]
name = "database"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"async-compression",
@@ -1759,7 +1759,7 @@ dependencies = [
[[package]]
name = "encoding"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"bytes",
@@ -1801,7 +1801,7 @@ dependencies = [
[[package]]
name = "environment"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"formatting",
@@ -1930,7 +1930,7 @@ dependencies = [
[[package]]
name = "formatting"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"mogh_error",
]
@@ -2109,7 +2109,7 @@ dependencies = [
[[package]]
name = "git"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"command",
@@ -2709,7 +2709,7 @@ dependencies = [
[[package]]
name = "interpolate"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"komodo_client",
@@ -2835,10 +2835,9 @@ dependencies = [
[[package]]
name = "komodo_cli"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"bcrypt",
"chrono",
"clap",
"colored",
@@ -2865,7 +2864,7 @@ dependencies = [
[[package]]
name = "komodo_client"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"async_timing_util",
@@ -2894,7 +2893,7 @@ dependencies = [
"strum 0.28.0",
"thiserror 2.0.18",
"tokio",
"tokio-tungstenite 0.29.0",
"tokio-tungstenite",
"tokio-util",
"tracing",
"typeshare",
@@ -2904,7 +2903,7 @@ dependencies = [
[[package]]
name = "komodo_core"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"arc-swap",
@@ -2962,7 +2961,7 @@ dependencies = [
"svi",
"tokio",
"tokio-util",
"toml",
"toml 1.0.4+spec-1.1.0",
"toml_pretty",
"tracing",
"transport",
@@ -2977,7 +2976,7 @@ dependencies = [
[[package]]
name = "komodo_periphery"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"arc-swap",
@@ -3226,9 +3225,9 @@ dependencies = [
[[package]]
name = "mogh_auth_server"
version = "1.2.13"
version = "1.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d649dff8bdacff15df7d65716fcc4e3b1643bbc970d609d31cb45b3e2e02b9ac"
checksum = "e748cc16d2f7d9a86fbab3eff5f2e847df205db8ff5aa27728e45271f96d327b"
dependencies = [
"anyhow",
"arc-swap",
@@ -3271,9 +3270,9 @@ dependencies = [
[[package]]
name = "mogh_config"
version = "1.0.4"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a75ba6d01ac3bb726f95ee40c9d6b37251a1d538cbaf9ea0945744cfcec4842"
checksum = "be34694a34d9b693db2db6b66c3a963c9ee77628b881801e20f110b771acf598"
dependencies = [
"colored",
"indexmap 2.13.0",
@@ -3282,7 +3281,7 @@ dependencies = [
"serde_json",
"serde_yaml_ng",
"thiserror 2.0.18",
"toml",
"toml 0.9.11+spec-1.1.0",
"wildcard",
]
@@ -3301,9 +3300,9 @@ dependencies = [
[[package]]
name = "mogh_logger"
version = "1.3.2"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc71b30d39325fd768c98f0dc60487365f40eb30f3565f0d986fc2d555f95148"
checksum = "f5d0f4b7792da5b8a1786c451d8171fc6a9d7f02d4d59c6529ba353c36774d8d"
dependencies = [
"anyhow",
"opentelemetry",
@@ -3317,9 +3316,9 @@ dependencies = [
[[package]]
name = "mogh_pki"
version = "1.1.3"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "477508d50e1852afd8ed6b546c7cfbc95f6c7c26b9589f9f0f64dd36b5742436"
checksum = "3fcb4cbdee296a86d40a4a133717dbd10fc220e17f0631ec5960bc01f94d36c7"
dependencies = [
"anyhow",
"arc-swap",
@@ -3685,18 +3684,18 @@ dependencies = [
[[package]]
name = "objc2-core-foundation"
version = "0.3.2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
dependencies = [
"bitflags 2.10.0",
]
[[package]]
name = "objc2-io-kit"
version = "0.3.2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a"
dependencies = [
"libc",
"objc2-core-foundation",
@@ -3837,9 +3836,9 @@ dependencies = [
[[package]]
name = "opentelemetry-otlp"
version = "0.31.1"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f"
checksum = "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf"
dependencies = [
"http 1.4.0",
"opentelemetry",
@@ -4032,7 +4031,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "periphery_client"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"encoding",
@@ -4229,9 +4228,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
dependencies = [
"unicode-ident",
]
@@ -4343,9 +4342,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
dependencies = [
"proc-macro2",
]
@@ -4993,9 +4992,9 @@ dependencies = [
[[package]]
name = "serde_qs"
version = "1.1.0"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c742cd44662647326f86b514eadcc227fff4ce684dbbdaf1943f758d5ea058c"
checksum = "ac22439301a0b6f45a037681518e3169e8db1db76080e2e9600a08d1027df037"
dependencies = [
"itoa",
"percent-encoding",
@@ -5016,9 +5015,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "1.1.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98"
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
dependencies = [
"serde_core",
]
@@ -5377,9 +5376,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [
"proc-macro2",
"quote",
@@ -5408,9 +5407,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.38.4"
version = "0.38.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f"
checksum = "d03c61d2a49c649a15c407338afe7accafde9dac869995dccb73e5f7ef7d9034"
dependencies = [
"libc",
"memchr",
@@ -5638,18 +5637,6 @@ name = "tokio-tungstenite"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite 0.28.0",
]
[[package]]
name = "tokio-tungstenite"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c"
dependencies = [
"futures-util",
"log",
@@ -5658,7 +5645,7 @@ dependencies = [
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.4",
"tungstenite 0.29.0",
"tungstenite",
]
[[package]]
@@ -5677,14 +5664,29 @@ dependencies = [
[[package]]
name = "toml"
version = "1.1.0+spec-1.1.0"
version = "0.9.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8195ca05e4eb728f4ba94f3e3291661320af739c4e43779cbdfae82ab239fcc"
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
dependencies = [
"indexmap 2.13.0",
"serde_core",
"serde_spanned",
"toml_datetime",
"toml_datetime 0.7.5+spec-1.1.0",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml"
version = "1.0.4+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c94c3321114413476740df133f0d8862c61d87c8d26f04c6841e033c8c80db47"
dependencies = [
"indexmap 2.13.0",
"serde_core",
"serde_spanned",
"toml_datetime 1.0.0+spec-1.1.0",
"toml_parser",
"toml_writer",
"winnow",
@@ -5692,18 +5694,27 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "1.1.0+spec-1.1.0"
version = "0.7.5+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f"
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_datetime"
version = "1.0.0+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_parser"
version = "1.1.0+spec-1.1.0"
version = "1.0.9+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011"
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
dependencies = [
"winnow",
]
@@ -5722,9 +5733,9 @@ dependencies = [
[[package]]
name = "toml_writer"
version = "1.1.0+spec-1.1.0"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed"
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
[[package]]
name = "tonic"
@@ -5767,9 +5778,9 @@ dependencies = [
[[package]]
name = "totp-rs"
version = "5.7.1"
version = "5.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2b36a9dd327e9f401320a2cb4572cc76ff43742bcfc3291f871691050f140ba"
checksum = "f124352108f58ef88299e909f6e9470f1cdc8d2a1397963901b4a6366206bf72"
dependencies = [
"base32",
"constant_time_eq",
@@ -5980,9 +5991,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.23"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
dependencies = [
"nu-ansi-term",
"serde",
@@ -5997,11 +6008,12 @@ dependencies = [
[[package]]
name = "transport"
version = "2.0.0"
version = "2.0.0-dev-124"
dependencies = [
"anyhow",
"axum",
"bytes",
"colored",
"data-encoding",
"encoding",
"futures-util",
@@ -6015,7 +6027,7 @@ dependencies = [
"sha1",
"sha2",
"tokio",
"tokio-tungstenite 0.29.0",
"tokio-tungstenite",
"tokio-util",
"tracing",
"url",
@@ -6033,23 +6045,6 @@ name = "tungstenite"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442"
dependencies = [
"bytes",
"data-encoding",
"http 1.4.0",
"httparse",
"log",
"rand 0.9.2",
"sha1",
"thiserror 2.0.18",
"utf-8",
]
[[package]]
name = "tungstenite"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8"
dependencies = [
"bytes",
"data-encoding",
@@ -6061,6 +6056,7 @@ dependencies = [
"rustls-pki-types",
"sha1",
"thiserror 2.0.18",
"utf-8",
]
[[package]]
@@ -6264,13 +6260,13 @@ dependencies = [
[[package]]
name = "uuid"
version = "1.22.0"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37"
checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb"
dependencies = [
"getrandom 0.4.1",
"js-sys",
"rand 0.10.0",
"rand 0.9.2",
"serde_core",
"wasm-bindgen",
]
@@ -7011,9 +7007,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
version = "1.0.0"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
[[package]]
name = "winreg"
+12 -12
View File
@@ -8,7 +8,7 @@ members = [
]
[workspace.package]
version = "2.0.0"
version = "2.0.0-dev-124"
edition = "2024"
authors = ["mbecker20 <becker.maxh@gmail.com>"]
license = "GPL-3.0-or-later"
@@ -37,19 +37,19 @@ mogh_error = { version = "1.0.3", default-features = false }
derive_default_builder = "0.1.8"
async_timing_util = "1.1.0"
mogh_auth_client = "1.2.2"
mogh_auth_server = "1.2.13"
mogh_auth_server = "1.2.12"
mogh_secret_file = "1.0.1"
mogh_validations = "1.0.1"
mogh_rate_limit = "1.0.1"
partial_derive2 = "0.4.5"
mongo_indexed = "2.0.2"
mogh_resolver = "1.0.0"
mogh_config = "1.0.4"
mogh_logger = "1.3.2"
mogh_config = "1.0.2"
mogh_logger = "1.3.1"
mogh_server = "1.4.5"
toml_pretty = "2.0.0"
mogh_cache = "1.1.1"
mogh_pki = "1.1.3"
mogh_pki = "1.1.0"
mungos = "3.2.2"
svi = "1.2.0"
@@ -60,10 +60,10 @@ tokio-util = { version = "0.7.18", features = ["io", "codec"] }
tokio-stream = { version = "0.1.18", features = ["sync"] }
pin-project-lite = "0.2.17"
futures-util = "0.3.32"
arc-swap = "1.9.0"
arc-swap = "1.8.2"
# SERVER
tokio-tungstenite = { version = "0.29.0", features = ["rustls-tls-native-roots"] }
tokio-tungstenite = { version = "0.28.0", features = ["rustls-tls-native-roots"] }
axum = { version = "0.8.8", features = ["ws", "json", "macros"] }
axum-extra = { version = "0.12.5", features = ["typed-header"] }
@@ -77,10 +77,10 @@ indexmap = { version = "2.13.0", features = ["serde"] }
serde = { version = "1.0.227", features = ["derive"] }
strum = { version = "0.28.0", features = ["derive"] }
bson = { version = "2.15.0" } # must keep in sync with mongodb version
toml = "1.1.0"
toml = "1.0.4"
serde_yaml_ng = "0.10.0"
serde_json = "1.0.149"
serde_qs = "1.1.0"
serde_qs = "1.0.0"
url = "2.5.8"
# ERROR
@@ -112,13 +112,13 @@ hickory-resolver = "0.25.2"
portable-pty = "0.9.0"
shell-escape = "0.1.5"
crossterm = "0.29.0"
bollard = "0.20.2"
sysinfo = "0.38.4"
bollard = "0.20.1"
sysinfo = "0.38.3"
shlex = "1.3.0"
# CLOUD
aws-config = "1.8.15"
aws-sdk-ec2 = "1.220.0"
aws-sdk-ec2 = "1.216.0"
aws-credential-types = "1.2.14"
## CRON
+1 -1
View File
@@ -1,7 +1,7 @@
## Builds the Komodo Core, Periphery, and Util binaries
## for a specific architecture. Requires OpenSSL 3 or later.
FROM rust:1.94.0-bookworm AS builder
FROM rust:1.93.1-bookworm AS builder
RUN cargo install cargo-strip
WORKDIR /builder
+1 -1
View File
@@ -3,7 +3,7 @@
## Uses chef for dependency caching to help speed up back-to-back builds.
FROM lukemathwalker/cargo-chef:latest-rust-1.94.0-bookworm AS chef
FROM lukemathwalker/cargo-chef:latest-rust-1.93.1-bookworm AS chef
WORKDIR /builder
# Plan just the RECIPE to see if things have changed
-1
View File
@@ -32,7 +32,6 @@ tracing.workspace = true
colored.workspace = true
dotenvy.workspace = true
anyhow.workspace = true
bcrypt.workspace = true
chrono.workspace = true
rustls.workspace = true
tokio.workspace = true
+1 -1
View File
@@ -1,4 +1,4 @@
FROM rust:1.94.0-bullseye AS builder
FROM rust:1.93.1-bullseye AS builder
RUN cargo install cargo-strip
WORKDIR /builder
+1 -1
View File
@@ -1,7 +1,7 @@
## Assumes the latest binaries for x86_64 and aarch64 are already built (by binaries.Dockerfile).
## Since theres no heavy build here, QEMU multi-arch builds are fine for this image.
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:2
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:latest
ARG X86_64_BINARIES=${BINARIES_IMAGE}-x86_64
ARG AARCH64_BINARIES=${BINARIES_IMAGE}-aarch64
+1 -1
View File
@@ -1,6 +1,6 @@
## Assumes the latest binaries for the required arch are already built (by binaries.Dockerfile).
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:2
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:latest
# This is required to work with COPY --from
FROM ${BINARIES_IMAGE} AS binaries
-13
View File
@@ -1,13 +0,0 @@
use anyhow::Context as _;
use komodo_client::api::read::GetCoreInfo;
pub async fn handle() -> anyhow::Result<()> {
let client = super::komodo_client().await?;
let info = client.read(GetCoreInfo {}).await?;
println!(
"{}",
serde_json::to_string_pretty(&info)
.context("Failed to serialize core info to JSON")?
);
Ok(())
}
-101
View File
@@ -1,101 +0,0 @@
use anyhow::Context as _;
use database::bson::doc;
use komodo_client::{
api::read::FindUser,
entities::{
api_key::ApiKey, config::cli::args::create::CreateApiKey,
komodo_timestamp, random_string,
},
};
use serde_json::json;
use crate::config::cli_config;
pub async fn create(
CreateApiKey {
name,
for_user,
expires,
use_api,
}: &CreateApiKey,
) -> anyhow::Result<()> {
let expires = if let Some(expires_days) = expires {
// now + expires in ms
komodo_timestamp() + expires_days * 24 * 60 * 60 * 1000
} else {
0
};
if *use_api {
// USE API
let client = crate::command::komodo_client().await?;
let keys = if let Some(username) = for_user {
// For service user
let user = client
.read(FindUser {
user: username.to_string(),
})
.await?;
client
.write(
komodo_client::api::write::CreateApiKeyForServiceUser {
user_id: user.id,
name: name.clone().unwrap_or_default(),
expires,
},
)
.await?
} else {
// For self
client
.auth_manage(komodo_client::api::auth::manage::CreateApiKey {
name: name.clone().unwrap_or_default(),
expires: expires as u64,
})
.await?
};
println!(
"{}",
serde_json::to_string_pretty(&keys)
.context("Failed to serialize api keys to JSON")?
);
} else {
// USE DATABASE
let db = database::Client::new(&cli_config().database).await?;
let user = db
.users
.find_one(doc! { "username": for_user })
.await
.context("Failed to query database for user")?
.context("No user found with given username")?;
let key = format!("K_{}_K", random_string(40));
let secret = format!("S_{}_S", random_string(40));
let hashed_secret = bcrypt::hash(&secret, 10)
.context("Failed at hashing secret string")?;
db.api_keys
.insert_one(&ApiKey {
name: name.clone().unwrap_or_default(),
user_id: user.id,
key: key.clone(),
secret: hashed_secret.clone(),
created_at: komodo_timestamp(),
expires,
})
.await?;
println!(
"{}",
serde_json::to_string_pretty(
&json!({ "key": key, "secret": secret })
)
.context("Failed to serialize api keys to JSON")?
);
}
Ok(())
}
-13
View File
@@ -1,13 +0,0 @@
use komodo_client::entities::config::cli::args::create::CreateCommand;
mod api_key;
mod onboarding_key;
pub async fn handle(command: &CreateCommand) -> anyhow::Result<()> {
match command {
CreateCommand::ApiKey(api_key) => api_key::create(api_key).await,
CreateCommand::OnboardingKey(onboarding_key) => {
onboarding_key::create(onboarding_key).await
}
}
}
@@ -1,46 +0,0 @@
use anyhow::Context as _;
use komodo_client::entities::{
config::cli::args::create::CreateOnboardingKey, komodo_timestamp,
};
pub async fn create(
CreateOnboardingKey {
name,
expires,
private_key,
tags,
privileged,
copy_server,
create_builder,
}: &CreateOnboardingKey,
) -> anyhow::Result<()> {
let expires = if let Some(expires_days) = expires {
// now + expires in ms
komodo_timestamp() + expires_days * 24 * 60 * 60 * 1000
} else {
0
};
// USE API
let client = crate::command::komodo_client().await?;
let key = client
.write(komodo_client::api::write::CreateOnboardingKey {
name: name.clone().unwrap_or_default(),
expires,
private_key: private_key.clone(),
tags: tags.clone(),
privileged: *privileged,
copy_server: copy_server.clone().unwrap_or_default(),
create_builder: *create_builder,
})
.await?;
println!(
"{}",
serde_json::to_string_pretty(&key)
.context("Failed to serialize onboarding key to JSON")?
);
Ok(())
}
-2
View File
@@ -15,8 +15,6 @@ use wildcard::Wildcard;
use crate::config::cli_config;
pub mod container;
pub mod core_info;
pub mod create;
pub mod database;
pub mod execute;
pub mod list;
+39 -81
View File
@@ -26,7 +26,7 @@ pub async fn handle_connect(
recreate,
}: &Connect,
) -> anyhow::Result<()> {
handle_terminal_forwarding(server, async {
handle_terminal_forwarding(async {
super::komodo_client()
.await?
.connect_server_terminal(
@@ -56,28 +56,25 @@ pub async fn handle_exec(
}: &Exec,
) -> anyhow::Result<()> {
let server = get_server(server.clone(), container).await?;
handle_terminal_forwarding(
&format!("{server}/{container}"),
async {
super::komodo_client()
.await?
.connect_container_terminal(
server,
container.to_string(),
None,
Some(InitTerminal {
command: Some(shell.to_string()),
recreate: if *recreate {
TerminalRecreateMode::Always
} else {
TerminalRecreateMode::DifferentCommand
},
mode: Some(ContainerTerminalMode::Exec),
}),
)
.await
},
)
handle_terminal_forwarding(async {
super::komodo_client()
.await?
.connect_container_terminal(
server,
container.to_string(),
None,
Some(InitTerminal {
command: Some(shell.to_string()),
recreate: if *recreate {
TerminalRecreateMode::Always
} else {
TerminalRecreateMode::DifferentCommand
},
mode: Some(ContainerTerminalMode::Exec),
}),
)
.await
})
.await
}
@@ -89,28 +86,25 @@ pub async fn handle_attach(
}: &Attach,
) -> anyhow::Result<()> {
let server = get_server(server.clone(), container).await?;
handle_terminal_forwarding(
&format!("{server}/{container}-attach"),
async {
super::komodo_client()
.await?
.connect_container_terminal(
server,
container.to_string(),
None,
Some(InitTerminal {
command: None,
recreate: if *recreate {
TerminalRecreateMode::Always
} else {
TerminalRecreateMode::DifferentCommand
},
mode: Some(ContainerTerminalMode::Attach),
}),
)
.await
},
)
handle_terminal_forwarding(async {
super::komodo_client()
.await?
.connect_container_terminal(
server,
container.to_string(),
None,
Some(InitTerminal {
command: None,
recreate: if *recreate {
TerminalRecreateMode::Always
} else {
TerminalRecreateMode::DifferentCommand
},
mode: Some(ContainerTerminalMode::Attach),
}),
)
.await
})
.await
}
@@ -169,7 +163,6 @@ async fn get_server(
async fn handle_terminal_forwarding<
C: Future<Output = anyhow::Result<TerminalWebsocket>>,
>(
label: &str,
connect: C,
) -> anyhow::Result<()> {
// Need to forward multiple sources into ws write
@@ -254,16 +247,6 @@ async fn handle_terminal_forwarding<
let forward_read = async {
let mut stdout = tokio::io::stdout();
// Write connection message
if let Err(e) = write_connection_message(&mut stdout, label)
.await
.context("Failed to write text to stdout")
{
cancel.cancel();
return Some(e);
}
while let Some(msg) =
future_or_cancel(ws_read.receive_stdout(), &cancel).await
{
@@ -314,31 +297,6 @@ async fn handle_terminal_forwarding<
std::process::exit(0)
}
async fn write_connection_message(
stdout: &mut tokio::io::Stdout,
label: &str,
) -> anyhow::Result<()> {
// Use message without ansi for correct length
let message_clean = format!("# Connected to {label} (km) #");
let bounder = "=".repeat(message_clean.chars().count());
let message = format!(
"# {} to {} {} #",
"Connected".green().bold(),
label.bold(),
"(km)".dimmed()
);
stdout
.write_all(
format!("\n{bounder}\r\n{message}\r\n{bounder}\r\n").as_bytes(),
)
.await?;
let _ = stdout.flush().await;
Ok(())
}
fn resize_message() -> anyhow::Result<TerminalStdinMessage> {
let (cols, rows) = crossterm::terminal::size()
.context("Failed to get terminal size")?;
-4
View File
@@ -45,7 +45,6 @@ async fn app() -> anyhow::Result<()> {
}
Ok(())
}
args::Command::CoreInfo => command::core_info::handle().await,
args::Command::Container(container) => {
command::container::handle(container).await
}
@@ -56,9 +55,6 @@ async fn app() -> anyhow::Result<()> {
args::Command::Execute(args) => {
command::execute::handle(&args.execution, args.yes).await
}
args::Command::Create { command } => {
command::create::handle(command).await
}
args::Command::Update { command } => {
command::update::handle(command).await
}
+1 -1
View File
@@ -1,7 +1,7 @@
## All in one, multi stage compile + runtime Docker build for your architecture.
# Build Core
FROM rust:1.94.0-trixie AS core-builder
FROM rust:1.93.1-trixie AS core-builder
RUN cargo install cargo-strip
WORKDIR /builder
+2 -2
View File
@@ -2,8 +2,8 @@
## Sets up the necessary runtime container dependencies for Komodo Core.
## Since theres no heavy build here, QEMU multi-arch builds are fine for this image.
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:2
ARG UI_IMAGE=ghcr.io/moghtech/komodo-ui:2
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:latest
ARG UI_IMAGE=ghcr.io/moghtech/komodo-ui:latest
ARG X86_64_BINARIES=${BINARIES_IMAGE}-x86_64
ARG AARCH64_BINARIES=${BINARIES_IMAGE}-aarch64
+1 -1
View File
@@ -1,7 +1,7 @@
## Assumes the latest binaries for the required arch are already built (by binaries.Dockerfile).
## Sets up the necessary runtime container dependencies for Komodo Core.
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:2
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:latest
# This is required to work with COPY --from
FROM ${BINARIES_IMAGE} AS binaries
+7 -9
View File
@@ -20,9 +20,7 @@ pub async fn send_alert(
let link = resource_link(ResourceTargetVariant::Swarm, id);
match alert.level {
SeverityLevel::Ok => {
format!(
"{level} | Swarm **{name}** is now **healthy**\n{link}"
)
format!("{level} | Swarm **{name}** is now **healthy**\n{link}")
}
SeverityLevel::Critical => {
let err = err
@@ -142,7 +140,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("\nserver: **{server}**")
} else {
String::new()
format!("")
};
format!(
"📦 Deployment **{name}** is now **{to}**{target}\nprevious: **{from}**\n{link}"
@@ -163,7 +161,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("\nserver: **{server}**")
} else {
String::new()
format!("")
};
format!(
"⬆ Deployment **{name}** has an update available{target}\nimage: **{image}**\n{link}"
@@ -184,7 +182,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("\nserver: **{server}**")
} else {
String::new()
format!("")
};
format!(
"⬆ Deployment **{name}** was updated automatically ⏫{target}\nimage: **{image}**\n{link}"
@@ -207,7 +205,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("\nserver: **{server}**")
} else {
String::new()
format!("")
};
format!(
"🥞 Stack **{name}** is now {to}{target}\nprevious: **{from}**\n{link}"
@@ -229,7 +227,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("\nserver: **{server}**")
} else {
String::new()
format!("")
};
format!(
"⬆ Stack **{name}** has an update available{target}\nservice: **{service}**\nimage: **{image}**\n{link}"
@@ -253,7 +251,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("\nserver: **{server}**")
} else {
String::new()
format!("")
};
format!(
"⬆ Stack **{name}** was updated automatically ⏫{target}\n{images_label}: **{images}**\n{link}"
+7 -9
View File
@@ -262,9 +262,7 @@ fn standard_alert_content(alert: &Alert) -> String {
.as_ref()
.map(|e| format!("\nerror: {e}"))
.unwrap_or_default();
format!(
"{level} | Swarm {name} is unhealthy ❌\n{link}{err}"
)
format!("{level} | Swarm {name} is unhealthy ❌\n{link}{err}")
}
_ => unreachable!(),
}
@@ -373,7 +371,7 @@ fn standard_alert_content(alert: &Alert) -> String {
} else if let Some(server) = server_name {
format!("\nserver: {server}")
} else {
String::new()
format!("")
};
format!(
"📦Deployment {name} is now {to_state}{target}\nprevious: {from}\n{link}",
@@ -394,7 +392,7 @@ fn standard_alert_content(alert: &Alert) -> String {
} else if let Some(server) = server_name {
format!("\nserver: {server}")
} else {
String::new()
format!("")
};
format!(
"⬆ Deployment {name} has an update available{target}\nimage: {image}\n{link}",
@@ -415,7 +413,7 @@ fn standard_alert_content(alert: &Alert) -> String {
} else if let Some(server) = server_name {
format!("\nserver: {server}")
} else {
String::new()
format!("")
};
format!(
"⬆ Deployment {name} was updated automatically{target}\nimage: {image}\n{link}",
@@ -438,7 +436,7 @@ fn standard_alert_content(alert: &Alert) -> String {
} else if let Some(server) = server_name {
format!("\nserver: {server}")
} else {
String::new()
format!("")
};
format!(
"🥞 Stack {name} is now {to_state}{target}\nprevious: {from}\n{link}",
@@ -460,7 +458,7 @@ fn standard_alert_content(alert: &Alert) -> String {
} else if let Some(server) = server_name {
format!("\nserver: {server}")
} else {
String::new()
format!("")
};
format!(
"⬆ Stack {name} has an update available{target}\nservice: {service}\nimage: {image}\n{link}",
@@ -484,7 +482,7 @@ fn standard_alert_content(alert: &Alert) -> String {
} else if let Some(server) = server_name {
format!("\nserver: {server}")
} else {
String::new()
format!("")
};
format!(
"⬆ Stack {name} was updated automatically ⏫{target}\n{images_label}: {images_str}\n{link}",
+6 -6
View File
@@ -289,7 +289,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("server: *{server}*\n")
} else {
String::new()
format!("")
};
let blocks = vec![
Block::header(text.clone()),
@@ -317,7 +317,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("server: *{server}*\n")
} else {
String::new()
format!("")
};
let blocks = vec![
Block::header(text.clone()),
@@ -345,7 +345,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("server: *{server}*\n")
} else {
String::new()
format!("")
};
let blocks = vec![
Block::header(text.clone()),
@@ -374,7 +374,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("server: *{server}*\n")
} else {
String::new()
format!("")
};
let blocks = vec![
Block::header(text.clone()),
@@ -402,7 +402,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("server: *{server}*\n")
} else {
String::new()
format!("")
};
let blocks = vec![
Block::header(text.clone()),
@@ -435,7 +435,7 @@ pub async fn send_alert(
} else if let Some(server) = server_name {
format!("server: *{server}*\n")
} else {
String::new()
format!("")
};
let blocks = vec![
Block::header(text.clone()),
+4 -8
View File
@@ -66,14 +66,14 @@ impl Resolve<ExecuteArgs> for BatchRunAction {
"BatchRunAction",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchRunAction>(&self.pattern, user)
@@ -87,7 +87,7 @@ impl Resolve<ExecuteArgs> for RunAction {
"RunAction",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
action = self.action,
@@ -95,11 +95,7 @@ impl Resolve<ExecuteArgs> for RunAction {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let mut action = get_check_permissions::<Action>(
&self.action,
+4 -12
View File
@@ -28,7 +28,7 @@ impl Resolve<ExecuteArgs> for TestAlerter {
"TestAlerter",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
alerter = self.alerter,
@@ -36,11 +36,7 @@ impl Resolve<ExecuteArgs> for TestAlerter {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let alerter = get_check_permissions::<Alerter>(
&self.alerter,
@@ -98,7 +94,7 @@ impl Resolve<ExecuteArgs> for SendAlert {
"SendAlert",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
request = format!("{self:?}"),
@@ -106,11 +102,7 @@ impl Resolve<ExecuteArgs> for SendAlert {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let alerters = list_full_for_user::<Alerter>(
Default::default(),
+7 -15
View File
@@ -75,14 +75,14 @@ impl Resolve<ExecuteArgs> for BatchRunBuild {
"BatchRunBuild",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchRunBuild>(&self.pattern, user)
@@ -96,7 +96,7 @@ impl Resolve<ExecuteArgs> for RunBuild {
"RunBuild",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
build = self.build,
@@ -104,11 +104,7 @@ impl Resolve<ExecuteArgs> for RunBuild {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let mut build = get_check_permissions::<Build>(
&self.build,
@@ -526,7 +522,7 @@ impl Resolve<ExecuteArgs> for CancelBuild {
"CancelBuild",
skip(user, update),
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
build = self.build,
@@ -534,11 +530,7 @@ impl Resolve<ExecuteArgs> for CancelBuild {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let build = get_check_permissions::<Build>(
&self.build,
@@ -634,7 +626,7 @@ async fn handle_post_build_redeploy(build_id: &str) {
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
}
+31 -63
View File
@@ -32,7 +32,7 @@ use crate::{
swarm::swarm_request,
update::update_update,
},
monitor::{refresh_server_cache, refresh_swarm_cache},
monitor::{update_cache_for_server, update_cache_for_swarm},
resource::{self, setup_deployment_execution},
state::action_states,
};
@@ -55,14 +55,14 @@ impl Resolve<ExecuteArgs> for BatchDeploy {
"BatchDeploy",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchDeploy>(&self.pattern, user)
@@ -76,7 +76,7 @@ impl Resolve<ExecuteArgs> for Deploy {
"Deploy",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -86,11 +86,7 @@ impl Resolve<ExecuteArgs> for Deploy {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (mut deployment, swarm_or_server) =
setup_deployment_execution(
@@ -226,7 +222,7 @@ impl Resolve<ExecuteArgs> for Deploy {
.await
{
Ok(logs) => {
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
update.logs.extend(logs)
}
Err(e) => {
@@ -250,7 +246,7 @@ impl Resolve<ExecuteArgs> for Deploy {
.await
{
Ok(log) => {
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.logs.push(log)
}
Err(e) => {
@@ -405,7 +401,7 @@ pub async fn pull_deployment_inner(
Err(e) => Log::error("Pull image", format_serror(&e.into())),
};
refresh_server_cache(server, true).await;
update_cache_for_server(server, true).await;
anyhow::Ok(log)
}
.await;
@@ -422,7 +418,7 @@ impl Resolve<ExecuteArgs> for PullDeployment {
"PullDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -430,11 +426,7 @@ impl Resolve<ExecuteArgs> for PullDeployment {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (deployment, swarm_or_server) = setup_deployment_execution(
&self.deployment,
@@ -480,7 +472,7 @@ impl Resolve<ExecuteArgs> for StartDeployment {
"StartDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -488,11 +480,7 @@ impl Resolve<ExecuteArgs> for StartDeployment {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (deployment, swarm_or_server) = setup_deployment_execution(
&self.deployment,
@@ -539,7 +527,7 @@ impl Resolve<ExecuteArgs> for StartDeployment {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -552,7 +540,7 @@ impl Resolve<ExecuteArgs> for RestartDeployment {
"RestartDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -560,11 +548,7 @@ impl Resolve<ExecuteArgs> for RestartDeployment {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (deployment, swarm_or_server) = setup_deployment_execution(
&self.deployment,
@@ -613,7 +597,7 @@ impl Resolve<ExecuteArgs> for RestartDeployment {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -626,7 +610,7 @@ impl Resolve<ExecuteArgs> for PauseDeployment {
"PauseDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -634,11 +618,7 @@ impl Resolve<ExecuteArgs> for PauseDeployment {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (deployment, swarm_or_server) = setup_deployment_execution(
&self.deployment,
@@ -685,7 +665,7 @@ impl Resolve<ExecuteArgs> for PauseDeployment {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -698,7 +678,7 @@ impl Resolve<ExecuteArgs> for UnpauseDeployment {
"UnpauseDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -706,11 +686,7 @@ impl Resolve<ExecuteArgs> for UnpauseDeployment {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (deployment, swarm_or_server) = setup_deployment_execution(
&self.deployment,
@@ -759,7 +735,7 @@ impl Resolve<ExecuteArgs> for UnpauseDeployment {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -772,7 +748,7 @@ impl Resolve<ExecuteArgs> for StopDeployment {
"StopDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -782,11 +758,7 @@ impl Resolve<ExecuteArgs> for StopDeployment {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (deployment, swarm_or_server) = setup_deployment_execution(
&self.deployment,
@@ -841,7 +813,7 @@ impl Resolve<ExecuteArgs> for StopDeployment {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -865,14 +837,14 @@ impl Resolve<ExecuteArgs> for BatchDestroyDeployment {
"BatchDestroyDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchDestroyDeployment>(
@@ -889,7 +861,7 @@ impl Resolve<ExecuteArgs> for DestroyDeployment {
"DestroyDeployment",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
deployment = self.deployment,
@@ -899,11 +871,7 @@ impl Resolve<ExecuteArgs> for DestroyDeployment {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (deployment, swarm_or_server) = setup_deployment_execution(
&self.deployment,
@@ -942,7 +910,7 @@ impl Resolve<ExecuteArgs> for DestroyDeployment {
.await
{
Ok(log) => {
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
log
}
Err(e) => Log::error(
@@ -970,7 +938,7 @@ impl Resolve<ExecuteArgs> for DestroyDeployment {
.await
{
Ok(log) => {
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
log
}
Err(e) => Log::error(
+10 -30
View File
@@ -54,18 +54,14 @@ impl Resolve<ExecuteArgs> for ClearRepoCache {
"ClearRepoCache",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id
)
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
if !user.admin {
return Err(
@@ -137,18 +133,14 @@ impl Resolve<ExecuteArgs> for BackupCoreDatabase {
"BackupCoreDatabase",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
)
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
if !user.admin {
return Err(
@@ -194,18 +186,14 @@ impl Resolve<ExecuteArgs> for GlobalAutoUpdate {
"GlobalAutoUpdate",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
)
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
if !user.admin {
return Err(
@@ -380,18 +368,14 @@ impl Resolve<ExecuteArgs> for RotateAllServerKeys {
"RotateAllServerKeys",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
)
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
if !user.admin {
return Err(
@@ -498,7 +482,7 @@ impl Resolve<ExecuteArgs> for RotateCoreKeys {
"RotateCoreKeys",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
force = self.force,
@@ -506,11 +490,7 @@ impl Resolve<ExecuteArgs> for RotateCoreKeys {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
if !user.admin {
return Err(
+21 -51
View File
@@ -49,9 +49,9 @@ mod sync;
use super::Variant;
pub struct ExecuteArgs {
/// The task id.
/// Unique for every '/execute' call.
pub task_id: Uuid,
/// The execution id.
/// Unique for every /execute call.
pub id: Uuid,
pub user: User,
pub update: Update,
}
@@ -60,7 +60,7 @@ pub struct ExecuteArgs {
#[derive(
Serialize, Deserialize, Debug, Clone, Resolve, EnumDiscriminants,
)]
#[strum_discriminants(name(ExecuteRequestMethod), derive(Display))]
#[strum_discriminants(name(ExecuteRequestVariant), derive(Display))]
#[args(ExecuteArgs)]
#[response(JsonString)]
#[error(mogh_error::Error)]
@@ -249,19 +249,11 @@ pub fn inner_handler(
async move {
let log = match handle.await {
Ok(Err(e)) => {
warn!(
api = "Execute",
task_id = task_id.to_string(),
"/execute request task error: {e:#}",
);
warn!("/execute request {task_id} task error: {e:#}",);
Log::error("Task Error", format_serror(&e.into()))
}
Err(e) => {
warn!(
api = "Execute",
task_id = task_id.to_string(),
"/execute request spawn error: {e:?}",
);
warn!("/execute request {task_id} spawn error: {e:?}",);
Log::error("Spawn Error", format!("{e:#?}"))
}
_ => return,
@@ -276,7 +268,7 @@ pub fn inner_handler(
find_one_by_id(&db_client().updates, &update_id)
.await
.context("Failed to query to db")?
.context("No Update exists with given id")?;
.context("No update exists with given id")?;
update.logs.push(log);
update.finalize();
update_update(update).await
@@ -285,10 +277,7 @@ pub fn inner_handler(
if let Err(e) = res {
warn!(
api = "Execute",
task_id = task_id.to_string(),
update_id,
"Failed to modify Update with task error log | {e:#}"
"Failed to update update with task error log | {e:#}"
);
}
}
@@ -304,44 +293,25 @@ async fn task(
user: User,
update: Update,
) -> anyhow::Result<String> {
let method: ExecuteRequestMethod = (&request).into();
let user_id = user.id.clone();
let username = user.username.clone();
let variant: ExecuteRequestVariant = (&request).into();
info!(
api = "Execute",
task_id = id.to_string(),
method = method.to_string(),
user_id,
username,
"EXECUTE REQUEST",
"EXECUTE REQUEST {id} | METHOD: {variant} | USER: {} ({})",
user.username, user.id
);
let res = match request
.resolve(&ExecuteArgs {
user,
update,
task_id: id,
})
.await
{
Err(e) => Err(e.error),
Ok(JsonString::Err(e)) => Err(
anyhow::Error::from(e).context("failed to serialize response"),
),
Ok(JsonString::Ok(res)) => Ok(res),
};
let res =
match request.resolve(&ExecuteArgs { user, update, id }).await {
Err(e) => Err(e.error),
Ok(JsonString::Err(e)) => Err(
anyhow::Error::from(e)
.context("failed to serialize response"),
),
Ok(JsonString::Ok(res)) => Ok(res),
};
if let Err(e) = &res {
warn!(
api = "Execute",
task_id = id.to_string(),
method = method.to_string(),
user_id,
username,
"EXECUTE REQUEST | ERROR: {e:#}"
);
warn!("EXECUTE REQUEST {id} | METHOD: {variant} | ERROR: {e:#}");
}
res
+2 -6
View File
@@ -59,7 +59,7 @@ impl Resolve<ExecuteArgs> for RunProcedure {
"RunProcedure",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
procedure = self.procedure,
@@ -67,11 +67,7 @@ impl Resolve<ExecuteArgs> for RunProcedure {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
Ok(
resolve_inner(self.procedure, user.clone(), update.clone())
+14 -30
View File
@@ -55,14 +55,14 @@ impl Resolve<ExecuteArgs> for BatchCloneRepo {
"BatchCloneRepo",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchCloneRepo>(&self.pattern, user)
@@ -76,7 +76,7 @@ impl Resolve<ExecuteArgs> for CloneRepo {
"CloneRepo",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
repo = self.repo,
@@ -84,11 +84,7 @@ impl Resolve<ExecuteArgs> for CloneRepo {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let mut repo = get_check_permissions::<Repo>(
&self.repo,
@@ -190,14 +186,14 @@ impl Resolve<ExecuteArgs> for BatchPullRepo {
"BatchPullRepo",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchPullRepo>(&self.pattern, user)
@@ -211,7 +207,7 @@ impl Resolve<ExecuteArgs> for PullRepo {
"PullRepo",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
repo = self.repo,
@@ -219,11 +215,7 @@ impl Resolve<ExecuteArgs> for PullRepo {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let mut repo = get_check_permissions::<Repo>(
&self.repo,
@@ -371,14 +363,14 @@ impl Resolve<ExecuteArgs> for BatchBuildRepo {
"BatchBuildRepo",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchBuildRepo>(&self.pattern, user)
@@ -392,7 +384,7 @@ impl Resolve<ExecuteArgs> for BuildRepo {
"BuildRepo",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
repo = self.repo,
@@ -400,11 +392,7 @@ impl Resolve<ExecuteArgs> for BuildRepo {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let mut repo = get_check_permissions::<Repo>(
&self.repo,
@@ -717,7 +705,7 @@ impl Resolve<ExecuteArgs> for CancelRepoBuild {
"CancelRepoBuild",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
repo = self.repo,
@@ -725,11 +713,7 @@ impl Resolve<ExecuteArgs> for CancelRepoBuild {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let repo = get_check_permissions::<Repo>(
&self.repo,
+64 -148
View File
@@ -14,7 +14,7 @@ use periphery_client::api;
use crate::{
helpers::{periphery_client, update::update_update},
monitor::refresh_server_cache,
monitor::update_cache_for_server,
permission::get_check_permissions,
state::action_states,
};
@@ -26,7 +26,7 @@ impl Resolve<ExecuteArgs> for StartContainer {
"StartContainer",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -35,11 +35,7 @@ impl Resolve<ExecuteArgs> for StartContainer {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -80,7 +76,7 @@ impl Resolve<ExecuteArgs> for StartContainer {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -94,7 +90,7 @@ impl Resolve<ExecuteArgs> for RestartContainer {
"RestartContainer",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -103,11 +99,7 @@ impl Resolve<ExecuteArgs> for RestartContainer {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -150,7 +142,7 @@ impl Resolve<ExecuteArgs> for RestartContainer {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -164,7 +156,7 @@ impl Resolve<ExecuteArgs> for PauseContainer {
"PauseContainer",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -173,11 +165,7 @@ impl Resolve<ExecuteArgs> for PauseContainer {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -218,7 +206,7 @@ impl Resolve<ExecuteArgs> for PauseContainer {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -232,7 +220,7 @@ impl Resolve<ExecuteArgs> for UnpauseContainer {
"UnpauseContainer",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -241,11 +229,7 @@ impl Resolve<ExecuteArgs> for UnpauseContainer {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -288,7 +272,7 @@ impl Resolve<ExecuteArgs> for UnpauseContainer {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -302,7 +286,7 @@ impl Resolve<ExecuteArgs> for StopContainer {
"StopContainer",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -313,11 +297,7 @@ impl Resolve<ExecuteArgs> for StopContainer {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -360,7 +340,7 @@ impl Resolve<ExecuteArgs> for StopContainer {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -374,7 +354,7 @@ impl Resolve<ExecuteArgs> for DestroyContainer {
"DestroyContainer",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -385,11 +365,7 @@ impl Resolve<ExecuteArgs> for DestroyContainer {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let DestroyContainer {
server,
@@ -440,7 +416,7 @@ impl Resolve<ExecuteArgs> for DestroyContainer {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -454,7 +430,7 @@ impl Resolve<ExecuteArgs> for StartAllContainers {
"StartAllContainers",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -462,11 +438,7 @@ impl Resolve<ExecuteArgs> for StartAllContainers {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -505,7 +477,7 @@ impl Resolve<ExecuteArgs> for StartAllContainers {
);
}
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -518,7 +490,7 @@ impl Resolve<ExecuteArgs> for RestartAllContainers {
"RestartAllContainers",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -526,11 +498,7 @@ impl Resolve<ExecuteArgs> for RestartAllContainers {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -571,7 +539,7 @@ impl Resolve<ExecuteArgs> for RestartAllContainers {
);
}
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -584,7 +552,7 @@ impl Resolve<ExecuteArgs> for PauseAllContainers {
"PauseAllContainers",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -592,11 +560,7 @@ impl Resolve<ExecuteArgs> for PauseAllContainers {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -635,7 +599,7 @@ impl Resolve<ExecuteArgs> for PauseAllContainers {
);
}
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -648,7 +612,7 @@ impl Resolve<ExecuteArgs> for UnpauseAllContainers {
"UnpauseAllContainers",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -656,11 +620,7 @@ impl Resolve<ExecuteArgs> for UnpauseAllContainers {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -701,7 +661,7 @@ impl Resolve<ExecuteArgs> for UnpauseAllContainers {
);
}
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -714,7 +674,7 @@ impl Resolve<ExecuteArgs> for StopAllContainers {
"StopAllContainers",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -722,11 +682,7 @@ impl Resolve<ExecuteArgs> for StopAllContainers {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -765,7 +721,7 @@ impl Resolve<ExecuteArgs> for StopAllContainers {
);
}
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -778,7 +734,7 @@ impl Resolve<ExecuteArgs> for PruneContainers {
"PruneContainers",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -786,11 +742,7 @@ impl Resolve<ExecuteArgs> for PruneContainers {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -833,7 +785,7 @@ impl Resolve<ExecuteArgs> for PruneContainers {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -847,7 +799,7 @@ impl Resolve<ExecuteArgs> for DeleteNetwork {
"DeleteNetwork",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -856,11 +808,7 @@ impl Resolve<ExecuteArgs> for DeleteNetwork {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -898,7 +846,7 @@ impl Resolve<ExecuteArgs> for DeleteNetwork {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -912,7 +860,7 @@ impl Resolve<ExecuteArgs> for PruneNetworks {
"PruneNetworks",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -920,11 +868,7 @@ impl Resolve<ExecuteArgs> for PruneNetworks {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -965,7 +909,7 @@ impl Resolve<ExecuteArgs> for PruneNetworks {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -979,7 +923,7 @@ impl Resolve<ExecuteArgs> for DeleteImage {
"DeleteImage",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -988,11 +932,7 @@ impl Resolve<ExecuteArgs> for DeleteImage {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -1027,7 +967,7 @@ impl Resolve<ExecuteArgs> for DeleteImage {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -1041,7 +981,7 @@ impl Resolve<ExecuteArgs> for PruneImages {
"PruneImages",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -1049,11 +989,7 @@ impl Resolve<ExecuteArgs> for PruneImages {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -1092,7 +1028,7 @@ impl Resolve<ExecuteArgs> for PruneImages {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -1106,7 +1042,7 @@ impl Resolve<ExecuteArgs> for DeleteVolume {
"DeleteVolume",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -1115,11 +1051,7 @@ impl Resolve<ExecuteArgs> for DeleteVolume {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -1157,7 +1089,7 @@ impl Resolve<ExecuteArgs> for DeleteVolume {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -1171,7 +1103,7 @@ impl Resolve<ExecuteArgs> for PruneVolumes {
"PruneVolumes",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -1179,11 +1111,7 @@ impl Resolve<ExecuteArgs> for PruneVolumes {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -1222,7 +1150,7 @@ impl Resolve<ExecuteArgs> for PruneVolumes {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -1236,7 +1164,7 @@ impl Resolve<ExecuteArgs> for PruneDockerBuilders {
"PruneDockerBuilders",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -1244,11 +1172,7 @@ impl Resolve<ExecuteArgs> for PruneDockerBuilders {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -1287,7 +1211,7 @@ impl Resolve<ExecuteArgs> for PruneDockerBuilders {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -1301,7 +1225,7 @@ impl Resolve<ExecuteArgs> for PruneBuildx {
"PruneBuildx",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -1309,11 +1233,7 @@ impl Resolve<ExecuteArgs> for PruneBuildx {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -1352,7 +1272,7 @@ impl Resolve<ExecuteArgs> for PruneBuildx {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -1366,7 +1286,7 @@ impl Resolve<ExecuteArgs> for PruneSystem {
"PruneSystem",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
server = self.server,
@@ -1374,11 +1294,7 @@ impl Resolve<ExecuteArgs> for PruneSystem {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let server = get_check_permissions::<Server>(
&self.server,
@@ -1416,7 +1332,7 @@ impl Resolve<ExecuteArgs> for PruneSystem {
};
update.logs.push(log);
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
+36 -76
View File
@@ -39,7 +39,7 @@ use crate::{
add_update_without_send, init_execution_update, update_update,
},
},
monitor::{refresh_server_cache, refresh_swarm_cache},
monitor::{update_cache_for_server, update_cache_for_swarm},
permission::get_check_permissions,
resource,
stack::{
@@ -69,14 +69,14 @@ impl Resolve<ExecuteArgs> for BatchDeployStack {
"BatchDeployStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchDeployStack>(&self.pattern, user)
@@ -90,7 +90,7 @@ impl Resolve<ExecuteArgs> for DeployStack {
"DeployStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -100,11 +100,7 @@ impl Resolve<ExecuteArgs> for DeployStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (mut stack, swarm_or_server) = setup_stack_execution(
&self.stack,
@@ -317,10 +313,10 @@ impl Resolve<ExecuteArgs> for DeployStack {
match swarm_or_server {
SwarmOrServer::None => unreachable!(),
SwarmOrServer::Swarm(swarm) => {
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
SwarmOrServer::Server(server) => {
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
}
}
@@ -346,14 +342,14 @@ impl Resolve<ExecuteArgs> for BatchDeployStackIfChanged {
"BatchDeployStackIfChanged",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchDeployStackIfChanged>(
@@ -370,7 +366,7 @@ impl Resolve<ExecuteArgs> for DeployStackIfChanged {
"DeployStackIfChanged",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -379,11 +375,7 @@ impl Resolve<ExecuteArgs> for DeployStackIfChanged {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let stack = get_check_permissions::<Stack>(
&self.stack,
@@ -441,7 +433,7 @@ impl Resolve<ExecuteArgs> for DeployStackIfChanged {
.resolve(&ExecuteArgs {
user: user.clone(),
update,
task_id: *task_id,
id: *id,
})
.await
}
@@ -580,7 +572,7 @@ async fn deploy_services(
.resolve(&ExecuteArgs {
user: user.clone(),
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
}
@@ -611,7 +603,7 @@ async fn restart_services(
.resolve(&ExecuteArgs {
user: user.clone(),
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
}
@@ -774,14 +766,14 @@ impl Resolve<ExecuteArgs> for BatchPullStack {
"BatchPullStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
Ok(
super::batch_execute::<BatchPullStack>(&self.pattern, user)
@@ -886,7 +878,7 @@ pub async fn pull_stack_inner(
.await?;
// Ensure cached stack state up to date by updating server cache
refresh_server_cache(server, true).await;
update_cache_for_server(server, true).await;
Ok(res)
}
@@ -896,7 +888,7 @@ impl Resolve<ExecuteArgs> for PullStack {
"PullStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -905,11 +897,7 @@ impl Resolve<ExecuteArgs> for PullStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (stack, swarm_or_server) = setup_stack_execution(
&self.stack,
@@ -971,7 +959,7 @@ impl Resolve<ExecuteArgs> for StartStack {
"StartStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -980,11 +968,7 @@ impl Resolve<ExecuteArgs> for StartStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
execute_compose::<StartStack>(
&self.stack,
@@ -1004,7 +988,7 @@ impl Resolve<ExecuteArgs> for RestartStack {
"RestartStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -1013,11 +997,7 @@ impl Resolve<ExecuteArgs> for RestartStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
execute_compose::<RestartStack>(
&self.stack,
@@ -1039,7 +1019,7 @@ impl Resolve<ExecuteArgs> for PauseStack {
"PauseStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -1048,11 +1028,7 @@ impl Resolve<ExecuteArgs> for PauseStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
execute_compose::<PauseStack>(
&self.stack,
@@ -1072,7 +1048,7 @@ impl Resolve<ExecuteArgs> for UnpauseStack {
"UnpauseStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -1081,11 +1057,7 @@ impl Resolve<ExecuteArgs> for UnpauseStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
execute_compose::<UnpauseStack>(
&self.stack,
@@ -1105,7 +1077,7 @@ impl Resolve<ExecuteArgs> for StopStack {
"StopStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -1114,11 +1086,7 @@ impl Resolve<ExecuteArgs> for StopStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
execute_compose::<StopStack>(
&self.stack,
@@ -1150,14 +1118,14 @@ impl Resolve<ExecuteArgs> for BatchDestroyStack {
"BatchDestroyStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
pattern = self.pattern,
)
)]
async fn resolve(
self,
ExecuteArgs { user, task_id, .. }: &ExecuteArgs,
ExecuteArgs { user, id, .. }: &ExecuteArgs,
) -> mogh_error::Result<BatchExecutionResponse> {
super::batch_execute::<BatchDestroyStack>(&self.pattern, user)
.await
@@ -1170,7 +1138,7 @@ impl Resolve<ExecuteArgs> for DestroyStack {
"DestroyStack",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -1181,11 +1149,7 @@ impl Resolve<ExecuteArgs> for DestroyStack {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (stack, swarm_or_server) = setup_stack_execution(
&self.stack,
@@ -1241,7 +1205,7 @@ impl Resolve<ExecuteArgs> for DestroyStack {
}
// Ensure cached stack state up to date by updating swarm cache
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
update.finalize();
update_update(update.clone()).await?;
@@ -1269,7 +1233,7 @@ impl Resolve<ExecuteArgs> for RunStackService {
"RunStackService",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
stack = self.stack,
@@ -1279,11 +1243,7 @@ impl Resolve<ExecuteArgs> for RunStackService {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let (mut stack, swarm_or_server) = setup_stack_execution(
&self.stack,
+28 -64
View File
@@ -12,7 +12,7 @@ use mogh_resolver::Resolve;
use crate::{
api::execute::ExecuteArgs,
helpers::{swarm::swarm_request, update::update_update},
monitor::refresh_swarm_cache,
monitor::update_cache_for_swarm,
permission::get_check_permissions,
};
@@ -21,7 +21,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmNodes {
"RemoveSwarmNodes",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -31,11 +31,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmNodes {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -59,7 +55,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmNodes {
{
Ok(log) => {
update.logs.push(log);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Remove Swarm Nodes",
@@ -81,7 +77,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmStacks {
"RemoveSwarmStacks",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -91,11 +87,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmStacks {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -119,7 +111,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmStacks {
{
Ok(log) => {
update.logs.push(log);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Remove Swarm Stacks",
@@ -141,7 +133,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmServices {
"RemoveSwarmServices",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -150,11 +142,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmServices {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -177,7 +165,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmServices {
{
Ok(log) => {
update.logs.push(log);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Remove Swarm Services",
@@ -199,7 +187,7 @@ impl Resolve<ExecuteArgs> for CreateSwarmConfig {
"CreateSwarmConfig",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -208,11 +196,7 @@ impl Resolve<ExecuteArgs> for CreateSwarmConfig {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -238,7 +222,7 @@ impl Resolve<ExecuteArgs> for CreateSwarmConfig {
{
Ok(log) => {
update.logs.push(log);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Create Swarm Config",
@@ -260,7 +244,7 @@ impl Resolve<ExecuteArgs> for RotateSwarmConfig {
"RotateSwarmConfig",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -269,11 +253,7 @@ impl Resolve<ExecuteArgs> for RotateSwarmConfig {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -297,7 +277,7 @@ impl Resolve<ExecuteArgs> for RotateSwarmConfig {
{
Ok(logs) => {
update.logs.extend(logs);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Rotate Swarm Config",
@@ -319,7 +299,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmConfigs {
"RemoveSwarmConfigs",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -328,11 +308,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmConfigs {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -355,7 +331,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmConfigs {
{
Ok(log) => {
update.logs.push(log);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Remove Swarm Configs",
@@ -377,7 +353,7 @@ impl Resolve<ExecuteArgs> for CreateSwarmSecret {
"CreateSwarmSecret",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -386,11 +362,7 @@ impl Resolve<ExecuteArgs> for CreateSwarmSecret {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -417,7 +389,7 @@ impl Resolve<ExecuteArgs> for CreateSwarmSecret {
{
Ok(log) => {
update.logs.push(log);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Create Swarm Secret",
@@ -439,7 +411,7 @@ impl Resolve<ExecuteArgs> for RotateSwarmSecret {
"RotateSwarmSecret",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -448,11 +420,7 @@ impl Resolve<ExecuteArgs> for RotateSwarmSecret {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -476,7 +444,7 @@ impl Resolve<ExecuteArgs> for RotateSwarmSecret {
{
Ok(logs) => {
update.logs.extend(logs);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Rotate Swarm Secret",
@@ -498,7 +466,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmSecrets {
"RemoveSwarmSecrets",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
swarm = self.swarm,
@@ -507,11 +475,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmSecrets {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> Result<Self::Response, Self::Error> {
let swarm = get_check_permissions::<Swarm>(
&self.swarm,
@@ -534,7 +498,7 @@ impl Resolve<ExecuteArgs> for RemoveSwarmSecrets {
{
Ok(log) => {
update.logs.push(log);
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
Err(e) => update.push_error_log(
"Remove Swarm Secrets",
+182 -79
View File
@@ -21,7 +21,6 @@ use komodo_client::{
repo::Repo,
server::Server,
stack::Stack,
swarm::Swarm,
sync::ResourceSync,
update::{Log, Update},
user::sync_user,
@@ -54,7 +53,7 @@ impl Resolve<ExecuteArgs> for RunSync {
"RunSync",
skip_all,
fields(
task_id = task_id.to_string(),
id = id.to_string(),
operator = user.id,
update_id = update.id,
sync = self.sync,
@@ -64,11 +63,7 @@ impl Resolve<ExecuteArgs> for RunSync {
)]
async fn resolve(
self,
ExecuteArgs {
user,
update,
task_id,
}: &ExecuteArgs,
ExecuteArgs { user, update, id }: &ExecuteArgs,
) -> mogh_error::Result<Update> {
let RunSync {
sync,
@@ -139,36 +134,56 @@ impl Resolve<ExecuteArgs> for RunSync {
let Some(resource_type) = match_resource_type else {
return Some(name_or_id);
};
macro_rules! resolve_id_to_name {
($(($Variant:ident, $field:ident)),* $(,)?) => {
match ObjectId::from_str(&name_or_id) {
Ok(_) => match resource_type {
$(
ResourceTargetVariant::$Variant => all_resources
.$field
.get(&name_or_id)
.map(|r| r.name.clone()),
)*
ResourceTargetVariant::System => None,
},
Err(_) => Some(name_or_id),
}
};
match ObjectId::from_str(&name_or_id) {
Ok(_) => match resource_type {
ResourceTargetVariant::Swarm => all_resources
.swarms
.get(&name_or_id)
.map(|s| s.name.clone()),
ResourceTargetVariant::Server => all_resources
.servers
.get(&name_or_id)
.map(|s| s.name.clone()),
ResourceTargetVariant::Stack => all_resources
.stacks
.get(&name_or_id)
.map(|s| s.name.clone()),
ResourceTargetVariant::Deployment => all_resources
.deployments
.get(&name_or_id)
.map(|d| d.name.clone()),
ResourceTargetVariant::Build => all_resources
.builds
.get(&name_or_id)
.map(|b| b.name.clone()),
ResourceTargetVariant::Repo => all_resources
.repos
.get(&name_or_id)
.map(|r| r.name.clone()),
ResourceTargetVariant::Procedure => all_resources
.procedures
.get(&name_or_id)
.map(|p| p.name.clone()),
ResourceTargetVariant::Action => all_resources
.actions
.get(&name_or_id)
.map(|p| p.name.clone()),
ResourceTargetVariant::ResourceSync => all_resources
.syncs
.get(&name_or_id)
.map(|s| s.name.clone()),
ResourceTargetVariant::Builder => all_resources
.builders
.get(&name_or_id)
.map(|b| b.name.clone()),
ResourceTargetVariant::Alerter => all_resources
.alerters
.get(&name_or_id)
.map(|a| a.name.clone()),
ResourceTargetVariant::System => None,
},
Err(_) => Some(name_or_id),
}
// New resource types need to be added here manually.
resolve_id_to_name!(
(Server, servers),
(Swarm, swarms),
(Stack, stacks),
(Deployment, deployments),
(Build, builds),
(Repo, repos),
(Procedure, procedures),
(Action, actions),
(ResourceSync, syncs),
(Builder, builders),
(Alerter, alerters),
)
})
.collect::<Vec<_>>()
});
@@ -216,39 +231,136 @@ impl Resolve<ExecuteArgs> for RunSync {
let delete = sync.config.managed || sync.config.delete;
macro_rules! get_deltas {
($(($var:ident, $Type:ident, $field:ident)),* $(,)?) => {
$(
let $var = if sync.config.include_resources {
get_updates_for_execution::<$Type>(
resources.$field,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
)*
};
}
// New resource types need to be added here manually.
get_deltas!(
(server_deltas, Server, servers),
(swarm_deltas, Swarm, swarms),
(stack_deltas, Stack, stacks),
(deployment_deltas, Deployment, deployments),
(build_deltas, Build, builds),
(repo_deltas, Repo, repos),
(procedure_deltas, Procedure, procedures),
(action_deltas, Action, actions),
(builder_deltas, Builder, builders),
(alerter_deltas, Alerter, alerters),
(resource_sync_deltas, ResourceSync, resource_syncs),
);
let server_deltas = if sync.config.include_resources {
get_updates_for_execution::<Server>(
resources.servers,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let stack_deltas = if sync.config.include_resources {
get_updates_for_execution::<Stack>(
resources.stacks,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let deployment_deltas = if sync.config.include_resources {
get_updates_for_execution::<Deployment>(
resources.deployments,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let build_deltas = if sync.config.include_resources {
get_updates_for_execution::<Build>(
resources.builds,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let repo_deltas = if sync.config.include_resources {
get_updates_for_execution::<Repo>(
resources.repos,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let procedure_deltas = if sync.config.include_resources {
get_updates_for_execution::<Procedure>(
resources.procedures,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let action_deltas = if sync.config.include_resources {
get_updates_for_execution::<Action>(
resources.actions,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let builder_deltas = if sync.config.include_resources {
get_updates_for_execution::<Builder>(
resources.builders,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let alerter_deltas = if sync.config.include_resources {
get_updates_for_execution::<Alerter>(
resources.alerters,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let resource_sync_deltas = if sync.config.include_resources {
get_updates_for_execution::<entities::sync::ResourceSync>(
resources.resource_syncs,
delete,
match_resource_type,
match_resources.as_deref(),
&id_to_tags,
&sync.config.match_tags,
)
.await?
} else {
Default::default()
};
let (
variables_to_create,
@@ -286,7 +398,6 @@ impl Resolve<ExecuteArgs> for RunSync {
if deploy_cache.is_empty()
&& resource_sync_deltas.no_changes()
&& server_deltas.no_changes()
&& swarm_deltas.no_changes()
&& deployment_deltas.no_changes()
&& stack_deltas.no_changes()
&& build_deltas.no_changes()
@@ -314,11 +425,7 @@ impl Resolve<ExecuteArgs> for RunSync {
return Ok(update);
}
// =====================================================
// The ordering these are executed does matter, since
// latter resources may depend on prior synced resources
// already being updated with the declared state.
// =====================================================
// =================
// No deps
maybe_extend(
@@ -357,10 +464,6 @@ impl Resolve<ExecuteArgs> for RunSync {
);
// Dependent on server
maybe_extend(
&mut update.logs,
Swarm::execute_sync_updates(swarm_deltas).await,
);
maybe_extend(
&mut update.logs,
Builder::execute_sync_updates(builder_deltas).await,
+9 -9
View File
@@ -79,7 +79,7 @@ pub async fn handle_build_webhook<B: super::ExtractBranch>(
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -121,7 +121,7 @@ impl RepoExecution for CloneRepo {
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -145,7 +145,7 @@ impl RepoExecution for PullRepo {
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -169,7 +169,7 @@ impl RepoExecution for BuildRepo {
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -272,7 +272,7 @@ impl StackExecution for DeployStack {
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -290,7 +290,7 @@ impl StackExecution for DeployStack {
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -403,7 +403,7 @@ impl SyncExecution for RunSync {
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -517,7 +517,7 @@ pub async fn handle_procedure_webhook<B: super::ExtractBranch>(
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
@@ -583,7 +583,7 @@ pub async fn handle_action_webhook<B: super::ExtractBranch>(
.resolve(&ExecuteArgs {
user,
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
.map_err(|e| e.error)?;
-23
View File
@@ -222,31 +222,8 @@ where
.status_code(StatusCode::BAD_REQUEST)?;
P::verify_secret(headers, body, R::custom_secret(&resource))
.status_code(StatusCode::UNAUTHORIZED)?;
info!(
resource_type = R::resource_type().to_string(),
resource_id = id,
source_ip = ip.to_string(),
"Successfully authenticated incoming webhook"
);
debug!(
resource_type = R::resource_type().to_string(),
resource_id = id,
source_ip = ip.to_string(),
"Webhook body: {body}"
);
mogh_error::Result::Ok(resource)
}
.with_failure_rate_limit_using_ip(&GENERAL_RATE_LIMITER, &ip)
.await
.inspect_err(|e| {
warn!(
resource_id = id,
source_ip = ip.to_string(),
"Incoming webhook failed | ERROR: {:#}",
e.error
);
})
}
+5 -15
View File
@@ -70,7 +70,7 @@ pub struct ReadArgs {
#[derive(
Serialize, Deserialize, Debug, Clone, Resolve, EnumDiscriminants,
)]
#[strum_discriminants(name(ReadRequestMethod), derive(Display))]
#[strum_discriminants(name(ReadRequestVariant), derive(Display))]
#[args(ReadArgs)]
#[response(Response)]
#[error(mogh_error::Error)]
@@ -291,28 +291,18 @@ async fn handler(
Json(request): Json<ReadRequest>,
) -> mogh_error::Result<axum::response::Response> {
let req_id = Uuid::new_v4();
let method: ReadRequestMethod = (&request).into();
let user_id = user.id.clone();
let username = user.username.clone();
let variant: ReadRequestVariant = (&request).into();
trace!(
req_id = req_id.to_string(),
method = method.to_string(),
user_id,
username,
"READ REQUEST",
"READ REQUEST {req_id} | METHOD: {variant} | USER: {} ({})",
user.username, user.id
);
let res = request.resolve(&ReadArgs { user }).await;
if let Err(e) = &res {
trace!(
req_id = req_id.to_string(),
method = method.to_string(),
user_id,
username,
"READ REQUEST | ERROR: {:#}",
"READ REQUEST {req_id} | METHOD: {variant} | ERROR: {:#}",
e.error
);
}
+1 -1
View File
@@ -120,7 +120,7 @@ impl Resolve<ReadArgs> for GetResourceSyncsSummary {
for resource_sync in resource_syncs {
res.total += 1;
if !(resource_sync.info.pending_deploys.is_empty()
if !(resource_sync.info.pending_deploy.to_deploy == 0
&& resource_sync.info.resource_updates.is_empty()
&& resource_sync.info.variable_updates.is_empty()
&& resource_sync.info.user_group_updates.is_empty())
+326 -100
View File
@@ -38,45 +38,122 @@ async fn get_all_targets(
user: &User,
) -> anyhow::Result<Vec<ResourceTarget>> {
let mut targets = Vec::<ResourceTarget>::new();
let all_tags = if tags.is_empty() {
vec![]
} else {
get_all_tags(None).await?
};
macro_rules! extend_targets {
($($Type:ident),* $(,)?) => {
$(
targets.extend(
resource::list_full_for_user::<$Type>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::$Type(resource.id)),
);
)*
};
}
extend_targets!(
Alerter,
Builder,
Server,
Swarm,
Stack,
Deployment,
Build,
Repo,
Procedure,
Action,
ResourceSync,
targets.extend(
resource::list_full_for_user::<Alerter>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Alerter(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Builder>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Builder(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Server>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Server(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Stack>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Stack(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Deployment>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Deployment(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Build>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Build(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Repo>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Repo(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Procedure>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Procedure(resource.id)),
);
targets.extend(
resource::list_full_for_user::<Action>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
.map(|resource| ResourceTarget::Action(resource.id)),
);
targets.extend(
resource::list_full_for_user::<ResourceSync>(
ResourceQuery::builder().tags(tags).build(),
user,
PermissionLevel::Read.into(),
&all_tags,
)
.await?
.into_iter()
// These will already be filtered by [ExportResourcesToToml]
.map(|resource| ResourceTarget::ResourceSync(resource.id)),
);
Ok(targets)
}
@@ -110,7 +187,6 @@ impl Resolve<ReadArgs> for ExportAllResourcesToToml {
targets,
user_groups,
include_variables: self.include_variables,
existing: self.existing,
}
.resolve(args)
.await
@@ -126,64 +202,131 @@ impl Resolve<ReadArgs> for ExportResourcesToToml {
targets,
user_groups,
include_variables,
existing,
} = self;
let mut res = ResourcesToml::default();
let id_to_tags = get_id_to_tags(None).await?;
let ReadArgs { user } = args;
macro_rules! convert_target {
($id:expr, $Type:ident, $field:ident) => {{
let mut resource = get_check_permissions::<$Type>(
&$id,
user,
PermissionLevel::Read.into(),
)
.await?;
$Type::replace_ids(&mut resource);
let (deploy, after) = existing
.as_ref()
.and_then(|e| {
e.$field.iter().find(|r| r.name == resource.name)
})
.map(|r| (r.deploy, r.after.clone()))
.unwrap_or_default();
res.$field.push(convert_resource::<$Type>(
resource,
deploy,
after,
&id_to_tags,
));
}};
}
for target in targets {
match target {
ResourceTarget::Server(id) => {
convert_target!(id, Server, servers)
}
ResourceTarget::Swarm(id) => {
convert_target!(id, Swarm, swarms)
let mut swarm = get_check_permissions::<Swarm>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Swarm::replace_ids(&mut swarm);
res.swarms.push(convert_resource::<Swarm>(
swarm,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::Server(id) => {
let mut server = get_check_permissions::<Server>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Server::replace_ids(&mut server);
res.servers.push(convert_resource::<Server>(
server,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::Stack(id) => {
convert_target!(id, Stack, stacks)
let mut stack = get_check_permissions::<Stack>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Stack::replace_ids(&mut stack);
res.stacks.push(convert_resource::<Stack>(
stack,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::Deployment(id) => {
convert_target!(id, Deployment, deployments)
let mut deployment = get_check_permissions::<Deployment>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Deployment::replace_ids(&mut deployment);
res.deployments.push(convert_resource::<Deployment>(
deployment,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::Build(id) => {
convert_target!(id, Build, builds)
let mut build = get_check_permissions::<Build>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Build::replace_ids(&mut build);
res.builds.push(convert_resource::<Build>(
build,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::Repo(id) => {
let mut repo = get_check_permissions::<Repo>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Repo::replace_ids(&mut repo);
res.repos.push(convert_resource::<Repo>(
repo,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::Repo(id) => convert_target!(id, Repo, repos),
ResourceTarget::Procedure(id) => {
convert_target!(id, Procedure, procedures)
let mut procedure = get_check_permissions::<Procedure>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Procedure::replace_ids(&mut procedure);
res.procedures.push(convert_resource::<Procedure>(
procedure,
false,
vec![],
&id_to_tags,
));
}
ResourceTarget::Action(id) => {
convert_target!(id, Action, actions)
}
ResourceTarget::Builder(id) => {
convert_target!(id, Builder, builders)
}
ResourceTarget::Alerter(id) => {
convert_target!(id, Alerter, alerters)
let mut action = get_check_permissions::<Action>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Action::replace_ids(&mut action);
res.actions.push(convert_resource::<Action>(
action,
false,
vec![],
&id_to_tags,
));
}
ResourceTarget::ResourceSync(id) => {
let mut sync = get_check_permissions::<ResourceSync>(
@@ -206,6 +349,36 @@ impl Resolve<ReadArgs> for ExportResourcesToToml {
))
}
}
ResourceTarget::Builder(id) => {
let mut builder = get_check_permissions::<Builder>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Builder::replace_ids(&mut builder);
res.builders.push(convert_resource::<Builder>(
builder,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::Alerter(id) => {
let mut alerter = get_check_permissions::<Alerter>(
&id,
user,
PermissionLevel::Read.into(),
)
.await?;
Alerter::replace_ids(&mut alerter);
res.alerters.push(convert_resource::<Alerter>(
alerter,
false,
vec![],
&id_to_tags,
))
}
ResourceTarget::System(_) => continue,
};
}
@@ -261,32 +434,85 @@ fn serialize_resources_toml(
) -> anyhow::Result<String> {
let mut toml = String::new();
macro_rules! serialize_resources {
($(($Type:ident, $field:ident, $header:literal)),* $(,)?) => {
$(
for resource in resources.$field {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str(concat!("[[",$header,"]]\n"));
$Type::push_to_toml_string(resource, &mut toml)?;
}
)*
};
for server in resources.servers {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[server]]\n");
Server::push_to_toml_string(server, &mut toml)?;
}
for stack in resources.stacks {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[stack]]\n");
Stack::push_to_toml_string(stack, &mut toml)?;
}
for deployment in resources.deployments {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[deployment]]\n");
Deployment::push_to_toml_string(deployment, &mut toml)?;
}
for build in resources.builds {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[build]]\n");
Build::push_to_toml_string(build, &mut toml)?;
}
for repo in resources.repos {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[repo]]\n");
Repo::push_to_toml_string(repo, &mut toml)?;
}
for procedure in resources.procedures {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[procedure]]\n");
Procedure::push_to_toml_string(procedure, &mut toml)?;
}
for action in resources.actions {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[action]]\n");
Action::push_to_toml_string(action, &mut toml)?;
}
for alerter in resources.alerters {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[alerter]]\n");
Alerter::push_to_toml_string(alerter, &mut toml)?;
}
for builder in resources.builders {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[builder]]\n");
Builder::push_to_toml_string(builder, &mut toml)?;
}
for resource_sync in resources.resource_syncs {
if !toml.is_empty() {
toml.push_str("\n\n##\n\n");
}
toml.push_str("[[resource_sync]]\n");
ResourceSync::push_to_toml_string(resource_sync, &mut toml)?;
}
serialize_resources!(
(Server, servers, "server"),
(Swarm, swarms, "swarm"),
(Stack, stacks, "stack"),
(Deployment, deployments, "deployment"),
(Build, builds, "build"),
(Repo, repos, "repo"),
(Procedure, procedures, "procedure"),
(Action, actions, "action"),
(Alerter, alerters, "alerter"),
(Builder, builders, "builder"),
(ResourceSync, resource_syncs, "resource_sync"),
);
for variable in &resources.variables {
if !toml.is_empty() {
+1 -12
View File
@@ -71,20 +71,9 @@ impl Resolve<ReadArgs> for ListUsers {
anyhow!("this route is only accessable by admins").into(),
);
}
let filter = match self.service_users {
komodo_client::api::read::ServiceUserQueryBehavior::Include => {
None
}
komodo_client::api::read::ServiceUserQueryBehavior::Exclude => {
Some(doc! { "config.type": { "$ne": "Service" } })
}
komodo_client::api::read::ServiceUserQueryBehavior::Only => {
Some(doc! { "config.type": "Service" })
}
};
let mut users = find_collect(
&db_client().users,
filter,
None,
FindOptions::builder().sort(doc! { "username": 1 }).build(),
)
.await
+2 -2
View File
@@ -436,7 +436,7 @@ pub async fn check_deployment_for_update_inner(
update_available: false,
});
}
let domain = extract_registry_domain(image)?;
let domain = extract_registry_domain(&image)?;
let account =
optional_string(&deployment.config.image_registry_account);
let token = if let Some(account) = &account {
@@ -458,7 +458,7 @@ pub async fn check_deployment_for_update_inner(
};
let latest_digest = image_digest_cache()
.get(swarm_or_server, image, account, token)
.get(&swarm_or_server, &image, account, token)
.await?;
resource::update_info::<Deployment>(
+8 -24
View File
@@ -54,7 +54,7 @@ pub struct WriteArgs {
#[derive(
Serialize, Deserialize, Debug, Clone, Resolve, EnumDiscriminants,
)]
#[strum_discriminants(name(WriteRequestMethod), derive(Display))]
#[strum_discriminants(name(WriteRequestVariant), derive(Display))]
#[args(WriteArgs)]
#[response(Response)]
#[error(mogh_error::Error)]
@@ -255,35 +255,19 @@ async fn task(
request: WriteRequest,
user: User,
) -> mogh_error::Result<axum::response::Response> {
let task_id = Uuid::new_v4();
let method: WriteRequestMethod = (&request).into();
let req_id = Uuid::new_v4();
let variant: WriteRequestVariant = (&request).into();
let user_id = user.id.clone();
let username = user.username.clone();
if !matches!(
request,
WriteRequest::SetLastSeenUpdate(_)
| WriteRequest::PushRecentlyViewed(_)
) {
info!(
task_id = task_id.to_string(),
method = method.to_string(),
user_id,
username,
"WRITE REQUEST",
);
}
info!(
"WRITE REQUEST {req_id} | METHOD: {variant} | USER: {} ({})",
user.username, user.id
);
let res = request.resolve(&WriteArgs { user }).await;
if let Err(e) = &res {
warn!(
task_id = task_id.to_string(),
method = method.to_string(),
user_id,
username,
"WRITE REQUEST | ERROR: {:#}",
"WRITE REQUEST {req_id} | METHOD: {variant} | ERROR: {:#}",
e.error
);
}
+5 -38
View File
@@ -15,10 +15,7 @@ use mogh_pki::EncodedKeyPair;
use mogh_resolver::Resolve;
use reqwest::StatusCode;
use crate::{
api::write::WriteArgs, helpers::query::get_all_tags,
state::db_client,
};
use crate::{api::write::WriteArgs, state::db_client};
//
@@ -56,21 +53,6 @@ impl Resolve<WriteArgs> for CreateOnboardingKey {
)?
.public
.into_inner();
let tags = if self.tags.is_empty() {
self.tags
} else {
// fix_tags by ensuring existence, and force replace with tag name.
let all_tags = get_all_tags(None).await?;
self
.tags
.into_iter()
.filter_map(|tag| {
let tag =
all_tags.iter().find(|t| t.id == tag || t.name == tag)?;
Some(tag.name.clone())
})
.collect()
};
let onboarding_key = OnboardingKey {
public_key,
name: self.name,
@@ -78,8 +60,8 @@ impl Resolve<WriteArgs> for CreateOnboardingKey {
onboarded: Default::default(),
created_at: komodo_timestamp(),
expires: self.expires,
tags,
privileged: self.privileged,
tags: self.tags,
fix_existing_servers: self.fix_existing_servers,
copy_server: self.copy_server,
create_builder: self.create_builder,
};
@@ -157,26 +139,11 @@ impl Resolve<WriteArgs> for UpdateOnboardingKey {
}
if let Some(tags) = self.tags {
let tags = if tags.is_empty() {
tags
} else {
// fix_tags by ensuring existence, and force replace with tag name.
let all_tags = get_all_tags(None).await?;
tags
.into_iter()
.filter_map(|tag| {
let tag = all_tags
.iter()
.find(|t| t.id == tag || t.name == tag)?;
Some(tag.name.clone())
})
.collect()
};
update.insert("tags", tags);
}
if let Some(privileged) = self.privileged {
update.insert("privileged", privileged);
if let Some(fix_existing_servers) = self.fix_existing_servers {
update.insert("fix_existing_servers", fix_existing_servers);
}
if let Some(copy_server) = self.copy_server {
+3 -12
View File
@@ -563,16 +563,7 @@ impl Resolve<WriteArgs> for RefreshStackCache {
(services, Some(contents), Some(errors), None, None)
} else {
// This path is reached if the swarm / server is not available.
// It carries over the last successful poll.
(
stack.info.latest_services,
stack.info.remote_contents,
stack.info.remote_errors,
// Files on host can set hash / message back to None.
None,
None,
)
(vec![], None, None, None, None)
}
} else if !repo_empty {
// ================
@@ -780,7 +771,7 @@ pub async fn check_stack_for_update_inner(
service.image_digest = None;
continue;
}
match cache.get(swarm_or_server, image, None, None).await {
match cache.get(&swarm_or_server, image, None, None).await {
Ok(digest) => service.image_digest = Some(digest),
Err(e) => {
warn!(
@@ -870,7 +861,7 @@ pub async fn check_stack_for_update_inner(
};
service_with_update.update_available =
latest_digest.update_available(current_digests);
latest_digest.update_available(&current_digests);
if service_with_update.update_available
&& (skip_auto_update || !stack.config.auto_update)
+105 -46
View File
@@ -26,8 +26,7 @@ use komodo_client::{
repo::Repo,
server::Server,
stack::Stack,
swarm::Swarm,
sync::{ResourceSync, ResourceSyncInfo},
sync::{ResourceSync, ResourceSyncInfo, SyncDeployUpdate},
to_path_compatible_name,
update::{Log, Update},
user::sync_user,
@@ -516,20 +515,11 @@ impl Resolve<WriteArgs> for CommitSync {
None
};
// Get the latest existing resources to preserve any meta values
let RemoteResources { resources, .. } =
crate::sync::remote::get_remote_resources(&sync, repo.as_ref())
.await
.context("failed to get remote resources")?;
let res = ExportAllResourcesToToml {
include_resources: sync.config.include_resources,
tags: sync.config.match_tags.clone(),
include_variables: sync.config.include_variables,
include_user_groups: sync.config.include_user_groups,
existing: resources
.inspect_err(|e| warn!("Existing resource TOML is unavailable, resource meta will not be preserved | ERROR: {e:#}"))
.ok(),
}
.resolve(&ReadArgs {
user: sync_user().to_owned(),
@@ -785,40 +775,110 @@ impl Resolve<WriteArgs> for RefreshResourceSyncPending {
let mut diffs = Vec::new();
macro_rules! push_updates {
($(($Type:ident, $field:ident)),* $(,)?) => {
$(
push_updates_for_view::<$Type>(
resources.$field,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
)*
};
}
// New resource types need to be added here manually.
push_updates!(
(Server, servers),
(Swarm, swarms),
(Stack, stacks),
(Deployment, deployments),
(Build, builds),
(Repo, repos),
(Procedure, procedures),
(Action, actions),
(Builder, builders),
(Alerter, alerters),
(ResourceSync, resource_syncs),
);
push_updates_for_view::<Server>(
resources.servers,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Stack>(
resources.stacks,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Deployment>(
resources.deployments,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Build>(
resources.builds,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Repo>(
resources.repos,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Procedure>(
resources.procedures,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Action>(
resources.actions,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Builder>(
resources.builders,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<Alerter>(
resources.alerters,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
push_updates_for_view::<ResourceSync>(
resources.resource_syncs,
delete,
None,
None,
&id_to_tags,
&sync.config.match_tags,
&mut diffs,
)
.await?;
(diffs, deploy_updates)
} else {
Default::default()
(Vec::new(), SyncDeployUpdate::default())
};
let variable_updates = if sync.config.include_variables {
@@ -852,7 +912,7 @@ impl Resolve<WriteArgs> for RefreshResourceSyncPending {
let (
resource_updates,
(pending_deploys, pending_deploy_error),
deploy_updates,
variable_updates,
user_group_updates,
pending_error,
@@ -868,7 +928,7 @@ impl Resolve<WriteArgs> for RefreshResourceSyncPending {
};
let has_updates = !resource_updates.is_empty()
|| !pending_deploys.is_empty()
|| !deploy_updates.to_deploy == 0
|| !variable_updates.is_empty()
|| !user_group_updates.is_empty();
@@ -880,8 +940,7 @@ impl Resolve<WriteArgs> for RefreshResourceSyncPending {
remote_errors: sync.info.remote_errors,
pending_hash: sync.info.pending_hash,
pending_message: sync.info.pending_message,
pending_deploys,
pending_deploy_error,
pending_deploy: deploy_updates,
resource_updates,
variable_updates,
user_group_updates,
+15 -29
View File
@@ -3,12 +3,8 @@ use futures_util::{StreamExt as _, stream::FuturesUnordered};
use komodo_client::{
api::write::*,
entities::{
NoData,
deployment::Deployment,
permission::PermissionLevel,
server::Server,
stack::Stack,
terminal::{Terminal, TerminalTarget},
NoData, deployment::Deployment, permission::PermissionLevel,
server::Server, stack::Stack, terminal::TerminalTarget,
user::User,
},
};
@@ -51,35 +47,30 @@ impl Resolve<WriteArgs> for CreateTerminal {
async fn resolve(
self,
WriteArgs { user }: &WriteArgs,
) -> mogh_error::Result<Terminal> {
) -> mogh_error::Result<NoData> {
match self.target.clone() {
TerminalTarget::Server { server } => {
let server = server
.context("Must provide 'target.params.server'")
.status_code(StatusCode::BAD_REQUEST)?;
create_server_terminal(self, server, user)
.await
.map_err(Into::into)
create_server_terminal(self, server, user).await?;
}
TerminalTarget::Container { server, container } => {
create_container_terminal(self, server, container, user)
.await
.map_err(Into::into)
.await?;
}
TerminalTarget::Stack { stack, service } => {
let service = service
.context("Must provide 'target.params.service'")
.status_code(StatusCode::BAD_REQUEST)?;
create_stack_service_terminal(self, stack, service, user)
.await
.map_err(Into::into)
.await?;
}
TerminalTarget::Deployment { deployment } => {
create_deployment_terminal(self, deployment, user)
.await
.map_err(Into::into)
create_deployment_terminal(self, deployment, user).await?;
}
}
};
Ok(NoData {})
}
}
@@ -93,7 +84,7 @@ async fn create_server_terminal(
}: CreateTerminal,
server: String,
user: &User,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<()> {
let server = get_check_permissions::<Server>(
&server,
user,
@@ -103,7 +94,7 @@ async fn create_server_terminal(
let periphery = periphery_client(&server).await?;
let mut terminal = periphery
periphery
.request(api::terminal::CreateServerTerminal {
name,
command,
@@ -112,12 +103,7 @@ async fn create_server_terminal(
.await
.context("Failed to create Server Terminal on Periphery")?;
// Fix server terminal target with server id
terminal.target = TerminalTarget::Server {
server: Some(server.id),
};
Ok(terminal)
Ok(())
}
async fn create_container_terminal(
@@ -125,7 +111,7 @@ async fn create_container_terminal(
server: String,
container: String,
user: &User,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<()> {
let server = get_check_permissions::<Server>(
&server,
user,
@@ -141,7 +127,7 @@ async fn create_stack_service_terminal(
stack: String,
service: String,
user: &User,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<()> {
let (_, periphery, container) =
get_stack_service_periphery_container(&stack, &service, user)
.await?;
@@ -152,7 +138,7 @@ async fn create_deployment_terminal(
req: CreateTerminal,
deployment: String,
user: &User,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<()> {
let (_, periphery, container) =
get_deployment_periphery_container(&deployment, user).await?;
create_container_terminal_inner(req, &periphery, container).await
-15
View File
@@ -36,15 +36,6 @@ use super::WriteArgs;
const RECENTLY_VIEWED_MAX: usize = 10;
impl Resolve<WriteArgs> for PushRecentlyViewed {
#[instrument(
"PushRecentlyViewed",
level = "debug",
skip_all,
fields(
user_id = user.id,
resource = format!("{:?}", self.resource)
)
)]
async fn resolve(
self,
WriteArgs { user, .. }: &WriteArgs,
@@ -88,12 +79,6 @@ impl Resolve<WriteArgs> for PushRecentlyViewed {
//
impl Resolve<WriteArgs> for SetLastSeenUpdate {
#[instrument(
"SetLastSeenUpdate",
level = "debug",
skip_all,
fields(user_id = user.id)
)]
async fn resolve(
self,
WriteArgs { user, .. }: &WriteArgs,
+5 -18
View File
@@ -5,7 +5,6 @@ use axum::{
response::IntoResponse,
};
use bytes::Bytes;
use colored::Colorize;
use futures_util::{SinkExt, StreamExt as _};
use komodo_client::{
api::terminal::ConnectTerminalQuery, entities::user::User,
@@ -129,26 +128,14 @@ async fn forward_ws_channel(
};
}
Ok(Err(e)) => {
let message = format!("{}: {e:#}", "ERROR".red().bold());
if message.contains("pty exited") {
let _ = client_send
.send(ws::Message::text(format!(
"\n{} {}",
"pty".bold(),
"exited".red().bold()
)))
.await;
} else {
let _ = client_send
.send(ws::Message::text(message.replace('\n', "\r\n")))
.await;
}
let _ = client_send
.send(ws::Message::text(format!("{e:#}")))
.await;
break;
}
Err(_) => {
let _ = client_send
.send(ws::Message::text("\r\n\nSTREAM EOF"))
.await;
let _ =
client_send.send(ws::Message::text("STREAM EOF")).await;
break;
}
}
+3 -1
View File
@@ -403,7 +403,9 @@ pub fn core_config() -> &'static CoreConfig {
ssl_cert_file: env
.komodo_ssl_cert_file
.unwrap_or(config.ssl_cert_file),
ui_path: env.komodo_ui_path.unwrap_or(config.ui_path),
ui_path: env
.komodo_ui_path
.unwrap_or(config.ui_path),
ui_index_force_no_cache: env
.komodo_ui_index_force_no_cache
.unwrap_or(config.ui_index_force_no_cache),
-15
View File
@@ -1,7 +1,6 @@
use std::time::Duration;
use anyhow::{Context, anyhow};
use komodo_client::entities::server::Server;
use periphery_client::{
CONNECTION_RETRY_SECONDS, transport::LoginMessage,
};
@@ -19,7 +18,6 @@ use transport::{
use crate::{
config::{core_config, core_connection_query},
monitor::refresh_server_cache,
periphery::PeripheryClient,
state::periphery_connections,
};
@@ -48,7 +46,6 @@ impl PeripheryConnectionArgs<'_> {
let responses = connection.responses.clone();
let _id = id.clone();
tokio::spawn(async move {
loop {
let ws = tokio::select! {
@@ -97,18 +94,6 @@ impl PeripheryConnectionArgs<'_> {
continue;
};
// Waits until after connection is handled then
// force refreshes the server cache.
let id = _id.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_millis(100)).await;
let Ok(server) = crate::resource::get::<Server>(&id).await
else {
return;
};
refresh_server_cache(&server, true).await;
});
connection.handle_socket(socket, &mut receiver).await
}
});
+8 -14
View File
@@ -1,4 +1,4 @@
use std::{str::FromStr, time::Duration};
use std::str::FromStr;
use anyhow::{Context, anyhow};
use axum::{
@@ -42,7 +42,6 @@ use crate::{
api::write::WriteArgs,
config::core_keys,
helpers::query::id_or_name_filter,
monitor::refresh_server_cache,
resource::KomodoResource,
state::{db_client, periphery_connections},
};
@@ -164,7 +163,7 @@ async fn existing_server_handler(
socket: &mut socket,
identifiers: identifiers.build(query.as_bytes()),
private_key: core_keys().load().private.as_str(),
public_key_validator: OnboardingKeyValidator { privileged_required: true },
public_key_validator: OnboardingKeyValidator { fix_existing_servers_required: true },
should_close: true
})
.await
@@ -202,13 +201,6 @@ async fn existing_server_handler(
return;
}
// Waits until after connection is handled then
// force refreshes the server cache.
tokio::spawn(async move {
tokio::time::sleep(Duration::from_millis(100)).await;
refresh_server_cache(&server, true).await;
});
connection.handle_socket(socket, &mut receiver).await
}))
}
@@ -235,7 +227,7 @@ async fn fix_existing_server_handler(
socket: &mut socket,
identifiers: identifiers.build(query.as_bytes()),
private_key: core_keys().load().private.as_str(),
public_key_validator: OnboardingKeyValidator { privileged_required: true },
public_key_validator: OnboardingKeyValidator { fix_existing_servers_required: true },
should_close: true,
})
.await
@@ -349,7 +341,7 @@ async fn onboard_new_server_handler(
socket: &mut socket,
identifiers: identifiers.build(query.as_bytes()),
private_key: core_keys().load().private.as_str(),
public_key_validator: OnboardingKeyValidator { privileged_required: false },
public_key_validator: OnboardingKeyValidator { fix_existing_servers_required: false },
should_close: true
})
.await
@@ -513,7 +505,7 @@ async fn create_server_maybe_builder(
}
struct OnboardingKeyValidator {
privileged_required: bool,
fix_existing_servers_required: bool,
}
impl PublicKeyValidator for OnboardingKeyValidator {
@@ -535,7 +527,9 @@ impl PublicKeyValidator for OnboardingKeyValidator {
{
return Err(anyhow!("Onboarding key is invalid"));
}
if self.privileged_required && !onboarding_key.privileged {
if self.fix_existing_servers_required
&& !onboarding_key.fix_existing_servers
{
return Err(anyhow!(
"Onboarding key not able to fix existing servers"
));
+23 -23
View File
@@ -39,34 +39,34 @@ impl ImageDigestCache {
account: Option<String>,
token: Option<String>,
) -> anyhow::Result<ImageDigest> {
if let Some((digest, valid_until)) = self.0.get(image).await
if let Some((digest, valid_until)) = self.0.get(&image).await
// Ensure the query time was within last 10 mins to use cache.
&& valid_until > komodo_timestamp()
{
return Ok(digest);
}
let digest = swarm_or_server_request(
swarm_or_server,
GetLatestImageDigest {
name: image.clone(),
account,
token,
},
)
.await?
.digest;
let digest = ImageDigest::new(image, &digest);
self
.0
.insert(
image,
(digest.clone(), komodo_timestamp() + 10 * 60 * 1_000),
} else {
let digest = swarm_or_server_request(
&swarm_or_server,
GetLatestImageDigest {
name: image.clone(),
account,
token,
},
)
.await;
.await?
.digest;
Ok(digest)
let digest = ImageDigest::new(image, &digest);
self
.0
.insert(
image,
(digest.clone(), komodo_timestamp() + 10 * 60 * 1_000),
)
.await;
Ok(digest)
}
}
}
+65 -321
View File
@@ -228,7 +228,7 @@ async fn execute_execution(
parent_name: &str,
) -> anyhow::Result<()> {
let user = procedure_user().to_owned();
let task_id = Uuid::new_v4();
let id = Uuid::new_v4();
let update = match execution {
Execution::None(_) => return Ok(()),
Execution::RunProcedure(req) => {
@@ -243,11 +243,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RunProcedure"),
@@ -270,11 +266,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RunAction"),
@@ -297,11 +289,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RunBuild"),
@@ -324,11 +312,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at CancelBuild"),
@@ -345,11 +329,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at Deploy"),
@@ -372,11 +352,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PullDeployment"),
@@ -393,11 +369,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StartDeployment"),
@@ -414,11 +386,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RestartDeployment"),
@@ -435,11 +403,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PauseDeployment"),
@@ -456,11 +420,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at UnpauseDeployment"),
@@ -477,11 +437,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StopDeployment"),
@@ -498,11 +454,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at DestroyDeployment"),
@@ -525,11 +477,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at CloneRepo"),
@@ -552,11 +500,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PullRepo"),
@@ -579,11 +523,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at BuildRepo"),
@@ -606,11 +546,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at CancelRepoBuild"),
@@ -627,11 +563,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StartContainer"),
@@ -648,11 +580,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RestartContainer"),
@@ -669,11 +597,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PauseContainer"),
@@ -690,11 +614,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at UnpauseContainer"),
@@ -711,11 +631,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StopContainer"),
@@ -732,11 +648,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RemoveContainer"),
@@ -753,11 +665,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StartAllContainers"),
@@ -774,11 +682,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RestartAllContainers"),
@@ -795,11 +699,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PauseAllContainers"),
@@ -816,11 +716,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at UnpauseAllContainers"),
@@ -837,11 +733,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StopAllContainers"),
@@ -858,11 +750,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PruneContainers"),
@@ -879,11 +767,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at DeleteNetwork"),
@@ -900,11 +784,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PruneNetworks"),
@@ -921,11 +801,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at DeleteImage"),
@@ -942,11 +818,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PruneImages"),
@@ -963,11 +835,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at DeleteVolume"),
@@ -984,11 +852,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PruneVolumes"),
@@ -1005,11 +869,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PruneDockerBuilders"),
@@ -1026,11 +886,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PruneBuildx"),
@@ -1047,11 +903,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PruneSystem"),
@@ -1068,11 +920,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RunSync"),
@@ -1095,11 +943,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at DeployStack"),
@@ -1122,11 +966,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at DeployStackIfChanged"),
@@ -1149,11 +989,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PullStack"),
@@ -1176,11 +1012,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StartStack"),
@@ -1197,11 +1029,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RestartStack"),
@@ -1218,11 +1046,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at PauseStack"),
@@ -1239,11 +1063,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at UnpauseStack"),
@@ -1260,11 +1080,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at StopStack"),
@@ -1281,11 +1097,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at DestroyStack"),
@@ -1302,11 +1114,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RunStackService"),
@@ -1329,11 +1137,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at TestAlerter"),
@@ -1350,11 +1154,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at SendAlert"),
@@ -1371,11 +1171,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RemoveSwarmNodes"),
@@ -1392,11 +1188,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RemoveSwarmStacks"),
@@ -1413,11 +1205,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RemoveSwarmServices"),
@@ -1434,11 +1222,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at CreateSwarmConfig"),
@@ -1455,11 +1239,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RotateSwarmConfig"),
@@ -1476,11 +1256,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RemoveSwarmConfigs"),
@@ -1497,11 +1273,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at CreateSwarmSecret"),
@@ -1518,11 +1290,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RotateSwarmSecret"),
@@ -1539,11 +1307,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RemoveSwarmSecrets"),
@@ -1560,11 +1324,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at ClearRepoCache"),
@@ -1581,11 +1341,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at BackupCoreDatabase"),
@@ -1602,11 +1358,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at GlobalAutoUpdate"),
@@ -1623,11 +1375,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RotateAllServerKeys"),
@@ -1644,11 +1392,7 @@ async fn execute_execution(
let update_id = update.id.clone();
handle_resolve_result(
req
.resolve(&ExecuteArgs {
user,
update,
task_id,
})
.resolve(&ExecuteArgs { user, update, id })
.await
.map_err(|e| e.error)
.context("Failed at RotateCoreKeys"),
+10 -9
View File
@@ -6,7 +6,7 @@ use komodo_client::{
permission::PermissionLevel,
server::Server,
stack::Stack,
terminal::{ContainerTerminalMode, Terminal, TerminalTarget},
terminal::{ContainerTerminalMode, TerminalTarget},
user::User,
},
};
@@ -84,7 +84,7 @@ async fn setup_server_target_for_user(
if let Some(init) = init {
periphery
.request(api::terminal::CreateServerTerminal {
name: Some(terminal.clone()),
name: terminal.clone(),
command: init.command,
recreate: init.recreate,
})
@@ -131,7 +131,7 @@ async fn setup_container_target_for_user(
if let Some(init) = init {
create_container_terminal_inner(
CreateTerminal {
name: Some(terminal.clone()),
name: terminal.clone(),
target: target.clone(),
command: init.command,
mode: init.mode,
@@ -166,7 +166,7 @@ async fn setup_stack_service_target_for_user(
if let Some(init) = init {
create_container_terminal_inner(
CreateTerminal {
name: Some(terminal.clone()),
name: terminal.clone(),
target: target.clone(),
command: init.command,
mode: init.mode,
@@ -199,7 +199,7 @@ async fn setup_deployment_target_for_user(
if let Some(init) = init {
create_container_terminal_inner(
CreateTerminal {
name: Some(terminal.clone()),
name: terminal.clone(),
target: target.clone(),
command: init.command,
mode: init.mode,
@@ -241,7 +241,7 @@ pub async fn create_container_terminal_inner(
}: CreateTerminal,
periphery: &PeripheryClient,
container: String,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<()> {
match mode.unwrap_or_default() {
ContainerTerminalMode::Exec => periphery
.request(periphery_client::api::terminal::CreateContainerExecTerminal {
@@ -254,7 +254,7 @@ pub async fn create_container_terminal_inner(
.await
.context(
"Failed to create Container Exec Terminal on Periphery",
),
)?,
ContainerTerminalMode::Attach => periphery
.request(periphery_client::api::terminal::CreateContainerAttachTerminal {
name,
@@ -265,8 +265,9 @@ pub async fn create_container_terminal_inner(
.await
.context(
"Failed to create Container Attach Terminal on Periphery",
),
}
)?,
};
Ok(())
}
pub async fn get_stack_service_periphery_container(
+1 -2
View File
@@ -3,8 +3,7 @@ use std::collections::HashMap;
use komodo_client::entities::{
ResourceTarget,
alert::{Alert, AlertData, SeverityLevel},
deployment::{Deployment, DeploymentState},
optional_string,
deployment::{Deployment, DeploymentState}, optional_string,
};
use crate::{
+1 -3
View File
@@ -2,9 +2,7 @@ use std::{collections::HashMap, sync::Mutex};
use anyhow::Context;
use komodo_client::entities::{
alert::AlertDataVariant, permission::PermissionLevel,
resource::ResourceQuery, server::Server, swarm::Swarm,
user::system_user,
alert::AlertDataVariant, permission::PermissionLevel, resource::ResourceQuery, server::Server, swarm::Swarm, user::system_user
};
use crate::resource;
+62 -162
View File
@@ -51,7 +51,7 @@ pub async fn alert_servers(
let mut alerts_to_open = Vec::<(Alert, SendAlerts)>::new();
let mut alerts_to_update = Vec::<(Alert, SendAlerts)>::new();
let mut alerts_to_close = Vec::<(Alert, SendAlerts)>::new();
let mut alert_ids_to_close = Vec::<(Alert, SendAlerts)>::new();
let buffer = alert_buffer();
@@ -66,21 +66,15 @@ pub async fn alert_servers(
let in_maintenance =
is_in_maintenance(&server.config.maintenance_windows, ts);
// ===============
// SERVER HEALTH
// ===============
// ===================
// SERVER HEALTH
// ===================
let health_alert = server_alerts.as_ref().and_then(|alerts| {
alerts.get(&AlertDataVariant::ServerUnreachable)
});
match (
server_status.state,
health_alert,
server.config.send_unreachable_alerts,
) {
// Skip alerting if alerts disabled
(ServerState::NotOk, None, false) => {}
(ServerState::NotOk, None, true) => {
// Only open unreachable alert if unreachable alerts enabled and not in maintenance and buffer is ready
match (server_status.state, health_alert) {
(ServerState::NotOk, None) => {
// Only open unreachable alert if not in maintenance and buffer is ready
if !in_maintenance
&& buffer.ready_to_open(
server_status.id.clone(),
@@ -105,14 +99,19 @@ pub async fn alert_servers(
.push((alert, server.config.send_unreachable_alerts))
}
}
(ServerState::NotOk, Some(alert), true) => {
(ServerState::NotOk, Some(alert)) => {
// update alert err
let mut alert = alert.clone();
let (id, name, region) = match alert.data {
AlertData::ServerUnreachable {
id, name, region, ..
} => (id, name, region),
_ => unreachable!(),
data => {
error!(
"got incorrect alert data in ServerStatus handler. got {data:?}"
);
continue;
}
};
alert.data = AlertData::ServerUnreachable {
id,
@@ -125,30 +124,23 @@ pub async fn alert_servers(
alerts_to_update.push((alert, false));
}
(ServerState::NotOk, Some(alert), false) => {
alerts_to_close.push((
alert.clone(),
server.config.send_unreachable_alerts,
));
}
// Close an open alert
(ServerState::Ok | ServerState::Disabled, Some(alert), _) => {
alerts_to_close.push((
(ServerState::Ok | ServerState::Disabled, Some(alert)) => {
alert_ids_to_close.push((
alert.clone(),
server.config.send_unreachable_alerts,
));
}
(ServerState::Ok | ServerState::Disabled, None, _) => buffer
(ServerState::Ok | ServerState::Disabled, None) => buffer
.reset(
server_status.id.clone(),
AlertDataVariant::ServerUnreachable,
),
}
// ========================
// ===================
// SERVER VERSION MISMATCH
// ========================
// ===================
let core_version = env!("CARGO_PKG_VERSION");
let mismatched_server_version =
if server_status.state != ServerState::Ok {
@@ -166,14 +158,9 @@ pub async fn alert_servers(
alerts.get(&AlertDataVariant::ServerVersionMismatch)
});
match (
mismatched_server_version,
version_alert,
server.config.send_version_mismatch_alerts,
) {
(Some(_), None, false) => {}
(Some(version), None, true) => {
// Only open version mismatch alert if version mismatch alerts enabled and not in maintenance and buffer is ready
match (mismatched_server_version, version_alert) {
(Some(version), None) => {
// Only open version mismatch alert if not in maintenance and buffer is ready
if !in_maintenance
&& buffer.ready_to_open(
server_status.id.clone(),
@@ -200,47 +187,27 @@ pub async fn alert_servers(
.push((alert, server.config.send_version_mismatch_alerts))
}
}
(Some(version), Some(alert), true) => {
// Update existing alert with current version info if changed
let (alert_server_version, alert_core_version) =
match &alert.data {
AlertData::ServerVersionMismatch {
server_version,
core_version,
..
} => (server_version, core_version),
_ => unreachable!(),
};
if alert_server_version != version
|| alert_core_version != core_version
{
let mut alert = alert.clone();
alert.data = AlertData::ServerVersionMismatch {
id: server_status.id.clone(),
name: server.name.clone(),
region: optional_string(&server.config.region),
server_version: version.clone(),
core_version: core_version.to_string(),
};
// Don't send notification for updates
alerts_to_update.push((alert, false));
}
(Some(version), Some(alert)) => {
// Update existing alert with current version info
let mut alert = alert.clone();
alert.data = AlertData::ServerVersionMismatch {
id: server_status.id.clone(),
name: server.name.clone(),
region: optional_string(&server.config.region),
server_version: version.clone(),
core_version: core_version.to_string(),
};
// Don't send notification for updates
alerts_to_update.push((alert, false));
}
(Some(_), Some(alert), false) => {
alerts_to_close.push((
alert.clone(),
server.config.send_version_mismatch_alerts,
));
}
(None, Some(alert), _) => {
(None, Some(alert)) => {
// Version is now correct, close the alert
alerts_to_close.push((
alert_ids_to_close.push((
alert.clone(),
server.config.send_version_mismatch_alerts,
));
}
(None, None, _) => {
(None, None) => {
// Reset buffer state when no mismatch and no alert
buffer.reset(
server_status.id.clone(),
@@ -260,25 +227,10 @@ pub async fn alert_servers(
.as_ref()
.and_then(|alerts| alerts.get(&AlertDataVariant::ServerCpu))
.cloned();
match (
health.cpu.level,
cpu_alert,
health.cpu.should_close_alert,
server.config.send_cpu_alerts,
) {
(
SeverityLevel::Warning | SeverityLevel::Critical,
None,
_,
false,
) => {}
(
SeverityLevel::Warning | SeverityLevel::Critical,
None,
_,
true,
) => {
// Only open CPU alert if cpu alerts enabled and not in maintenance and buffer is ready
match (health.cpu.level, cpu_alert, health.cpu.should_close_alert)
{
(SeverityLevel::Warning | SeverityLevel::Critical, None, _) => {
// Only open CPU alert if not in maintenance and buffer is ready
if !in_maintenance
&& buffer.ready_to_open(
server_status.id.clone(),
@@ -310,7 +262,6 @@ pub async fn alert_servers(
SeverityLevel::Warning | SeverityLevel::Critical,
Some(mut alert),
_,
true,
) => {
// modify alert level only if it has increased and not in maintenance
if !in_maintenance && alert.level < health.cpu.level {
@@ -329,15 +280,8 @@ pub async fn alert_servers(
.push((alert, server.config.send_cpu_alerts));
}
}
(
SeverityLevel::Warning | SeverityLevel::Critical,
Some(alert),
_,
false,
) => {
alerts_to_close.push((alert, server.config.send_cpu_alerts));
}
(SeverityLevel::Ok, Some(mut alert), true, _) => {
(SeverityLevel::Ok, Some(alert), true) => {
let mut alert = alert.clone();
alert.data = AlertData::ServerCpu {
id: server_status.id.clone(),
name: server.name.clone(),
@@ -348,9 +292,10 @@ pub async fn alert_servers(
.map(|s| s.cpu_perc as f64)
.unwrap_or(0.0),
};
alerts_to_close.push((alert, server.config.send_cpu_alerts))
alert_ids_to_close
.push((alert, server.config.send_cpu_alerts))
}
(SeverityLevel::Ok, _, _, _) => buffer
(SeverityLevel::Ok, _, _) => buffer
.reset(server_status.id.clone(), AlertDataVariant::ServerCpu),
}
@@ -361,25 +306,10 @@ pub async fn alert_servers(
.as_ref()
.and_then(|alerts| alerts.get(&AlertDataVariant::ServerMem))
.cloned();
match (
health.mem.level,
mem_alert,
health.mem.should_close_alert,
server.config.send_mem_alerts,
) {
(
SeverityLevel::Warning | SeverityLevel::Critical,
None,
_,
false,
) => {}
(
SeverityLevel::Warning | SeverityLevel::Critical,
None,
_,
true,
) => {
// Only open memory alert if memory alerts enabled and not in maintenance and buffer is ready
match (health.mem.level, mem_alert, health.mem.should_close_alert)
{
(SeverityLevel::Warning | SeverityLevel::Critical, None, _) => {
// Only open memory alert if not in maintenance and buffer is ready
if !in_maintenance
&& buffer.ready_to_open(
server_status.id.clone(),
@@ -416,7 +346,6 @@ pub async fn alert_servers(
SeverityLevel::Warning | SeverityLevel::Critical,
Some(mut alert),
_,
true,
) => {
// modify alert level only if it has increased and not in maintenance
if !in_maintenance && alert.level < health.mem.level {
@@ -440,16 +369,7 @@ pub async fn alert_servers(
.push((alert, server.config.send_mem_alerts));
}
}
(
SeverityLevel::Warning | SeverityLevel::Critical,
Some(alert),
_,
false,
) => {
alerts_to_close
.push((alert.clone(), server.config.send_mem_alerts));
}
(SeverityLevel::Ok, Some(alert), true, _) => {
(SeverityLevel::Ok, Some(alert), true) => {
let mut alert = alert.clone();
alert.data = AlertData::ServerMem {
id: server_status.id.clone(),
@@ -466,9 +386,10 @@ pub async fn alert_servers(
.map(|s| s.mem_used_gb)
.unwrap_or(0.0),
};
alerts_to_close.push((alert, server.config.send_mem_alerts))
alert_ids_to_close
.push((alert, server.config.send_mem_alerts))
}
(SeverityLevel::Ok, _, _, _) => buffer
(SeverityLevel::Ok, _, _) => buffer
.reset(server_status.id.clone(), AlertDataVariant::ServerMem),
}
@@ -484,25 +405,13 @@ pub async fn alert_servers(
.as_ref()
.and_then(|alerts| alerts.get(path))
.cloned();
match (
health.level,
disk_alert,
health.should_close_alert,
server.config.send_disk_alerts,
) {
match (health.level, disk_alert, health.should_close_alert) {
(
SeverityLevel::Warning | SeverityLevel::Critical,
None,
_,
false,
) => {}
(
SeverityLevel::Warning | SeverityLevel::Critical,
None,
_,
true,
) => {
// Only open disk alert if disk alerts enabled and not in maintenance and buffer is ready
// Only open disk alert if not in maintenance and buffer is ready
if !in_maintenance
&& buffer.ready_to_open(
server_status.id.clone(),
@@ -541,7 +450,6 @@ pub async fn alert_servers(
SeverityLevel::Warning | SeverityLevel::Critical,
Some(mut alert),
_,
true,
) => {
// modify alert level only if it has increased and not in maintenance
if !in_maintenance && health.level < alert.level {
@@ -562,16 +470,8 @@ pub async fn alert_servers(
.push((alert, server.config.send_disk_alerts));
}
}
(
SeverityLevel::Warning | SeverityLevel::Critical,
Some(alert),
_,
false,
) => {
alerts_to_close
.push((alert, server.config.send_disk_alerts));
}
(SeverityLevel::Ok, Some(mut alert), true, _) => {
(SeverityLevel::Ok, Some(alert), true) => {
let mut alert = alert.clone();
let disk =
server_status.system_stats.as_ref().and_then(|stats| {
stats.disks.iter().find(|disk| disk.mount == *path)
@@ -585,10 +485,10 @@ pub async fn alert_servers(
total_gb: disk.map(|d| d.total_gb).unwrap_or_default(),
used_gb: disk.map(|d| d.used_gb).unwrap_or_default(),
};
alerts_to_close
alert_ids_to_close
.push((alert, server.config.send_disk_alerts))
}
(SeverityLevel::Ok, _, _, _) => buffer.reset(
(SeverityLevel::Ok, _, _) => buffer.reset(
server_status.id.clone(),
AlertDataVariant::ServerDisk,
),
@@ -601,7 +501,7 @@ pub async fn alert_servers(
if !health.disks.contains_key(path) {
let mut alert = alert.clone();
alert.level = SeverityLevel::Ok;
alerts_to_close
alert_ids_to_close
.push((alert, server.config.send_disk_alerts));
}
}
@@ -611,7 +511,7 @@ pub async fn alert_servers(
tokio::join!(
open_new_alerts(&alerts_to_open),
update_alerts(&alerts_to_update),
resolve_alerts(&alerts_to_close),
resolve_alerts(&alert_ids_to_close),
);
}
+3 -1
View File
@@ -64,7 +64,9 @@ pub async fn alert_stacks(
let data = AlertData::StackStateChange {
id: status.curr.id.clone(),
name: stack.name,
swarm_name: swarm_names.get(&stack.config.swarm_id).cloned(),
swarm_name: swarm_names
.get(&stack.config.swarm_id)
.cloned(),
swarm_id: optional_string(stack.config.swarm_id),
server_name: server_names
.get(&stack.config.server_id)
+7 -31
View File
@@ -47,7 +47,7 @@ pub async fn alert_swarms(
let mut alerts_to_open = Vec::<(Alert, SendAlerts)>::new();
let mut alerts_to_update = Vec::<(Alert, SendAlerts)>::new();
let mut alerts_to_close = Vec::<(Alert, SendAlerts)>::new();
let mut alert_ids_to_close = Vec::<(Alert, SendAlerts)>::new();
let buffer = alert_buffer();
@@ -68,26 +68,14 @@ pub async fn alert_swarms(
let health_alert = swarm_alerts.as_ref().and_then(|alerts| {
alerts.get(&AlertDataVariant::SwarmUnhealthy)
});
match (
swarm_status.state,
health_alert,
swarm.config.send_unhealthy_alerts,
) {
match (swarm_status.state, health_alert) {
(
SwarmState::Unhealthy
| SwarmState::Down
| SwarmState::Unknown,
None,
false,
) => {}
(
SwarmState::Unhealthy
| SwarmState::Down
| SwarmState::Unknown,
None,
true,
) => {
// Only open unhealthy alert if unhealthy alerts enabled and not in maintenance and buffer is ready
// Only open unreachable alert if not in maintenance and buffer is ready
if !in_maintenance
&& buffer.ready_to_open(
swarm_status.id.clone(),
@@ -116,7 +104,6 @@ pub async fn alert_swarms(
| SwarmState::Down
| SwarmState::Unknown,
Some(alert),
true,
) => {
// update alert err
let mut alert = alert.clone();
@@ -139,23 +126,12 @@ pub async fn alert_swarms(
alerts_to_update.push((alert, false));
}
(
SwarmState::Unhealthy
| SwarmState::Down
| SwarmState::Unknown,
Some(alert),
false,
) => {
alerts_to_close
.push((alert.clone(), swarm.config.send_unhealthy_alerts));
}
// Close an open alert
(SwarmState::Healthy, Some(alert), _) => {
alerts_to_close
(SwarmState::Healthy, Some(alert)) => {
alert_ids_to_close
.push((alert.clone(), swarm.config.send_unhealthy_alerts));
}
(SwarmState::Healthy, None, _) => buffer.reset(
(SwarmState::Healthy, None) => buffer.reset(
swarm_status.id.clone(),
AlertDataVariant::SwarmUnhealthy,
),
@@ -165,7 +141,7 @@ pub async fn alert_swarms(
tokio::join!(
open_new_alerts(&alerts_to_open),
update_alerts(&alerts_to_update),
resolve_alerts(&alerts_to_close),
resolve_alerts(&alert_ids_to_close),
);
}
+168 -180
View File
@@ -41,7 +41,7 @@ mod record;
mod resources;
mod swarm;
pub use swarm::refresh_swarm_cache;
pub use swarm::update_cache_for_swarm;
const ADDITIONAL_MS: u128 = 500;
@@ -52,17 +52,17 @@ pub fn spawn_monitoring_loops() {
fn spawn_server_monitoring_loop() {
tokio::spawn(async move {
refresh_all_server_cache(komodo_timestamp()).await;
refresh_server_cache(komodo_timestamp()).await;
let interval = monitoring_interval();
loop {
let ts = (wait_until_timelength(interval, ADDITIONAL_MS).await
- ADDITIONAL_MS) as i64;
refresh_all_server_cache(ts).await;
refresh_server_cache(ts).await;
}
});
}
async fn refresh_all_server_cache(ts: i64) {
async fn refresh_server_cache(ts: i64) {
let servers =
match find_collect(&db_client().servers, None, None).await {
Ok(servers) => servers,
@@ -74,7 +74,7 @@ async fn refresh_all_server_cache(ts: i64) {
}
};
let futures = servers.into_iter().map(|server| async move {
refresh_server_cache(&server, false).await;
update_cache_for_server(&server, false).await;
});
join_all(futures).await;
tokio::join!(check_alerts(ts), record_server_stats(ts));
@@ -82,7 +82,7 @@ async fn refresh_all_server_cache(ts: i64) {
/// Makes sure cache for server doesn't update too frequently / simultaneously.
/// If forced, will still block against simultaneous update.
fn refresh_server_cache_controller()
fn update_cache_for_server_controller()
-> &'static CloneCache<String, Arc<Mutex<i64>>> {
static CACHE: OnceLock<CloneCache<String, Arc<Mutex<i64>>>> =
OnceLock::new();
@@ -93,176 +93,188 @@ fn refresh_server_cache_controller()
/// which exits early if the lock is busy or it was completed too recently.
/// If force is true, it will wait on simultaneous calls, and will
/// ignore the restriction on being completed too recently.
///
/// Returns impl Future for explicit Send bound, as this function
/// calls `periphery_client` which in some paths calls back this function `refresh_server_cache`.
/// While infinite recursion is prevented, the compiler needs some help to know the Send bound.
///
/// Clippy is not aware of this requirement, so the `manual_async_fn` lint is allowed here.
#[allow(clippy::manual_async_fn)]
pub fn refresh_server_cache(
server: &Server,
force: bool,
) -> impl Future<Output = ()> + Send + '_ {
async move {
// Concurrency controller to ensure it isn't done too often
// when it happens in other contexts.
let controller = refresh_server_cache_controller()
.get_or_insert_default(&server.id)
.await;
let mut lock = match controller.try_lock() {
Ok(lock) => lock,
Err(_) if force => controller.lock().await,
Err(_) => return,
};
pub async fn update_cache_for_server(server: &Server, force: bool) {
// Concurrency controller to ensure it isn't done too often
// when it happens in other contexts.
let controller = update_cache_for_server_controller()
.get_or_insert_default(&server.id)
.await;
let mut lock = match controller.try_lock() {
Ok(lock) => lock,
Err(_) if force => controller.lock().await,
Err(_) => return,
};
let now = komodo_timestamp();
let now = komodo_timestamp();
// early return if called again sooner than 1s.
if !force && *lock > now - 1_000 {
return;
}
// early return if called again sooner than 1s.
if !force && *lock > now - 1_000 {
return;
}
*lock = now;
*lock = now;
let resources = RefreshCacheResources::load_server(server).await;
// Handle server disabled
if !server.config.enabled {
resources.insert_status_unknown().await;
insert_server_status(
server,
ServerState::Disabled,
None,
None,
None,
None,
None,
)
.await;
periphery_connections().remove(&server.id).await;
return;
}
let periphery = match periphery_client(server).await {
Ok(periphery) => periphery,
Err(e) => {
resources.insert_status_unknown().await;
insert_server_status(
server,
ServerState::NotOk,
None,
None,
None,
None,
Serror::from(&e),
)
.await;
return;
}
};
let PollStatusResponse {
periphery_info,
system_info,
system_stats,
mut docker,
} = match periphery
.request(api::poll::PollStatus {
include_stats: server.config.stats_monitoring,
include_docker: true,
})
.await
{
Ok(info) => info,
Err(e) => {
resources.insert_status_unknown().await;
insert_server_status(
server,
ServerState::NotOk,
None,
None,
None,
None,
Serror::from(&e),
)
.await;
return;
}
};
if let Some(docker) = &mut docker {
docker.containers.iter_mut().for_each(|container| {
container.server_id = Some(server.id.clone())
});
}
let containers = docker
.as_ref()
.map(|docker| docker.containers.as_slice())
.unwrap_or(&[]);
let images = docker
.as_ref()
.map(|docker| docker.images.as_slice())
.unwrap_or(&[]);
tokio::join!(
resources::update_server_stack_cache(
resources.stacks,
containers,
images
),
resources::update_server_deployment_cache(
resources.deployments,
containers,
images,
),
);
let resources = UpdateCacheResources::load_server(server).await;
// Handle server disabled
if !server.config.enabled {
resources.insert_status_unknown().await;
insert_server_status(
server,
ServerState::Ok,
Some(periphery_info),
Some(system_info),
system_stats.map(|stats| filter_volumes(server, stats)),
docker,
ServerState::Disabled,
None,
None,
None,
None,
None,
)
.await;
periphery_connections().remove(&server.id).await;
return;
}
let status_cache = repo_status_cache();
for repo in resources.repos {
let (latest_hash, latest_message) = periphery
.request(GetLatestCommit {
name: repo.name.clone(),
path: optional_string(&repo.config.path),
})
.await
.ok()
.flatten()
.map(|c| (c.hash, c.message))
.unzip();
status_cache
.insert(
repo.id,
CachedRepoStatus {
latest_hash,
latest_message,
}
.into(),
)
.await;
let periphery = match periphery_client(server).await {
Ok(periphery) => periphery,
Err(e) => {
resources.insert_status_unknown().await;
insert_server_status(
server,
ServerState::NotOk,
None,
None,
None,
None,
Serror::from(&e),
)
.await;
return;
}
};
let PollStatusResponse {
periphery_info,
system_info,
system_stats,
mut docker,
} = match periphery
.request(api::poll::PollStatus {
include_stats: server.config.stats_monitoring,
include_docker: true,
})
.await
{
Ok(info) => info,
Err(e) => {
resources.insert_status_unknown().await;
insert_server_status(
server,
ServerState::NotOk,
None,
None,
None,
None,
Serror::from(&e),
)
.await;
return;
}
};
if let Some(docker) = &mut docker {
docker.containers.iter_mut().for_each(|container| {
container.server_id = Some(server.id.clone())
});
}
let containers = docker
.as_ref()
.map(|docker| docker.containers.as_slice())
.unwrap_or(&[]);
let images = docker
.as_ref()
.map(|docker| docker.images.as_slice())
.unwrap_or(&[]);
tokio::join!(
resources::update_server_stack_cache(
resources.stacks,
containers,
images
),
resources::update_server_deployment_cache(
resources.deployments,
containers,
images,
),
);
insert_server_status(
server,
ServerState::Ok,
Some(periphery_info),
Some(system_info),
system_stats.map(|stats| filter_volumes(server, stats)),
docker,
None,
)
.await;
let status_cache = repo_status_cache();
for repo in resources.repos {
let (latest_hash, latest_message) = periphery
.request(GetLatestCommit {
name: repo.name.clone(),
path: optional_string(&repo.config.path),
})
.await
.ok()
.flatten()
.map(|c| (c.hash, c.message))
.unzip();
status_cache
.insert(
repo.id,
CachedRepoStatus {
latest_hash,
latest_message,
}
.into(),
)
.await;
}
}
struct RefreshCacheResources {
struct UpdateCacheResources {
stacks: Vec<Stack>,
deployments: Vec<Deployment>,
repos: Vec<Repo>,
}
impl RefreshCacheResources {
impl UpdateCacheResources {
pub async fn load_swarm(swarm: &Swarm) -> Self {
let (stacks, deployments) = tokio::join!(
find_collect(
&db_client().stacks,
doc! { "config.swarm_id": &swarm.id },
None,
),
find_collect(
&db_client().deployments,
doc! { "config.swarm_id": &swarm.id },
None,
),
);
let stacks = stacks.inspect_err(|e| error!("Failed to get stacks list from db (update swarm status cache) | swarm: {} | {e:#}", swarm.name)).unwrap_or_default();
let deployments = deployments.inspect_err(|e| error!("Failed to get deployments list from db (update swarm status cache) | swarm : {} | {e:#}", swarm.name)).unwrap_or_default();
Self {
stacks,
deployments,
repos: Default::default(),
}
}
pub async fn load_server(server: &Server) -> Self {
let (stacks, deployments, repos) = tokio::join!(
find_collect(
@@ -293,30 +305,6 @@ impl RefreshCacheResources {
}
}
pub async fn load_swarm(swarm: &Swarm) -> Self {
let (stacks, deployments) = tokio::join!(
find_collect(
&db_client().stacks,
doc! { "config.swarm_id": &swarm.id },
None,
),
find_collect(
&db_client().deployments,
doc! { "config.swarm_id": &swarm.id },
None,
),
);
let stacks = stacks.inspect_err(|e| error!("Failed to get stacks list from db (update swarm status cache) | swarm: {} | {e:#}", swarm.name)).unwrap_or_default();
let deployments = deployments.inspect_err(|e| error!("Failed to get deployments list from db (update swarm status cache) | swarm : {} | {e:#}", swarm.name)).unwrap_or_default();
Self {
stacks,
deployments,
repos: Default::default(),
}
}
pub async fn insert_status_unknown(self) {
insert_stacks_status_unknown(self.stacks).await;
insert_deployments_status_unknown(self.deployments).await;
+9 -9
View File
@@ -23,7 +23,7 @@ use crate::{
config::monitoring_interval,
helpers::swarm::swarm_request_custom_timeout,
monitor::{
RefreshCacheResources,
UpdateCacheResources,
resources::{
update_swarm_deployment_cache, update_swarm_stack_cache,
},
@@ -35,16 +35,16 @@ const ADDITIONAL_MS: u128 = 1000;
pub fn spawn_swarm_monitoring_loop() {
tokio::spawn(async move {
refresh_all_swarm_cache().await;
refresh_swarm_cache().await;
let interval = monitoring_interval();
loop {
wait_until_timelength(interval, ADDITIONAL_MS).await;
refresh_all_swarm_cache().await;
refresh_swarm_cache().await;
}
});
}
async fn refresh_all_swarm_cache() {
async fn refresh_swarm_cache() {
let swarms =
match find_collect(&db_client().swarms, None, None).await {
Ok(swarms) => swarms,
@@ -56,7 +56,7 @@ async fn refresh_all_swarm_cache() {
}
};
let futures = swarms.into_iter().map(|swarm| async move {
refresh_swarm_cache(&swarm, false).await;
update_cache_for_swarm(&swarm, false).await;
});
join_all(futures).await;
// tokio::join!(check_alerts(ts), record_swarm_stats(ts));
@@ -64,7 +64,7 @@ async fn refresh_all_swarm_cache() {
/// Makes sure cache for swarm doesn't update too frequently / simultaneously.
/// If forced, will still block against simultaneous update.
fn refresh_swarm_cache_controller()
fn update_cache_for_swarm_controller()
-> &'static CloneCache<String, Arc<Mutex<i64>>> {
static CACHE: OnceLock<CloneCache<String, Arc<Mutex<i64>>>> =
OnceLock::new();
@@ -75,10 +75,10 @@ fn refresh_swarm_cache_controller()
/// which exits early if the lock is busy or it was completed too recently.
/// If force is true, it will wait on simultaneous calls, and will
/// ignore the restriction on being completed too recently.
pub async fn refresh_swarm_cache(swarm: &Swarm, force: bool) {
pub async fn update_cache_for_swarm(swarm: &Swarm, force: bool) {
// Concurrency controller to ensure it isn't done too often
// when it happens in other contexts.
let controller = refresh_swarm_cache_controller()
let controller = update_cache_for_swarm_controller()
.get_or_insert_default(&swarm.id)
.await;
let mut lock = match controller.try_lock() {
@@ -96,7 +96,7 @@ pub async fn refresh_swarm_cache(swarm: &Swarm, force: bool) {
*lock = now;
let resources = RefreshCacheResources::load_swarm(swarm).await;
let resources = UpdateCacheResources::load_swarm(swarm).await;
if swarm.config.server_ids.is_empty() {
resources.insert_status_unknown().await;
+4 -10
View File
@@ -33,7 +33,7 @@ use crate::{
query::{get_deployment_state, get_swarm_or_server},
swarm::swarm_request,
},
monitor::{refresh_server_cache, refresh_swarm_cache},
monitor::{update_cache_for_server, update_cache_for_swarm},
state::{action_states, db_client, deployment_status_cache},
};
@@ -72,13 +72,7 @@ impl super::KomodoResource for Deployment {
fn inherit_specific_permissions_from(
_self: &Resource<Self::Config, Self::Info>,
) -> Option<ResourceTarget> {
if !_self.config.swarm_id.is_empty() {
Some(ResourceTarget::Swarm(_self.config.swarm_id.clone()))
} else if !_self.config.server_id.is_empty() {
Some(ResourceTarget::Server(_self.config.server_id.clone()))
} else {
None
}
ResourceTarget::Server(_self.config.server_id.clone()).into()
}
fn coll() -> &'static Collection<Resource<Self::Config, Self::Info>>
@@ -227,10 +221,10 @@ impl super::KomodoResource for Deployment {
};
match swarm_or_server {
SwarmOrServer::Swarm(swarm) => {
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
SwarmOrServer::Server(server) => {
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
}
SwarmOrServer::None => {}
}
+3 -3
View File
@@ -24,7 +24,7 @@ use periphery_client::api;
use crate::{
config::core_config,
helpers::periphery_client,
monitor::refresh_server_cache,
monitor::update_cache_for_server,
state::{
action_states, db_client, periphery_connections,
server_status_cache,
@@ -151,7 +151,7 @@ impl super::KomodoResource for Server {
created: &Resource<Self::Config, Self::Info>,
_update: &mut Update,
) -> anyhow::Result<()> {
refresh_server_cache(created, true).await;
update_cache_for_server(created, true).await;
Ok(())
}
@@ -173,7 +173,7 @@ impl super::KomodoResource for Server {
updated: &Self,
_update: &mut Update,
) -> anyhow::Result<()> {
refresh_server_cache(updated, true).await;
update_cache_for_server(updated, true).await;
Ok(())
}
+4 -10
View File
@@ -35,7 +35,7 @@ use crate::{
repo_link,
swarm::swarm_request,
},
monitor::{refresh_server_cache, refresh_swarm_cache},
monitor::{update_cache_for_server, update_cache_for_swarm},
state::{
action_states, all_resources_cache, db_client,
server_status_cache, stack_status_cache,
@@ -77,13 +77,7 @@ impl super::KomodoResource for Stack {
fn inherit_specific_permissions_from(
_self: &Resource<Self::Config, Self::Info>,
) -> Option<ResourceTarget> {
if !_self.config.swarm_id.is_empty() {
Some(ResourceTarget::Swarm(_self.config.swarm_id.clone()))
} else if !_self.config.server_id.is_empty() {
Some(ResourceTarget::Server(_self.config.server_id.clone()))
} else {
None
}
ResourceTarget::Server(_self.config.server_id.clone()).into()
}
fn coll() -> &'static Collection<Resource<Self::Config, Self::Info>>
@@ -300,10 +294,10 @@ impl super::KomodoResource for Stack {
};
match swarm_or_server {
SwarmOrServer::Swarm(swarm) => {
refresh_swarm_cache(&swarm, true).await;
update_cache_for_swarm(&swarm, true).await;
}
SwarmOrServer::Server(server) => {
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
}
SwarmOrServer::None => {}
}
+3 -3
View File
@@ -15,7 +15,7 @@ use komodo_client::entities::{
use crate::{
config::core_config,
monitor::refresh_swarm_cache,
monitor::update_cache_for_swarm,
state::{db_client, swarm_status_cache},
};
@@ -89,7 +89,7 @@ impl super::KomodoResource for Swarm {
created: &Self,
_update: &mut Update,
) -> anyhow::Result<()> {
refresh_swarm_cache(created, true).await;
update_cache_for_swarm(created, true).await;
Ok(())
}
@@ -111,7 +111,7 @@ impl super::KomodoResource for Swarm {
updated: &Self,
_update: &mut Update,
) -> anyhow::Result<()> {
refresh_swarm_cache(updated, true).await;
update_cache_for_swarm(updated, true).await;
Ok(())
}
+8 -6
View File
@@ -10,7 +10,12 @@ use komodo_client::{
permission::PermissionLevel,
repo::Repo,
resource::Resource,
sync::*,
sync::{
PartialResourceSyncConfig, ResourceSync, ResourceSyncConfig,
ResourceSyncConfigDiff, ResourceSyncInfo, ResourceSyncListItem,
ResourceSyncListItemInfo, ResourceSyncQuerySpecifics,
ResourceSyncState,
},
update::Update,
user::{User, sync_user},
},
@@ -255,15 +260,12 @@ async fn get_resource_sync_state(
{
return state;
}
if data.pending_error.is_some()
|| data.pending_deploy_error.is_some()
|| !data.remote_errors.is_empty()
{
if data.pending_error.is_some() || !data.remote_errors.is_empty() {
ResourceSyncState::Failed
} else if !data.resource_updates.is_empty()
|| !data.variable_updates.is_empty()
|| !data.user_group_updates.is_empty()
|| !data.pending_deploys.is_empty()
|| data.pending_deploy.to_deploy > 0
{
ResourceSyncState::Pending
} else {
+2 -2
View File
@@ -109,7 +109,7 @@ pub fn spawn_schedule_executor() {
.resolve(&ExecuteArgs {
user: action_user().to_owned(),
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
{
@@ -180,7 +180,7 @@ pub fn spawn_schedule_executor() {
.resolve(&ExecuteArgs {
user: procedure_user().to_owned(),
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
{
+2 -2
View File
@@ -14,7 +14,7 @@ use periphery_client::api::compose::*;
use crate::{
helpers::{periphery_client, update::update_update},
monitor::refresh_server_cache,
monitor::update_cache_for_server,
periphery::PeripheryClient,
state::action_states,
};
@@ -102,7 +102,7 @@ pub async fn execute_compose_with_stack_and_server<
.push(T::execute(periphery, stack, services, extras).await?);
// Ensure cached stack state up to date by updating server cache
refresh_server_cache(&server, true).await;
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
+4 -3
View File
@@ -1,6 +1,7 @@
use std::str::FromStr;
use anyhow::Context;
use colored::Colorize;
use database::mungos::{
find::find_collect,
mongodb::bson::{
@@ -92,7 +93,7 @@ pub async fn run_startup_actions() {
.resolve(&ExecuteArgs {
user: action_user().to_owned(),
update,
task_id: Uuid::new_v4(),
id: Uuid::new_v4(),
})
.await
{
@@ -348,11 +349,11 @@ async fn ensure_init_user_and_resources() {
|| procedures.is_some()
|| tags.is_some()
{
info!("Skipping initial system resource creation");
info!("System resources init {}", "DISABLED".red());
return;
}
info!("Creating initial system resources...");
info!("Creating init system resources...");
let write_args = WriteArgs {
user: system_user().to_owned(),
+1 -1
View File
@@ -220,5 +220,5 @@ pub fn all_resources_cache() -> &'static ArcSwap<AllResourcesById> {
pub fn image_digest_cache() -> &'static ImageDigestCache {
static IMAGE_DIGEST_CACHE: OnceLock<Arc<ImageDigestCache>> =
OnceLock::new();
IMAGE_DIGEST_CACHE.get_or_init(ImageDigestCache::new)
IMAGE_DIGEST_CACHE.get_or_init(|| ImageDigestCache::new())
}
+54 -27
View File
@@ -18,7 +18,7 @@ use komodo_client::{
PartialStackConfig, Stack, StackConfig,
StackRemoteFileContents, StackState,
},
sync::SyncDeployTarget,
sync::SyncDeployUpdate,
toml::ResourceToml,
update::Log,
user::sync_user,
@@ -41,7 +41,8 @@ use super::ResourceSyncTrait;
/// All entries in here are due to be deployed,
/// after the given dependencies,
/// with the given reason.
pub type ToDeployCache = Vec<SyncDeployTarget>;
pub type ToDeployCache =
Vec<(ResourceTarget, String, Vec<ResourceTarget>)>;
#[derive(Clone, Copy)]
pub struct SyncDeployParams<'a> {
@@ -71,16 +72,14 @@ pub async fn deploy_from_cache(
// Collect all waiting deployments without waiting dependencies.
let good_to_deploy = to_deploy
.iter()
.filter(|SyncDeployTarget { after, .. }| {
to_deploy.iter().all(|SyncDeployTarget { target, .. }| {
!after.contains(target)
})
.filter(|(_, _, after)| {
to_deploy
.iter()
.all(|(target, _, _)| !after.contains(target))
})
// The target / reason need the be cloned out to to_deploy is not borrowed from.
// to_deploy will be mutably accessed later.
.map(|SyncDeployTarget { target, reason, .. }| {
(target.clone(), reason.clone())
})
.map(|(target, reason, _)| (target.clone(), reason.clone()))
.collect::<HashMap<_, _>>();
// Deploy the ones ready for deployment
@@ -104,7 +103,7 @@ pub async fn deploy_from_cache(
.resolve(&ExecuteArgs {
user: user.to_owned(),
update,
task_id: id,
id,
})
.await
}
@@ -123,7 +122,7 @@ pub async fn deploy_from_cache(
.resolve(&ExecuteArgs {
user: user.to_owned(),
update,
task_id: id,
id,
})
.await
}
@@ -173,9 +172,8 @@ pub async fn deploy_from_cache(
}
// Remove the deployed ones from 'to_deploy'
to_deploy.retain(|SyncDeployTarget { target, .. }| {
!good_to_deploy.contains_key(target)
});
to_deploy
.retain(|(target, _, _)| !good_to_deploy.contains_key(target));
// If there must be another round, these are dependent on the first round.
// Sleep for 1s to allow for first round to startup
@@ -198,10 +196,46 @@ pub async fn deploy_from_cache(
pub async fn get_updates_for_view(
params: SyncDeployParams<'_>,
) -> (Vec<SyncDeployTarget>, Option<String>) {
match build_deploy_cache(params).await {
Ok(targets) => (targets, None),
Err(e) => (Vec::new(), Some(format_serror(&e.into()))),
) -> SyncDeployUpdate {
let inner = async {
let mut update = SyncDeployUpdate {
to_deploy: 0,
log: String::from("Deploy Updates\n-------------------\n"),
};
let mut lines = Vec::<String>::new();
for (target, reason, after) in build_deploy_cache(params).await? {
update.to_deploy += 1;
let mut line = format!(
"{}: {}. reason: {reason}",
colored("Deploy", Color::Green),
bold(format!("{target:?}")),
);
if !after.is_empty() {
line.push_str(&format!(
"\n{}: {}",
colored("After", Color::Blue),
after
.iter()
.map(|target| format!("{target:?}"))
.collect::<Vec<_>>()
.join(", ")
))
}
lines.push(line);
}
update.log.push_str(&lines.join("\n-------------------\n"));
anyhow::Ok(update)
};
match inner.await {
Ok(res) => res,
Err(e) => SyncDeployUpdate {
to_deploy: 0,
log: format_serror(
&e.context("failed to get deploy updates for view").into(),
),
},
}
}
@@ -260,11 +294,7 @@ pub async fn build_deploy_cache(
.map(|(target, (reason, mut after))| {
// Only keep targets which are deploying.
after.retain(|target| clone.contains_key(target));
SyncDeployTarget {
target,
reason,
after,
}
(target, reason, after)
})
.collect(),
)
@@ -590,12 +620,9 @@ fn build_cache_for_stack<'a>(
|| diff.extra_args.is_some()
|| diff.environment.is_some()
|| diff.env_file_path.is_some()
|| diff.additional_env_files.is_some()
|| diff.linked_repo.is_some()
|| diff.repo.is_some()
|| diff.branch.is_some()
|| diff.commit.is_some()
|| diff.compose_cmd_wrapper.is_some();
|| diff.commit.is_some();
if changed {
cache.insert(
target,
+475 -150
View File
@@ -35,6 +35,17 @@ use super::{
include_resource_by_tags,
};
impl ResourceSyncTrait for Swarm {
fn get_diff(
original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
Ok(original.partial_diff(update))
}
}
impl ExecuteResourceSync for Swarm {}
impl ResourceSyncTrait for Server {
fn get_diff(
original: Self::Config,
@@ -46,41 +57,20 @@ impl ResourceSyncTrait for Server {
impl ExecuteResourceSync for Server {}
impl ResourceSyncTrait for Swarm {
fn get_diff(
mut original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
let all = all_resources_cache().load();
original.server_ids.iter_mut().for_each(|server_id| {
*server_id = all
.servers
.get(server_id)
.map(|s| s.name.clone())
.unwrap_or_default();
});
Ok(original.partial_diff(update))
}
}
impl ExecuteResourceSync for Swarm {}
impl ResourceSyncTrait for Deployment {
fn get_diff(
mut original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
let all = all_resources_cache().load();
let resources = all_resources_cache().load();
original.swarm_id = all
original.swarm_id = resources
.swarms
.get(&original.swarm_id)
.map(|s| s.name.clone())
.unwrap_or_default();
original.server_id = all
original.server_id = resources
.servers
.get(&original.server_id)
.map(|s| s.name.clone())
@@ -90,7 +80,7 @@ impl ResourceSyncTrait for Deployment {
&original.image
{
original.image = DeploymentImage::Build {
build_id: all
build_id: resources
.builds
.get(build_id)
.map(|b| b.name.clone())
@@ -110,21 +100,21 @@ impl ResourceSyncTrait for Stack {
mut original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
let all = all_resources_cache().load();
let resources = all_resources_cache().load();
original.swarm_id = all
original.swarm_id = resources
.swarms
.get(&original.swarm_id)
.map(|s| s.name.clone())
.unwrap_or_default();
original.server_id = all
original.server_id = resources
.servers
.get(&original.server_id)
.map(|s| s.name.clone())
.unwrap_or_default();
original.linked_repo = all
original.linked_repo = resources
.repos
.get(&original.linked_repo)
.map(|r| r.name.clone())
@@ -141,13 +131,13 @@ impl ResourceSyncTrait for Build {
mut original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
let all = all_resources_cache().load();
original.builder_id = all
let resources = all_resources_cache().load();
original.builder_id = resources
.builders
.get(&original.builder_id)
.map(|b| b.name.clone())
.unwrap_or_default();
original.linked_repo = all
original.linked_repo = resources
.repos
.get(&original.linked_repo)
.map(|r| r.name.clone())
@@ -175,16 +165,16 @@ impl ResourceSyncTrait for Repo {
mut original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
let all = all_resources_cache().load();
let resources = all_resources_cache().load();
// Need to replace server id with name
original.server_id = all
original.server_id = resources
.servers
.get(&original.server_id)
.map(|s| s.name.clone())
.unwrap_or_default();
// Need to replace builder id with name
original.builder_id = all
original.builder_id = resources
.builders
.get(&original.builder_id)
.map(|s| s.name.clone())
@@ -214,8 +204,8 @@ impl ResourceSyncTrait for Builder {
) -> anyhow::Result<Self::ConfigDiff> {
// need to replace server builder id with name
if let BuilderConfig::Server(config) = &mut original {
let all = all_resources_cache().load();
config.server_id = all
let resources = all_resources_cache().load();
config.server_id = resources
.servers
.get(&config.server_id)
.map(|s| s.name.clone())
@@ -323,8 +313,8 @@ impl ResourceSyncTrait for ResourceSync {
mut original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
let all = all_resources_cache().load();
original.linked_repo = all
let resources = all_resources_cache().load();
original.linked_repo = resources
.repos
.get(&original.linked_repo)
.map(|r| r.name.clone())
@@ -341,121 +331,456 @@ impl ResourceSyncTrait for Procedure {
mut original: Self::Config,
update: Self::PartialConfig,
) -> anyhow::Result<Self::ConfigDiff> {
let all = all_resources_cache().load();
let resources = all_resources_cache().load();
for stage in &mut original.stages {
for execution in &mut stage.executions {
// Replaces an id field on config with the resource name from `all`.
macro_rules! replace_id_with_name {
($($Variant:ident => $field:ident, $collection:ident);* $(;)?) => {
match &mut execution.execution {
$(
Execution::$Variant(config) => {
config.$field = all
.$collection
.get(&config.$field)
.map(|r| r.name.clone())
.unwrap_or_default();
}
)*
// SendAlert maps a Vec of alerter ids
Execution::SendAlert(config) => {
config.alerters = config
match &mut execution.execution {
Execution::None(_) => {}
Execution::RunProcedure(config) => {
config.procedure = resources
.procedures
.get(&config.procedure)
.map(|p| p.name.clone())
.unwrap_or_default();
}
Execution::BatchRunProcedure(_config) => {}
Execution::RunAction(config) => {
config.action = resources
.actions
.get(&config.action)
.map(|p| p.name.clone())
.unwrap_or_default();
}
Execution::BatchRunAction(_config) => {}
Execution::RunBuild(config) => {
config.build = resources
.builds
.get(&config.build)
.map(|b| b.name.clone())
.unwrap_or_default();
}
Execution::BatchRunBuild(_config) => {}
Execution::CancelBuild(config) => {
config.build = resources
.builds
.get(&config.build)
.map(|b| b.name.clone())
.unwrap_or_default();
}
Execution::Deploy(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::BatchDeploy(_config) => {}
Execution::PullDeployment(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::StartDeployment(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::RestartDeployment(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PauseDeployment(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::UnpauseDeployment(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::StopDeployment(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::DestroyDeployment(config) => {
config.deployment = resources
.deployments
.get(&config.deployment)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::BatchDestroyDeployment(_config) => {}
Execution::CloneRepo(config) => {
config.repo = resources
.repos
.get(&config.repo)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::BatchCloneRepo(_config) => {}
Execution::PullRepo(config) => {
config.repo = resources
.repos
.get(&config.repo)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::BatchPullRepo(_config) => {}
Execution::BuildRepo(config) => {
config.repo = resources
.repos
.get(&config.repo)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::BatchBuildRepo(_config) => {}
Execution::CancelRepoBuild(config) => {
config.repo = resources
.repos
.get(&config.repo)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::StartContainer(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::RestartContainer(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PauseContainer(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::UnpauseContainer(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::StopContainer(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::DestroyContainer(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::StartAllContainers(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::RestartAllContainers(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PauseAllContainers(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::UnpauseAllContainers(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::StopAllContainers(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PruneContainers(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::DeleteNetwork(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PruneNetworks(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::DeleteImage(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PruneImages(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::DeleteVolume(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PruneVolumes(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PruneDockerBuilders(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PruneBuildx(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::PruneSystem(config) => {
config.server = resources
.servers
.get(&config.server)
.map(|d| d.name.clone())
.unwrap_or_default();
}
Execution::RunSync(config) => {
config.sync = resources
.syncs
.get(&config.sync)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::CommitSync(config) => {
config.sync = resources
.syncs
.get(&config.sync)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::DeployStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::BatchDeployStack(_config) => {}
Execution::DeployStackIfChanged(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::BatchDeployStackIfChanged(_config) => {}
Execution::PullStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::BatchPullStack(_config) => {}
Execution::StartStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RestartStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::PauseStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::UnpauseStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::StopStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::DestroyStack(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RunStackService(config) => {
config.stack = resources
.stacks
.get(&config.stack)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::BatchDestroyStack(_config) => {}
Execution::TestAlerter(config) => {
config.alerter = resources
.alerters
.get(&config.alerter)
.map(|a| a.name.clone())
.unwrap_or_default();
}
Execution::SendAlert(config) => {
config.alerters = config
.alerters
.iter()
.map(|alerter| {
resources
.alerters
.iter()
.map(|alerter| {
all
.alerters
.get(alerter)
.map(|a| a.name.clone())
.unwrap_or_default()
})
.collect();
}
// No-op variants
Execution::None(_)
| Execution::BatchRunProcedure(_)
| Execution::BatchRunAction(_)
| Execution::BatchRunBuild(_)
| Execution::BatchDeploy(_)
| Execution::BatchDestroyDeployment(_)
| Execution::BatchCloneRepo(_)
| Execution::BatchPullRepo(_)
| Execution::BatchBuildRepo(_)
| Execution::BatchDeployStack(_)
| Execution::BatchDeployStackIfChanged(_)
| Execution::BatchPullStack(_)
| Execution::BatchDestroyStack(_)
| Execution::ClearRepoCache(_)
| Execution::BackupCoreDatabase(_)
| Execution::GlobalAutoUpdate(_)
| Execution::RotateAllServerKeys(_)
| Execution::RotateCoreKeys(_)
| Execution::Sleep(_) => {}
}
};
.get(alerter)
.map(|a| a.name.clone())
.unwrap_or_default()
})
.collect();
}
Execution::RemoveSwarmNodes(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RemoveSwarmStacks(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RemoveSwarmServices(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::CreateSwarmConfig(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RotateSwarmConfig(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RemoveSwarmConfigs(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::CreateSwarmSecret(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RotateSwarmSecret(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::RemoveSwarmSecrets(config) => {
config.swarm = resources
.swarms
.get(&config.swarm)
.map(|s| s.name.clone())
.unwrap_or_default();
}
Execution::ClearRepoCache(_) => {}
Execution::BackupCoreDatabase(_) => {}
Execution::GlobalAutoUpdate(_) => {}
Execution::RotateAllServerKeys(_) => {}
Execution::RotateCoreKeys(_) => {}
Execution::Sleep(_) => {}
}
replace_id_with_name!(
RunProcedure => procedure, procedures;
RunAction => action, actions;
RunBuild => build, builds;
CancelBuild => build, builds;
Deploy => deployment, deployments;
PullDeployment => deployment, deployments;
StartDeployment => deployment, deployments;
RestartDeployment => deployment, deployments;
PauseDeployment => deployment, deployments;
UnpauseDeployment => deployment, deployments;
StopDeployment => deployment, deployments;
DestroyDeployment => deployment, deployments;
CloneRepo => repo, repos;
PullRepo => repo, repos;
BuildRepo => repo, repos;
CancelRepoBuild => repo, repos;
StartContainer => server, servers;
RestartContainer => server, servers;
PauseContainer => server, servers;
UnpauseContainer => server, servers;
StopContainer => server, servers;
DestroyContainer => server, servers;
StartAllContainers => server, servers;
RestartAllContainers => server, servers;
PauseAllContainers => server, servers;
UnpauseAllContainers => server, servers;
StopAllContainers => server, servers;
PruneContainers => server, servers;
DeleteNetwork => server, servers;
PruneNetworks => server, servers;
DeleteImage => server, servers;
PruneImages => server, servers;
DeleteVolume => server, servers;
PruneVolumes => server, servers;
PruneDockerBuilders => server, servers;
PruneBuildx => server, servers;
PruneSystem => server, servers;
RunSync => sync, syncs;
CommitSync => sync, syncs;
DeployStack => stack, stacks;
DeployStackIfChanged => stack, stacks;
PullStack => stack, stacks;
StartStack => stack, stacks;
RestartStack => stack, stacks;
PauseStack => stack, stacks;
UnpauseStack => stack, stacks;
StopStack => stack, stacks;
DestroyStack => stack, stacks;
RunStackService => stack, stacks;
TestAlerter => alerter, alerters;
RemoveSwarmNodes => swarm, swarms;
RemoveSwarmStacks => swarm, swarms;
RemoveSwarmServices => swarm, swarms;
CreateSwarmConfig => swarm, swarms;
RotateSwarmConfig => swarm, swarms;
RemoveSwarmConfigs => swarm, swarms;
CreateSwarmSecret => swarm, swarms;
RotateSwarmSecret => swarm, swarms;
RemoveSwarmSecrets => swarm, swarms;
);
}
}
Ok(original.partial_diff(update))
-8
View File
@@ -178,14 +178,6 @@ impl ToToml for ResourceSync {
impl ToToml for Swarm {
fn replace_ids(resource: &mut Resource<Self::Config, Self::Info>) {
let all = all_resources_cache().load();
resource.config.server_ids.iter_mut().for_each(|server_id| {
*server_id = all
.servers
.get(server_id)
.map(|s| s.name.clone())
.unwrap_or_default();
});
let mut res =
Vec::with_capacity(resource.config.server_ids.capacity());
for server_id in &resource.config.server_ids {
+1 -1
View File
@@ -1,6 +1,6 @@
## All in one, multi stage compile + runtime Docker build for your architecture.
FROM rust:1.94.0-trixie AS builder
FROM rust:1.93.1-trixie AS builder
RUN cargo install cargo-strip
WORKDIR /builder
+1 -1
View File
@@ -2,7 +2,7 @@
## Sets up the necessary runtime container dependencies for Komodo Periphery.
## Since theres no heavy build here, QEMU multi-arch builds are fine for this image.
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:2
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:latest
ARG X86_64_BINARIES=${BINARIES_IMAGE}-x86_64
ARG AARCH64_BINARIES=${BINARIES_IMAGE}-aarch64
+1 -1
View File
@@ -1,7 +1,7 @@
## Assumes the latest binaries for the required arch are already built (by binaries.Dockerfile).
## Sets up the necessary runtime container dependencies for Komodo Periphery.
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:2
ARG BINARIES_IMAGE=ghcr.io/moghtech/komodo-binaries:latest
# This is required to work with COPY --from
FROM ${BINARIES_IMAGE} AS binaries
+42 -217
View File
@@ -307,8 +307,8 @@ impl Resolve<crate::api::Args> for ComposePull {
};
// Canonicalize the path to ensure it exists, and is the cleanest path to the run directory.
let run_directory = run_directory.canonicalize().with_context(||
format!("Failed to validate run directory on host after stack write (canonicalize error), path={}", run_directory.to_string_lossy()),
let run_directory = run_directory.canonicalize().context(
"Failed to validate run directory on host after stack write (canonicalize error)",
)?;
let file_paths = stack
@@ -352,56 +352,16 @@ impl Resolve<crate::api::Args> for ComposePull {
let project_name = stack.project_name(false);
// Parse wrapper configuration
let compose_cmd_wrapper =
parse_multiline_command(&stack.config.compose_cmd_wrapper);
// If wrapper_include is empty but wrapper is set, use default ["up"] for backward compatibility
let default_include = vec![String::from("up")];
let wrapper_include =
if stack.config.compose_cmd_wrapper_include.is_empty()
&& !compose_cmd_wrapper.is_empty()
{
&default_include
} else {
&stack.config.compose_cmd_wrapper_include
};
let pull_command = format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} pull{service_args}",
);
let (pull_command, wrapped) = match maybe_wrap_command(
pull_command,
&compose_cmd_wrapper,
wrapper_include,
"pull",
) {
Ok(result) => result,
Err(log) => {
res.logs.push(log);
return Ok(res);
}
};
let span = info_span!("RunComposePull");
let mode = if wrapped {
KomodoCommandMode::Shell
} else {
KomodoCommandMode::Standard
};
let Some(log) = run_komodo_command_with_sanitization(
let log = run_komodo_standard_command(
"Compose Pull",
run_directory.as_path(),
pull_command,
mode,
&replacers,
run_directory.as_ref(),
format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} pull{service_args}",
),
)
.instrument(span)
.await
else {
// Only reachable if command is empty,
// not the case since it is provided above.
unreachable!()
};
.await;
res.logs.push(log);
@@ -467,8 +427,8 @@ impl Resolve<crate::api::Args> for ComposeUp {
};
// Canonicalize the path to ensure it exists, and is the cleanest path to the run directory.
let run_directory = run_directory.canonicalize().with_context(||
format!("Failed to validate run directory on host after stack write (canonicalize error), path={}", run_directory.to_string_lossy()),
let run_directory = run_directory.canonicalize().context(
"Failed to validate run directory on host after stack write (canonicalize error)",
)?;
validate_files(&stack, &run_directory, &mut res).await;
@@ -523,54 +483,25 @@ impl Resolve<crate::api::Args> for ComposeUp {
&stack.config.additional_env_files,
)?;
// Parse wrapper configuration once for reuse
let compose_cmd_wrapper =
parse_multiline_command(&stack.config.compose_cmd_wrapper);
// If wrapper_include is empty but wrapper is set, use default ["up"] for backward compatibility
let default_include = vec![String::from("up")];
let wrapper_include =
if stack.config.compose_cmd_wrapper_include.is_empty()
&& !compose_cmd_wrapper.is_empty()
{
&default_include
} else {
&stack.config.compose_cmd_wrapper_include
};
// Uses 'docker compose config' command to extract services (including image)
// after performing interpolation
{
let command = format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} config",
);
let (command, wrapped) = match maybe_wrap_command(
command,
&compose_cmd_wrapper,
wrapper_include,
"config",
) {
Ok(result) => result,
Err(log) => {
res.logs.push(log);
return Ok(res);
}
};
let mode = if wrapped {
KomodoCommandMode::Shell
} else {
KomodoCommandMode::Standard
};
let span = info_span!("GetComposeConfig", command);
let Some(config_log) = run_komodo_command_with_sanitization(
"Compose Config",
run_directory.as_path(),
command,
mode,
KomodoCommandMode::Standard,
&replacers,
)
.instrument(span)
.await
else {
// Only reachable if command is empty,
// not the case since it is provided above.
unreachable!()
};
if !config_log.success {
@@ -627,29 +558,12 @@ impl Resolve<crate::api::Args> for ComposeUp {
let command = format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} build{build_extra_args}{service_args}",
);
let (command, wrapped) = match maybe_wrap_command(
command,
&compose_cmd_wrapper,
wrapper_include,
"build",
) {
Ok(result) => result,
Err(log) => {
res.logs.push(log);
return Ok(res);
}
};
let mode = if wrapped {
KomodoCommandMode::Shell
} else {
KomodoCommandMode::Standard
};
let span = info_span!("ExecuteComposeBuild");
let Some(log) = run_komodo_command_with_sanitization(
"Compose Build",
run_directory.as_path(),
command,
mode,
KomodoCommandMode::Shell,
&replacers,
)
.instrument(span)
@@ -670,36 +584,14 @@ impl Resolve<crate::api::Args> for ComposeUp {
let command = format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} pull{service_args}",
);
let (command, wrapped) = match maybe_wrap_command(
command,
&compose_cmd_wrapper,
wrapper_include,
"pull",
) {
Ok(result) => result,
Err(log) => {
res.logs.push(log);
return Ok(res);
}
};
let mode = if wrapped {
KomodoCommandMode::Shell
} else {
KomodoCommandMode::Standard
};
let span = info_span!("RunComposePull");
let Some(log) = run_komodo_command_with_sanitization(
let log = run_komodo_standard_command(
"Compose Pull",
run_directory.as_path(),
run_directory.as_ref(),
command,
mode,
&replacers,
)
.instrument(span)
.await
else {
unreachable!()
};
.await;
res.logs.push(log);
if !all_logs_success(&res.logs) {
return Ok(res);
@@ -719,21 +611,24 @@ impl Resolve<crate::api::Args> for ComposeUp {
// Run compose up
let extra_args = format_extra_args(&stack.config.extra_args);
let command = format!(
let mut command = format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} up -d{extra_args}{service_args}",
);
let (command, _) = match maybe_wrap_command(
command,
&compose_cmd_wrapper,
wrapper_include,
"up",
) {
Ok(result) => result,
Err(log) => {
res.logs.push(log);
// Apply compose cmd wrapper if configured
let compose_cmd_wrapper =
parse_multiline_command(&stack.config.compose_cmd_wrapper);
if !compose_cmd_wrapper.is_empty() {
if !compose_cmd_wrapper.contains("[[COMPOSE_COMMAND]]") {
res.logs.push(Log::error(
"Compose Command Wrapper",
"compose_cmd_wrapper is configured but does not contain [[COMPOSE_COMMAND]] placeholder. The placeholder is required to inject the compose command.".to_string(),
));
return Ok(res);
}
};
command =
compose_cmd_wrapper.replace("[[COMPOSE_COMMAND]]", &command);
}
let span = info_span!("ExecuteComposeUp");
let Some(log) = run_komodo_command_with_sanitization(
@@ -867,8 +762,8 @@ impl Resolve<crate::api::Args> for ComposeRun {
}
};
let run_directory = run_directory.canonicalize().with_context(||
format!("Failed to validate run directory on host after stack write (canonicalize error), path={}", run_directory.to_string_lossy())
let run_directory = run_directory.canonicalize().context(
"Failed to validate run directory on host after stack write (canonicalize error)",
)?;
maybe_login_registry(&stack, registry_token, &mut Vec::new())
@@ -889,49 +784,15 @@ impl Resolve<crate::api::Args> for ComposeRun {
let project_name = stack.project_name(true);
// Parse wrapper configuration
let compose_cmd_wrapper =
parse_multiline_command(&stack.config.compose_cmd_wrapper);
// If wrapper_include is empty but wrapper is set, use default ["up"] for backward compatibility
let default_include = vec![String::from("up")];
let wrapper_include =
if stack.config.compose_cmd_wrapper_include.is_empty()
&& !compose_cmd_wrapper.is_empty()
{
&default_include
} else {
&stack.config.compose_cmd_wrapper_include
};
if pull.unwrap_or_default() {
let pull_command = format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} pull {service}",
);
let (pull_command, wrapped) = match maybe_wrap_command(
pull_command,
&compose_cmd_wrapper,
wrapper_include,
"pull",
) {
Ok(result) => result,
Err(log) => return Ok(log),
};
let mode = if wrapped {
KomodoCommandMode::Shell
} else {
KomodoCommandMode::Standard
};
let Some(pull_log) = run_komodo_command_with_sanitization(
let pull_log = run_komodo_standard_command(
"Compose Pull",
run_directory.as_path(),
pull_command,
mode,
&replacers,
run_directory.as_ref(),
format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} pull {service}",
),
)
.await
else {
unreachable!()
};
.await;
if !pull_log.success {
return Ok(pull_log);
}
@@ -978,24 +839,15 @@ impl Resolve<crate::api::Args> for ComposeRun {
})
.unwrap_or_default();
let run_command = format!(
let command = format!(
"{docker_compose} -p {project_name} -f {file_args}{env_file_args} run{run_flags} {service}{command_args}",
);
let (run_command, _) = match maybe_wrap_command(
run_command,
&compose_cmd_wrapper,
wrapper_include,
"run",
) {
Ok(result) => result,
Err(log) => return Ok(log),
};
let span = info_span!("RunComposeRun", run_command);
let span = info_span!("RunComposeRun", command);
let Some(log) = run_komodo_command_with_sanitization(
"Compose Run",
run_directory.as_path(),
run_command,
command,
KomodoCommandMode::Shell,
&replacers,
)
@@ -1036,33 +888,6 @@ fn env_file_args(
Ok(res)
}
/// Apply compose_cmd_wrapper to command if the subcommand is in wrapper_include list.
/// Returns Ok((command, wrapped)) where `wrapped` indicates if wrapper was applied.
/// Returns Err(Log) if wrapper is invalid (missing placeholder).
fn maybe_wrap_command(
command: String,
wrapper: &str,
wrapper_include: &[String],
subcommand: &str,
) -> Result<(String, bool), Log> {
// Skip wrapping if wrapper is empty or subcommand is not in include list
if wrapper.is_empty()
|| !wrapper_include.iter().any(|c| c == subcommand)
{
return Ok((command, false));
}
// Validate wrapper contains placeholder
if !wrapper.contains("[[COMPOSE_COMMAND]]") {
return Err(Log::error(
"Compose Command Wrapper",
"compose_cmd_wrapper is configured but does not contain [[COMPOSE_COMMAND]] placeholder. The placeholder is required to inject the compose command.".to_string(),
));
}
Ok((wrapper.replace("[[COMPOSE_COMMAND]]", &command), true))
}
#[instrument("ComposeDown", skip(res))]
async fn compose_down(
project: &str,
+12 -68
View File
@@ -30,32 +30,6 @@ use crate::{
state::docker_client,
};
/// Apply compose_cmd_wrapper to command if the subcommand is in wrapper_include list.
/// Returns Ok((command, wrapped)) where `wrapped` indicates if wrapper was applied.
fn maybe_wrap_command(
command: String,
wrapper: &str,
wrapper_include: &[String],
subcommand: &str,
) -> Result<(String, bool), Log> {
// Skip wrapping if wrapper is empty or subcommand is not in include list
if wrapper.is_empty()
|| !wrapper_include.iter().any(|c| c == subcommand)
{
return Ok((command, false));
}
// Validate wrapper contains placeholder
if !wrapper.contains("[[COMPOSE_COMMAND]]") {
return Err(Log::error(
"Compose Command Wrapper",
"compose_cmd_wrapper is configured but does not contain [[COMPOSE_COMMAND]] placeholder. The placeholder is required to inject the compose command.".to_string(),
));
}
Ok((wrapper.replace("[[COMPOSE_COMMAND]]", &command), true))
}
impl Resolve<crate::api::Args> for InspectSwarmStack {
async fn resolve(
self,
@@ -204,47 +178,16 @@ impl Resolve<crate::api::Args> for DeploySwarmStack {
let last_project_name = stack.project_name(false);
let project_name = stack.project_name(true);
// Parse wrapper configuration once for reuse
let compose_cmd_wrapper =
parse_multiline_command(&stack.config.compose_cmd_wrapper);
// If wrapper_include is empty but wrapper is set, use default ["deploy"] for backward compatibility
let default_include = vec![String::from("deploy")];
let wrapper_include =
if stack.config.compose_cmd_wrapper_include.is_empty()
&& !compose_cmd_wrapper.is_empty()
{
&default_include
} else {
&stack.config.compose_cmd_wrapper_include
};
// Uses 'docker stack config' command to extract services (including image)
// after performing interpolation
{
let command = format!("docker stack config -c {file_args}",);
let (command, wrapped) = match maybe_wrap_command(
command,
&compose_cmd_wrapper,
wrapper_include,
"config",
) {
Ok(result) => result,
Err(log) => {
res.logs.push(log);
return Ok(res);
}
};
let mode = if wrapped {
KomodoCommandMode::Shell
} else {
KomodoCommandMode::Standard
};
let span = info_span!("GetStackConfig", command);
let Some(config_log) = run_komodo_command_with_sanitization(
"Stack Config",
run_directory.as_path(),
command,
mode,
KomodoCommandMode::Standard,
&replacers,
)
.instrument(span)
@@ -297,18 +240,19 @@ impl Resolve<crate::api::Args> for DeploySwarmStack {
write!(&mut command, " {project_name}")?;
// Apply compose cmd wrapper if configured
let (command, _) = match maybe_wrap_command(
command,
&compose_cmd_wrapper,
wrapper_include,
"deploy",
) {
Ok(result) => result,
Err(log) => {
res.logs.push(log);
let compose_cmd_wrapper =
parse_multiline_command(&stack.config.compose_cmd_wrapper);
if !compose_cmd_wrapper.is_empty() {
if !compose_cmd_wrapper.contains("[[COMPOSE_COMMAND]]") {
res.logs.push(Log::error(
"Compose Command Wrapper",
"compose_cmd_wrapper is configured but does not contain [[COMPOSE_COMMAND]] placeholder. The placeholder is required to inject the compose command.".to_string(),
));
return Ok(res);
}
};
command =
compose_cmd_wrapper.replace("[[COMPOSE_COMMAND]]", &command);
}
let span = info_span!("ExecuteStackDeploy");
let Some(log) = run_komodo_command_with_sanitization(
+10 -40
View File
@@ -3,7 +3,7 @@ use std::sync::Arc;
use anyhow::{Context, anyhow};
use futures_util::{Stream, StreamExt, TryStreamExt};
use komodo_client::entities::{
KOMODO_EXIT_CODE, NoData, optional_string,
KOMODO_EXIT_CODE, NoData,
terminal::{Terminal, TerminalStdinMessage, TerminalTarget},
};
use mogh_resolver::Resolve;
@@ -52,32 +52,20 @@ impl Resolve<crate::api::Args> for CreateServerTerminal {
async fn resolve(
self,
args: &crate::api::Args,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<NoData> {
if periphery_config().disable_terminals {
return Err(anyhow!(
"Terminals are disabled in the Periphery config"
));
}
let existing =
list_terminals(Some(&TerminalTarget::Server { server: None }))
.await;
create_terminal(
self
.name
.and_then(optional_string)
.unwrap_or_else(|| format!("term-{}", existing.len())),
self.name,
TerminalTarget::Server { server: None },
self.command,
self.recreate,
)
.await
.map(|terminal| Terminal {
name: terminal.name.clone(),
target: TerminalTarget::Server { server: None },
command: terminal.command.clone(),
stored_size_kb: terminal.history.size_kb(),
created_at: terminal.created_at,
})
.map(|_| NoData {})
}
}
@@ -99,7 +87,7 @@ impl Resolve<crate::api::Args> for CreateContainerExecTerminal {
async fn resolve(
self,
args: &crate::api::Args,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<NoData> {
if periphery_config().disable_container_terminals {
return Err(anyhow!(
"Container Terminals are disabled in the Periphery config"
@@ -118,23 +106,14 @@ impl Resolve<crate::api::Args> for CreateContainerExecTerminal {
"The use of '&&' is forbidden in the container name or command"
));
}
let existing = list_terminals(Some(&target)).await;
create_terminal(
name.and_then(optional_string).unwrap_or_else(|| {
format!("exec-{container}-{}", existing.len())
}),
name,
target,
Some(format!("docker exec -it {container} {command}")),
recreate,
)
.await
.map(|terminal| Terminal {
name: terminal.name.clone(),
target: terminal.target.clone(),
command: terminal.command.clone(),
stored_size_kb: terminal.history.size_kb(),
created_at: terminal.created_at,
})
.map(|_| NoData {})
}
}
@@ -155,7 +134,7 @@ impl Resolve<crate::api::Args> for CreateContainerAttachTerminal {
async fn resolve(
self,
args: &crate::api::Args,
) -> anyhow::Result<Terminal> {
) -> anyhow::Result<NoData> {
if periphery_config().disable_container_terminals {
return Err(anyhow!(
"Container Terminals are disabled in the Periphery config"
@@ -172,23 +151,14 @@ impl Resolve<crate::api::Args> for CreateContainerAttachTerminal {
"The use of '&&' is forbidden in the container name"
));
}
let existing = list_terminals(Some(&target)).await;
create_terminal(
name.and_then(optional_string).unwrap_or_else(|| {
format!("attach-{container}-{}", existing.len())
}),
name,
target,
Some(format!("docker attach {container} --sig-proxy=false")),
recreate,
)
.await
.map(|terminal| Terminal {
name: terminal.name.clone(),
target: terminal.target.clone(),
command: terminal.command.clone(),
stored_size_kb: terminal.history.size_kb(),
created_at: terminal.created_at,
})
.map(|_| NoData {})
}
}
+46 -46
View File
@@ -461,80 +461,80 @@ impl DockerClient {
}
fn convert_summary_container_state(
state: bollard::config::ContainerSummaryStateEnum,
state: bollard::secret::ContainerSummaryStateEnum,
) -> ContainerStateStatusEnum {
match state {
bollard::config::ContainerSummaryStateEnum::EMPTY => {
bollard::secret::ContainerSummaryStateEnum::EMPTY => {
ContainerStateStatusEnum::Empty
}
bollard::config::ContainerSummaryStateEnum::CREATED => {
bollard::secret::ContainerSummaryStateEnum::CREATED => {
ContainerStateStatusEnum::Created
}
bollard::config::ContainerSummaryStateEnum::RUNNING => {
bollard::secret::ContainerSummaryStateEnum::RUNNING => {
ContainerStateStatusEnum::Running
}
bollard::config::ContainerSummaryStateEnum::PAUSED => {
bollard::secret::ContainerSummaryStateEnum::PAUSED => {
ContainerStateStatusEnum::Paused
}
bollard::config::ContainerSummaryStateEnum::RESTARTING => {
bollard::secret::ContainerSummaryStateEnum::RESTARTING => {
ContainerStateStatusEnum::Restarting
}
bollard::config::ContainerSummaryStateEnum::EXITED => {
bollard::secret::ContainerSummaryStateEnum::EXITED => {
ContainerStateStatusEnum::Exited
}
bollard::config::ContainerSummaryStateEnum::REMOVING => {
bollard::secret::ContainerSummaryStateEnum::REMOVING => {
ContainerStateStatusEnum::Removing
}
bollard::config::ContainerSummaryStateEnum::DEAD => {
bollard::secret::ContainerSummaryStateEnum::DEAD => {
ContainerStateStatusEnum::Dead
}
}
}
fn convert_container_state_status(
state: bollard::config::ContainerStateStatusEnum,
state: bollard::secret::ContainerStateStatusEnum,
) -> ContainerStateStatusEnum {
match state {
bollard::config::ContainerStateStatusEnum::EMPTY => {
bollard::secret::ContainerStateStatusEnum::EMPTY => {
ContainerStateStatusEnum::Empty
}
bollard::config::ContainerStateStatusEnum::CREATED => {
bollard::secret::ContainerStateStatusEnum::CREATED => {
ContainerStateStatusEnum::Created
}
bollard::config::ContainerStateStatusEnum::RUNNING => {
bollard::secret::ContainerStateStatusEnum::RUNNING => {
ContainerStateStatusEnum::Running
}
bollard::config::ContainerStateStatusEnum::PAUSED => {
bollard::secret::ContainerStateStatusEnum::PAUSED => {
ContainerStateStatusEnum::Paused
}
bollard::config::ContainerStateStatusEnum::RESTARTING => {
bollard::secret::ContainerStateStatusEnum::RESTARTING => {
ContainerStateStatusEnum::Restarting
}
bollard::config::ContainerStateStatusEnum::EXITED => {
bollard::secret::ContainerStateStatusEnum::EXITED => {
ContainerStateStatusEnum::Exited
}
bollard::config::ContainerStateStatusEnum::REMOVING => {
bollard::secret::ContainerStateStatusEnum::REMOVING => {
ContainerStateStatusEnum::Removing
}
bollard::config::ContainerStateStatusEnum::DEAD => {
bollard::secret::ContainerStateStatusEnum::DEAD => {
ContainerStateStatusEnum::Dead
}
}
}
fn convert_port_type(
typ: bollard::config::PortSummaryTypeEnum,
typ: bollard::secret::PortSummaryTypeEnum,
) -> PortTypeEnum {
match typ {
bollard::config::PortSummaryTypeEnum::EMPTY => {
bollard::secret::PortSummaryTypeEnum::EMPTY => {
PortTypeEnum::EMPTY
}
bollard::config::PortSummaryTypeEnum::TCP => PortTypeEnum::TCP,
bollard::config::PortSummaryTypeEnum::UDP => PortTypeEnum::UDP,
bollard::config::PortSummaryTypeEnum::SCTP => PortTypeEnum::SCTP,
bollard::secret::PortSummaryTypeEnum::TCP => PortTypeEnum::TCP,
bollard::secret::PortSummaryTypeEnum::UDP => PortTypeEnum::UDP,
bollard::secret::PortSummaryTypeEnum::SCTP => PortTypeEnum::SCTP,
}
}
fn convert_port(port: bollard::config::PortSummary) -> Port {
fn convert_port(port: bollard::secret::PortSummary) -> Port {
Port {
ip: port.ip,
private_port: port.private_port,
@@ -544,27 +544,27 @@ fn convert_port(port: bollard::config::PortSummary) -> Port {
}
fn convert_health_status(
status: bollard::config::HealthStatusEnum,
status: bollard::secret::HealthStatusEnum,
) -> HealthStatusEnum {
match status {
bollard::config::HealthStatusEnum::EMPTY => {
bollard::secret::HealthStatusEnum::EMPTY => {
HealthStatusEnum::Empty
}
bollard::config::HealthStatusEnum::NONE => HealthStatusEnum::None,
bollard::config::HealthStatusEnum::STARTING => {
bollard::secret::HealthStatusEnum::NONE => HealthStatusEnum::None,
bollard::secret::HealthStatusEnum::STARTING => {
HealthStatusEnum::Starting
}
bollard::config::HealthStatusEnum::HEALTHY => {
bollard::secret::HealthStatusEnum::HEALTHY => {
HealthStatusEnum::Healthy
}
bollard::config::HealthStatusEnum::UNHEALTHY => {
bollard::secret::HealthStatusEnum::UNHEALTHY => {
HealthStatusEnum::Unhealthy
}
}
}
fn convert_health_check_result(
check: bollard::config::HealthcheckResult,
check: bollard::secret::HealthcheckResult,
) -> HealthcheckResult {
HealthcheckResult {
start: check.start,
@@ -575,57 +575,57 @@ fn convert_health_check_result(
}
fn convert_restart_policy(
policy: bollard::config::RestartPolicyNameEnum,
policy: bollard::secret::RestartPolicyNameEnum,
) -> RestartPolicyNameEnum {
match policy {
bollard::config::RestartPolicyNameEnum::EMPTY => {
bollard::secret::RestartPolicyNameEnum::EMPTY => {
RestartPolicyNameEnum::Empty
}
bollard::config::RestartPolicyNameEnum::NO => {
bollard::secret::RestartPolicyNameEnum::NO => {
RestartPolicyNameEnum::No
}
bollard::config::RestartPolicyNameEnum::ALWAYS => {
bollard::secret::RestartPolicyNameEnum::ALWAYS => {
RestartPolicyNameEnum::Always
}
bollard::config::RestartPolicyNameEnum::UNLESS_STOPPED => {
bollard::secret::RestartPolicyNameEnum::UNLESS_STOPPED => {
RestartPolicyNameEnum::UnlessStopped
}
bollard::config::RestartPolicyNameEnum::ON_FAILURE => {
bollard::secret::RestartPolicyNameEnum::ON_FAILURE => {
RestartPolicyNameEnum::OnFailure
}
}
}
fn convert_cgroupns_mode(
mode: bollard::config::HostConfigCgroupnsModeEnum,
mode: bollard::secret::HostConfigCgroupnsModeEnum,
) -> HostConfigCgroupnsModeEnum {
match mode {
bollard::config::HostConfigCgroupnsModeEnum::EMPTY => {
bollard::secret::HostConfigCgroupnsModeEnum::EMPTY => {
HostConfigCgroupnsModeEnum::Empty
}
bollard::config::HostConfigCgroupnsModeEnum::PRIVATE => {
bollard::secret::HostConfigCgroupnsModeEnum::PRIVATE => {
HostConfigCgroupnsModeEnum::Private
}
bollard::config::HostConfigCgroupnsModeEnum::HOST => {
bollard::secret::HostConfigCgroupnsModeEnum::HOST => {
HostConfigCgroupnsModeEnum::Host
}
}
}
fn convert_isolation_mode(
isolation: bollard::config::HostConfigIsolationEnum,
isolation: bollard::secret::HostConfigIsolationEnum,
) -> HostConfigIsolationEnum {
match isolation {
bollard::config::HostConfigIsolationEnum::EMPTY => {
bollard::secret::HostConfigIsolationEnum::EMPTY => {
HostConfigIsolationEnum::Empty
}
bollard::config::HostConfigIsolationEnum::DEFAULT => {
bollard::secret::HostConfigIsolationEnum::DEFAULT => {
HostConfigIsolationEnum::Default
}
bollard::config::HostConfigIsolationEnum::PROCESS => {
bollard::secret::HostConfigIsolationEnum::PROCESS => {
HostConfigIsolationEnum::Process
}
bollard::config::HostConfigIsolationEnum::HYPERV => {
bollard::secret::HostConfigIsolationEnum::HYPERV => {
HostConfigIsolationEnum::Hyperv
}
}
+8 -7
View File
@@ -29,7 +29,8 @@ impl DockerClient {
});
let name = image
.repo_tags
.first()
.iter()
.next()
.cloned()
.unwrap_or_else(|| image.id.clone());
ImageListItem {
@@ -72,10 +73,10 @@ impl DockerClient {
content: manifest.size.content,
},
kind: manifest.kind.map(|kind| match kind {
bollard::config::ImageManifestSummaryKindEnum::EMPTY => ImageManifestSummaryKindEnum::Empty,
bollard::config::ImageManifestSummaryKindEnum::IMAGE => ImageManifestSummaryKindEnum::Image,
bollard::config::ImageManifestSummaryKindEnum::ATTESTATION => ImageManifestSummaryKindEnum::Attestation,
bollard::config::ImageManifestSummaryKindEnum::UNKNOWN => ImageManifestSummaryKindEnum::Unknown,
bollard::secret::ImageManifestSummaryKindEnum::EMPTY => ImageManifestSummaryKindEnum::Empty,
bollard::secret::ImageManifestSummaryKindEnum::IMAGE => ImageManifestSummaryKindEnum::Image,
bollard::secret::ImageManifestSummaryKindEnum::ATTESTATION => ImageManifestSummaryKindEnum::Attestation,
bollard::secret::ImageManifestSummaryKindEnum::UNKNOWN => ImageManifestSummaryKindEnum::Unknown,
}),
image_data: manifest.image_data.map(|data| {
ImageManifestSummaryImageData {
@@ -159,7 +160,7 @@ impl DockerClient {
}
fn convert_oci_descriptor(
descriptor: bollard::config::OciDescriptor,
descriptor: bollard::secret::OciDescriptor,
) -> OciDescriptor {
OciDescriptor {
media_type: descriptor.media_type,
@@ -174,7 +175,7 @@ fn convert_oci_descriptor(
}
fn convert_oci_platform(
platform: bollard::config::OciPlatform,
platform: bollard::secret::OciPlatform,
) -> OciPlatform {
OciPlatform {
architecture: platform.architecture,
+47 -47
View File
@@ -151,68 +151,68 @@ fn convert_mount(mount: bollard::models::Mount) -> Mount {
}
fn convert_mount_type(
typ: bollard::config::MountTypeEnum,
typ: bollard::secret::MountTypeEnum,
) -> MountTypeEnum {
match typ {
bollard::config::MountTypeEnum::EMPTY => MountTypeEnum::Empty,
bollard::config::MountTypeEnum::BIND => MountTypeEnum::Bind,
bollard::config::MountTypeEnum::VOLUME => MountTypeEnum::Volume,
bollard::config::MountTypeEnum::IMAGE => MountTypeEnum::Image,
bollard::config::MountTypeEnum::TMPFS => MountTypeEnum::Tmpfs,
bollard::config::MountTypeEnum::NPIPE => MountTypeEnum::Npipe,
bollard::config::MountTypeEnum::CLUSTER => MountTypeEnum::Cluster,
bollard::secret::MountTypeEnum::EMPTY => MountTypeEnum::Empty,
bollard::secret::MountTypeEnum::BIND => MountTypeEnum::Bind,
bollard::secret::MountTypeEnum::VOLUME => MountTypeEnum::Volume,
bollard::secret::MountTypeEnum::IMAGE => MountTypeEnum::Image,
bollard::secret::MountTypeEnum::TMPFS => MountTypeEnum::Tmpfs,
bollard::secret::MountTypeEnum::NPIPE => MountTypeEnum::Npipe,
bollard::secret::MountTypeEnum::CLUSTER => MountTypeEnum::Cluster,
}
}
fn convert_mount_propogation(
propogation: bollard::config::MountBindOptionsPropagationEnum,
propogation: bollard::secret::MountBindOptionsPropagationEnum,
) -> MountBindOptionsPropagationEnum {
match propogation {
bollard::config::MountBindOptionsPropagationEnum::EMPTY => {
bollard::secret::MountBindOptionsPropagationEnum::EMPTY => {
MountBindOptionsPropagationEnum::Empty
}
bollard::config::MountBindOptionsPropagationEnum::PRIVATE => {
bollard::secret::MountBindOptionsPropagationEnum::PRIVATE => {
MountBindOptionsPropagationEnum::Private
}
bollard::config::MountBindOptionsPropagationEnum::RPRIVATE => {
bollard::secret::MountBindOptionsPropagationEnum::RPRIVATE => {
MountBindOptionsPropagationEnum::Rprivate
}
bollard::config::MountBindOptionsPropagationEnum::SHARED => {
bollard::secret::MountBindOptionsPropagationEnum::SHARED => {
MountBindOptionsPropagationEnum::Shared
}
bollard::config::MountBindOptionsPropagationEnum::RSHARED => {
bollard::secret::MountBindOptionsPropagationEnum::RSHARED => {
MountBindOptionsPropagationEnum::Rshared
}
bollard::config::MountBindOptionsPropagationEnum::SLAVE => {
bollard::secret::MountBindOptionsPropagationEnum::SLAVE => {
MountBindOptionsPropagationEnum::Slave
}
bollard::config::MountBindOptionsPropagationEnum::RSLAVE => {
bollard::secret::MountBindOptionsPropagationEnum::RSLAVE => {
MountBindOptionsPropagationEnum::Rslave
}
}
}
fn convert_mount_point_type(
typ: bollard::config::MountPointTypeEnum,
typ: bollard::secret::MountPointTypeEnum,
) -> MountTypeEnum {
match typ {
bollard::config::MountPointTypeEnum::EMPTY => {
bollard::secret::MountPointTypeEnum::EMPTY => {
MountTypeEnum::Empty
}
bollard::config::MountPointTypeEnum::BIND => MountTypeEnum::Bind,
bollard::config::MountPointTypeEnum::VOLUME => {
bollard::secret::MountPointTypeEnum::BIND => MountTypeEnum::Bind,
bollard::secret::MountPointTypeEnum::VOLUME => {
MountTypeEnum::Volume
}
bollard::config::MountPointTypeEnum::IMAGE => {
bollard::secret::MountPointTypeEnum::IMAGE => {
MountTypeEnum::Image
}
bollard::config::MountPointTypeEnum::TMPFS => {
bollard::secret::MountPointTypeEnum::TMPFS => {
MountTypeEnum::Tmpfs
}
bollard::config::MountPointTypeEnum::NPIPE => {
bollard::secret::MountPointTypeEnum::NPIPE => {
MountTypeEnum::Npipe
}
bollard::config::MountPointTypeEnum::CLUSTER => {
bollard::secret::MountPointTypeEnum::CLUSTER => {
MountTypeEnum::Cluster
}
}
@@ -290,17 +290,17 @@ fn convert_endpoint_spec_ports(
.map(|port| EndpointPortConfig {
name: port.name,
protocol: port.protocol.map(|protocol| match protocol {
bollard::config::EndpointPortConfigProtocolEnum::EMPTY => EndpointPortConfigProtocolEnum::EMPTY,
bollard::config::EndpointPortConfigProtocolEnum::TCP => EndpointPortConfigProtocolEnum::TCP,
bollard::config::EndpointPortConfigProtocolEnum::UDP => EndpointPortConfigProtocolEnum::UDP,
bollard::config::EndpointPortConfigProtocolEnum::SCTP => EndpointPortConfigProtocolEnum::SCTP,
bollard::secret::EndpointPortConfigProtocolEnum::EMPTY => EndpointPortConfigProtocolEnum::EMPTY,
bollard::secret::EndpointPortConfigProtocolEnum::TCP => EndpointPortConfigProtocolEnum::TCP,
bollard::secret::EndpointPortConfigProtocolEnum::UDP => EndpointPortConfigProtocolEnum::UDP,
bollard::secret::EndpointPortConfigProtocolEnum::SCTP => EndpointPortConfigProtocolEnum::SCTP,
}),
target_port: port.target_port,
published_port: port.published_port,
publish_mode: port.publish_mode.map(|protocol| match protocol {
bollard::config::EndpointPortConfigPublishModeEnum::EMPTY => EndpointPortConfigPublishModeEnum::EMPTY,
bollard::config::EndpointPortConfigPublishModeEnum::INGRESS => EndpointPortConfigPublishModeEnum::INGRESS,
bollard::config::EndpointPortConfigPublishModeEnum::HOST => EndpointPortConfigPublishModeEnum::HOST,
bollard::secret::EndpointPortConfigPublishModeEnum::EMPTY => EndpointPortConfigPublishModeEnum::EMPTY,
bollard::secret::EndpointPortConfigPublishModeEnum::INGRESS => EndpointPortConfigPublishModeEnum::INGRESS,
bollard::secret::EndpointPortConfigPublishModeEnum::HOST => EndpointPortConfigPublishModeEnum::HOST,
}),
})
.collect()
@@ -423,10 +423,10 @@ fn convert_task_spec_container_spec(
seccomp: privilege.seccomp.map(|seccomp| {
TaskSpecContainerSpecPrivilegesSeccomp {
mode: seccomp.mode.map(|mode| match mode {
bollard::config::TaskSpecContainerSpecPrivilegesSeccompModeEnum::EMPTY => TaskSpecContainerSpecPrivilegesSeccompModeEnum::EMPTY,
bollard::config::TaskSpecContainerSpecPrivilegesSeccompModeEnum::DEFAULT => TaskSpecContainerSpecPrivilegesSeccompModeEnum::DEFAULT,
bollard::config::TaskSpecContainerSpecPrivilegesSeccompModeEnum::UNCONFINED => TaskSpecContainerSpecPrivilegesSeccompModeEnum::UNCONFINED,
bollard::config::TaskSpecContainerSpecPrivilegesSeccompModeEnum::CUSTOM => TaskSpecContainerSpecPrivilegesSeccompModeEnum::CUSTOM,
bollard::secret::TaskSpecContainerSpecPrivilegesSeccompModeEnum::EMPTY => TaskSpecContainerSpecPrivilegesSeccompModeEnum::EMPTY,
bollard::secret::TaskSpecContainerSpecPrivilegesSeccompModeEnum::DEFAULT => TaskSpecContainerSpecPrivilegesSeccompModeEnum::DEFAULT,
bollard::secret::TaskSpecContainerSpecPrivilegesSeccompModeEnum::UNCONFINED => TaskSpecContainerSpecPrivilegesSeccompModeEnum::UNCONFINED,
bollard::secret::TaskSpecContainerSpecPrivilegesSeccompModeEnum::CUSTOM => TaskSpecContainerSpecPrivilegesSeccompModeEnum::CUSTOM,
}),
profile: seccomp.profile,
}
@@ -434,9 +434,9 @@ fn convert_task_spec_container_spec(
app_armor: privilege.app_armor.map(|app_armor| {
TaskSpecContainerSpecPrivilegesAppArmor {
mode: app_armor.mode.map(|mode| match mode {
bollard::config::TaskSpecContainerSpecPrivilegesAppArmorModeEnum::EMPTY => TaskSpecContainerSpecPrivilegesAppArmorModeEnum::EMPTY,
bollard::config::TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DEFAULT => TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DEFAULT,
bollard::config::TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DISABLED => TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DISABLED,
bollard::secret::TaskSpecContainerSpecPrivilegesAppArmorModeEnum::EMPTY => TaskSpecContainerSpecPrivilegesAppArmorModeEnum::EMPTY,
bollard::secret::TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DEFAULT => TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DEFAULT,
bollard::secret::TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DISABLED => TaskSpecContainerSpecPrivilegesAppArmorModeEnum::DISABLED,
}),
}
}),
@@ -478,10 +478,10 @@ fn convert_task_spec_container_spec(
config_name: config.config_name,
}).collect()),
isolation: spec.isolation.map(|isolation| match isolation {
bollard::config::TaskSpecContainerSpecIsolationEnum::DEFAULT => TaskSpecContainerSpecIsolationEnum::DEFAULT,
bollard::config::TaskSpecContainerSpecIsolationEnum::PROCESS => TaskSpecContainerSpecIsolationEnum::PROCESS,
bollard::config::TaskSpecContainerSpecIsolationEnum::HYPERV => TaskSpecContainerSpecIsolationEnum::HYPERV,
bollard::config::TaskSpecContainerSpecIsolationEnum::EMPTY => TaskSpecContainerSpecIsolationEnum::EMPTY,
bollard::secret::TaskSpecContainerSpecIsolationEnum::DEFAULT => TaskSpecContainerSpecIsolationEnum::DEFAULT,
bollard::secret::TaskSpecContainerSpecIsolationEnum::PROCESS => TaskSpecContainerSpecIsolationEnum::PROCESS,
bollard::secret::TaskSpecContainerSpecIsolationEnum::HYPERV => TaskSpecContainerSpecIsolationEnum::HYPERV,
bollard::secret::TaskSpecContainerSpecIsolationEnum::EMPTY => TaskSpecContainerSpecIsolationEnum::EMPTY,
}),
init: spec.init,
sysctls: spec.sysctls,
@@ -492,13 +492,13 @@ fn convert_task_spec_container_spec(
}
fn convert_task_spec_restart_policy_condition(
condition: bollard::config::TaskSpecRestartPolicyConditionEnum,
condition: bollard::secret::TaskSpecRestartPolicyConditionEnum,
) -> TaskSpecRestartPolicyConditionEnum {
match condition {
bollard::config::TaskSpecRestartPolicyConditionEnum::EMPTY => TaskSpecRestartPolicyConditionEnum::EMPTY,
bollard::config::TaskSpecRestartPolicyConditionEnum::NONE => TaskSpecRestartPolicyConditionEnum::NONE,
bollard::config::TaskSpecRestartPolicyConditionEnum::ON_FAILURE => TaskSpecRestartPolicyConditionEnum::ON_FAILURE,
bollard::config::TaskSpecRestartPolicyConditionEnum::ANY => TaskSpecRestartPolicyConditionEnum::ANY,
bollard::secret::TaskSpecRestartPolicyConditionEnum::EMPTY => TaskSpecRestartPolicyConditionEnum::EMPTY,
bollard::secret::TaskSpecRestartPolicyConditionEnum::NONE => TaskSpecRestartPolicyConditionEnum::NONE,
bollard::secret::TaskSpecRestartPolicyConditionEnum::ON_FAILURE => TaskSpecRestartPolicyConditionEnum::ON_FAILURE,
bollard::secret::TaskSpecRestartPolicyConditionEnum::ANY => TaskSpecRestartPolicyConditionEnum::ANY,
}
}
+17 -17
View File
@@ -116,13 +116,13 @@ fn convert_node(node: bollard::models::Node) -> SwarmNode {
leader: manager_status.leader,
reachability: manager_status.reachability.map(
|reachability| match reachability {
bollard::config::Reachability::UNKNOWN => {
bollard::secret::Reachability::UNKNOWN => {
NodeReachability::UNKNOWN
}
bollard::config::Reachability::UNREACHABLE => {
bollard::secret::Reachability::UNREACHABLE => {
NodeReachability::UNREACHABLE
}
bollard::config::Reachability::REACHABLE => {
bollard::secret::Reachability::REACHABLE => {
NodeReachability::REACHABLE
}
},
@@ -143,46 +143,46 @@ fn convert_node_spec(spec: bollard::models::NodeSpec) -> NodeSpec {
}
fn convert_role(
role: bollard::config::NodeSpecRoleEnum,
role: bollard::secret::NodeSpecRoleEnum,
) -> NodeSpecRoleEnum {
match role {
bollard::config::NodeSpecRoleEnum::EMPTY => {
bollard::secret::NodeSpecRoleEnum::EMPTY => {
NodeSpecRoleEnum::EMPTY
}
bollard::config::NodeSpecRoleEnum::WORKER => {
bollard::secret::NodeSpecRoleEnum::WORKER => {
NodeSpecRoleEnum::WORKER
}
bollard::config::NodeSpecRoleEnum::MANAGER => {
bollard::secret::NodeSpecRoleEnum::MANAGER => {
NodeSpecRoleEnum::MANAGER
}
}
}
fn convert_availability(
availability: bollard::config::NodeSpecAvailabilityEnum,
availability: bollard::secret::NodeSpecAvailabilityEnum,
) -> NodeSpecAvailabilityEnum {
match availability {
bollard::config::NodeSpecAvailabilityEnum::EMPTY => {
bollard::secret::NodeSpecAvailabilityEnum::EMPTY => {
NodeSpecAvailabilityEnum::EMPTY
}
bollard::config::NodeSpecAvailabilityEnum::ACTIVE => {
bollard::secret::NodeSpecAvailabilityEnum::ACTIVE => {
NodeSpecAvailabilityEnum::ACTIVE
}
bollard::config::NodeSpecAvailabilityEnum::PAUSE => {
bollard::secret::NodeSpecAvailabilityEnum::PAUSE => {
NodeSpecAvailabilityEnum::PAUSE
}
bollard::config::NodeSpecAvailabilityEnum::DRAIN => {
bollard::secret::NodeSpecAvailabilityEnum::DRAIN => {
NodeSpecAvailabilityEnum::DRAIN
}
}
}
fn convert_state(state: bollard::config::NodeState) -> NodeState {
fn convert_state(state: bollard::secret::NodeState) -> NodeState {
match state {
bollard::config::NodeState::UNKNOWN => NodeState::UNKNOWN,
bollard::config::NodeState::DOWN => NodeState::DOWN,
bollard::config::NodeState::READY => NodeState::READY,
bollard::config::NodeState::DISCONNECTED => {
bollard::secret::NodeState::UNKNOWN => NodeState::UNKNOWN,
bollard::secret::NodeState::DOWN => NodeState::DOWN,
bollard::secret::NodeState::READY => NodeState::READY,
bollard::secret::NodeState::DISCONNECTED => {
NodeState::DISCONNECTED
}
}
+25 -25
View File
@@ -27,7 +27,7 @@ impl DockerClient {
.await
.context("Failed to query for swarm service list")?
.into_iter()
.map(convert_service_list_item)
.map(|service| convert_service_list_item(service))
.collect::<Vec<_>>();
services.sort_by(|a, b| {
@@ -324,17 +324,17 @@ fn convert_service(
parallelism: config.parallelism,
delay: config.delay,
failure_action: config.failure_action.map(|action| match action {
bollard::config::ServiceSpecUpdateConfigFailureActionEnum::EMPTY => ServiceSpecUpdateConfigFailureActionEnum::EMPTY,
bollard::config::ServiceSpecUpdateConfigFailureActionEnum::CONTINUE => ServiceSpecUpdateConfigFailureActionEnum::CONTINUE,
bollard::config::ServiceSpecUpdateConfigFailureActionEnum::PAUSE => ServiceSpecUpdateConfigFailureActionEnum::PAUSE,
bollard::config::ServiceSpecUpdateConfigFailureActionEnum::ROLLBACK => ServiceSpecUpdateConfigFailureActionEnum::ROLLBACK,
bollard::secret::ServiceSpecUpdateConfigFailureActionEnum::EMPTY => ServiceSpecUpdateConfigFailureActionEnum::EMPTY,
bollard::secret::ServiceSpecUpdateConfigFailureActionEnum::CONTINUE => ServiceSpecUpdateConfigFailureActionEnum::CONTINUE,
bollard::secret::ServiceSpecUpdateConfigFailureActionEnum::PAUSE => ServiceSpecUpdateConfigFailureActionEnum::PAUSE,
bollard::secret::ServiceSpecUpdateConfigFailureActionEnum::ROLLBACK => ServiceSpecUpdateConfigFailureActionEnum::ROLLBACK,
}),
monitor: config.monitor,
max_failure_ratio: config.max_failure_ratio,
order: config.order.map(|order| match order {
bollard::config::ServiceSpecUpdateConfigOrderEnum::EMPTY => ServiceSpecUpdateConfigOrderEnum::EMPTY,
bollard::config::ServiceSpecUpdateConfigOrderEnum::STOP_FIRST => ServiceSpecUpdateConfigOrderEnum::STOP_FIRST,
bollard::config::ServiceSpecUpdateConfigOrderEnum::START_FIRST => ServiceSpecUpdateConfigOrderEnum::START_FIRST,
bollard::secret::ServiceSpecUpdateConfigOrderEnum::EMPTY => ServiceSpecUpdateConfigOrderEnum::EMPTY,
bollard::secret::ServiceSpecUpdateConfigOrderEnum::STOP_FIRST => ServiceSpecUpdateConfigOrderEnum::STOP_FIRST,
bollard::secret::ServiceSpecUpdateConfigOrderEnum::START_FIRST => ServiceSpecUpdateConfigOrderEnum::START_FIRST,
}),
}
}),
@@ -343,16 +343,16 @@ fn convert_service(
parallelism: config.parallelism,
delay: config.delay,
failure_action: config.failure_action.map(|action| match action {
bollard::config::ServiceSpecRollbackConfigFailureActionEnum::EMPTY => ServiceSpecRollbackConfigFailureActionEnum::EMPTY,
bollard::config::ServiceSpecRollbackConfigFailureActionEnum::CONTINUE => ServiceSpecRollbackConfigFailureActionEnum::CONTINUE,
bollard::config::ServiceSpecRollbackConfigFailureActionEnum::PAUSE => ServiceSpecRollbackConfigFailureActionEnum::PAUSE,
bollard::secret::ServiceSpecRollbackConfigFailureActionEnum::EMPTY => ServiceSpecRollbackConfigFailureActionEnum::EMPTY,
bollard::secret::ServiceSpecRollbackConfigFailureActionEnum::CONTINUE => ServiceSpecRollbackConfigFailureActionEnum::CONTINUE,
bollard::secret::ServiceSpecRollbackConfigFailureActionEnum::PAUSE => ServiceSpecRollbackConfigFailureActionEnum::PAUSE,
}),
monitor: config.monitor,
max_failure_ratio: config.max_failure_ratio,
order: config.order.map(|order| match order {
bollard::config::ServiceSpecRollbackConfigOrderEnum::EMPTY => ServiceSpecRollbackConfigOrderEnum::EMPTY,
bollard::config::ServiceSpecRollbackConfigOrderEnum::STOP_FIRST => ServiceSpecRollbackConfigOrderEnum::STOP_FIRST,
bollard::config::ServiceSpecRollbackConfigOrderEnum::START_FIRST => ServiceSpecRollbackConfigOrderEnum::START_FIRST,
bollard::secret::ServiceSpecRollbackConfigOrderEnum::EMPTY => ServiceSpecRollbackConfigOrderEnum::EMPTY,
bollard::secret::ServiceSpecRollbackConfigOrderEnum::STOP_FIRST => ServiceSpecRollbackConfigOrderEnum::STOP_FIRST,
bollard::secret::ServiceSpecRollbackConfigOrderEnum::START_FIRST => ServiceSpecRollbackConfigOrderEnum::START_FIRST,
}),
}
}),
@@ -408,13 +408,13 @@ fn convert_endpoint_spec(
) -> EndpointSpec {
EndpointSpec {
mode: spec.mode.map(|mode| match mode {
bollard::config::EndpointSpecModeEnum::EMPTY => {
bollard::secret::EndpointSpecModeEnum::EMPTY => {
EndpointSpecModeEnum::EMPTY
}
bollard::config::EndpointSpecModeEnum::VIP => {
bollard::secret::EndpointSpecModeEnum::VIP => {
EndpointSpecModeEnum::VIP
}
bollard::config::EndpointSpecModeEnum::DNSRR => {
bollard::secret::EndpointSpecModeEnum::DNSRR => {
EndpointSpecModeEnum::DNSRR
}
}),
@@ -423,15 +423,15 @@ fn convert_endpoint_spec(
}
fn convert_state(
state: bollard::config::ServiceUpdateStatusStateEnum,
state: bollard::secret::ServiceUpdateStatusStateEnum,
) -> ServiceUpdateStatusStateEnum {
match state {
bollard::config::ServiceUpdateStatusStateEnum::EMPTY => ServiceUpdateStatusStateEnum::EMPTY,
bollard::config::ServiceUpdateStatusStateEnum::UPDATING => ServiceUpdateStatusStateEnum::UPDATING,
bollard::config::ServiceUpdateStatusStateEnum::PAUSED => ServiceUpdateStatusStateEnum::PAUSED,
bollard::config::ServiceUpdateStatusStateEnum::COMPLETED => ServiceUpdateStatusStateEnum::COMPLETED,
bollard::config::ServiceUpdateStatusStateEnum::ROLLBACK_STARTED => ServiceUpdateStatusStateEnum::ROLLBACK_STARTED,
bollard::config::ServiceUpdateStatusStateEnum::ROLLBACK_PAUSED => ServiceUpdateStatusStateEnum::ROLLBACK_PAUSED,
bollard::config::ServiceUpdateStatusStateEnum::ROLLBACK_COMPLETED => ServiceUpdateStatusStateEnum::ROLLBACK_COMPLETED,
bollard::secret::ServiceUpdateStatusStateEnum::EMPTY => ServiceUpdateStatusStateEnum::EMPTY,
bollard::secret::ServiceUpdateStatusStateEnum::UPDATING => ServiceUpdateStatusStateEnum::UPDATING,
bollard::secret::ServiceUpdateStatusStateEnum::PAUSED => ServiceUpdateStatusStateEnum::PAUSED,
bollard::secret::ServiceUpdateStatusStateEnum::COMPLETED => ServiceUpdateStatusStateEnum::COMPLETED,
bollard::secret::ServiceUpdateStatusStateEnum::ROLLBACK_STARTED => ServiceUpdateStatusStateEnum::ROLLBACK_STARTED,
bollard::secret::ServiceUpdateStatusStateEnum::ROLLBACK_PAUSED => ServiceUpdateStatusStateEnum::ROLLBACK_PAUSED,
bollard::secret::ServiceUpdateStatusStateEnum::ROLLBACK_COMPLETED => ServiceUpdateStatusStateEnum::ROLLBACK_COMPLETED,
}
}
+2 -2
View File
@@ -60,8 +60,8 @@ fn convert_swarm_info(
.into_iter()
.map(|cas| SwarmSpecCaConfigExternalCas {
protocol: cas.protocol.map(|protocol| match protocol {
bollard::config::SwarmSpecCaConfigExternalCasProtocolEnum::EMPTY => SwarmSpecCaConfigExternalCasProtocolEnum::EMPTY,
bollard::config::SwarmSpecCaConfigExternalCasProtocolEnum::CFSSL => SwarmSpecCaConfigExternalCasProtocolEnum::CFSSL,
bollard::secret::SwarmSpecCaConfigExternalCasProtocolEnum::EMPTY => SwarmSpecCaConfigExternalCasProtocolEnum::EMPTY,
bollard::secret::SwarmSpecCaConfigExternalCasProtocolEnum::CFSSL => SwarmSpecCaConfigExternalCasProtocolEnum::CFSSL,
}),
url: cas.url,
options: cas.options,
+15 -15
View File
@@ -135,20 +135,20 @@ fn convert_task_state(
state: bollard::models::TaskState,
) -> TaskState {
match state {
bollard::config::TaskState::NEW => TaskState::NEW,
bollard::config::TaskState::ALLOCATED => TaskState::ALLOCATED,
bollard::config::TaskState::PENDING => TaskState::PENDING,
bollard::config::TaskState::ASSIGNED => TaskState::ASSIGNED,
bollard::config::TaskState::ACCEPTED => TaskState::ACCEPTED,
bollard::config::TaskState::PREPARING => TaskState::PREPARING,
bollard::config::TaskState::READY => TaskState::READY,
bollard::config::TaskState::STARTING => TaskState::STARTING,
bollard::config::TaskState::RUNNING => TaskState::RUNNING,
bollard::config::TaskState::COMPLETE => TaskState::COMPLETE,
bollard::config::TaskState::SHUTDOWN => TaskState::SHUTDOWN,
bollard::config::TaskState::FAILED => TaskState::FAILED,
bollard::config::TaskState::REJECTED => TaskState::REJECTED,
bollard::config::TaskState::REMOVE => TaskState::REMOVE,
bollard::config::TaskState::ORPHANED => TaskState::ORPHANED,
bollard::secret::TaskState::NEW => TaskState::NEW,
bollard::secret::TaskState::ALLOCATED => TaskState::ALLOCATED,
bollard::secret::TaskState::PENDING => TaskState::PENDING,
bollard::secret::TaskState::ASSIGNED => TaskState::ASSIGNED,
bollard::secret::TaskState::ACCEPTED => TaskState::ACCEPTED,
bollard::secret::TaskState::PREPARING => TaskState::PREPARING,
bollard::secret::TaskState::READY => TaskState::READY,
bollard::secret::TaskState::STARTING => TaskState::STARTING,
bollard::secret::TaskState::RUNNING => TaskState::RUNNING,
bollard::secret::TaskState::COMPLETE => TaskState::COMPLETE,
bollard::secret::TaskState::SHUTDOWN => TaskState::SHUTDOWN,
bollard::secret::TaskState::FAILED => TaskState::FAILED,
bollard::secret::TaskState::REJECTED => TaskState::REJECTED,
bollard::secret::TaskState::REMOVE => TaskState::REMOVE,
bollard::secret::TaskState::ORPHANED => TaskState::ORPHANED,
}
}
+23 -23
View File
@@ -21,13 +21,13 @@ impl DockerClient {
let scope = volume
.scope
.map(|scope| match scope {
bollard::config::VolumeScopeEnum::EMPTY => {
bollard::secret::VolumeScopeEnum::EMPTY => {
VolumeScopeEnum::Empty
}
bollard::config::VolumeScopeEnum::LOCAL => {
bollard::secret::VolumeScopeEnum::LOCAL => {
VolumeScopeEnum::Local
}
bollard::config::VolumeScopeEnum::GLOBAL => {
bollard::secret::VolumeScopeEnum::GLOBAL => {
VolumeScopeEnum::Global
}
})
@@ -69,13 +69,13 @@ impl DockerClient {
scope: volume
.scope
.map(|scope| match scope {
bollard::config::VolumeScopeEnum::EMPTY => {
bollard::secret::VolumeScopeEnum::EMPTY => {
VolumeScopeEnum::Empty
}
bollard::config::VolumeScopeEnum::LOCAL => {
bollard::secret::VolumeScopeEnum::LOCAL => {
VolumeScopeEnum::Local
}
bollard::config::VolumeScopeEnum::GLOBAL => {
bollard::secret::VolumeScopeEnum::GLOBAL => {
VolumeScopeEnum::Global
}
})
@@ -91,16 +91,16 @@ impl DockerClient {
access_mode: spec.access_mode.map(|mode| {
ClusterVolumeSpecAccessMode {
scope: mode.scope.map(|scope| match scope {
bollard::config::ClusterVolumeSpecAccessModeScopeEnum::EMPTY => ClusterVolumeSpecAccessModeScopeEnum::Empty,
bollard::config::ClusterVolumeSpecAccessModeScopeEnum::SINGLE => ClusterVolumeSpecAccessModeScopeEnum::Single,
bollard::config::ClusterVolumeSpecAccessModeScopeEnum::MULTI => ClusterVolumeSpecAccessModeScopeEnum::Multi,
bollard::secret::ClusterVolumeSpecAccessModeScopeEnum::EMPTY => ClusterVolumeSpecAccessModeScopeEnum::Empty,
bollard::secret::ClusterVolumeSpecAccessModeScopeEnum::SINGLE => ClusterVolumeSpecAccessModeScopeEnum::Single,
bollard::secret::ClusterVolumeSpecAccessModeScopeEnum::MULTI => ClusterVolumeSpecAccessModeScopeEnum::Multi,
}).unwrap_or_default(),
sharing: mode.sharing.map(|sharing| match sharing {
bollard::config::ClusterVolumeSpecAccessModeSharingEnum::EMPTY => ClusterVolumeSpecAccessModeSharingEnum::Empty,
bollard::config::ClusterVolumeSpecAccessModeSharingEnum::NONE => ClusterVolumeSpecAccessModeSharingEnum::None,
bollard::config::ClusterVolumeSpecAccessModeSharingEnum::READONLY => ClusterVolumeSpecAccessModeSharingEnum::Readonly,
bollard::config::ClusterVolumeSpecAccessModeSharingEnum::ONEWRITER => ClusterVolumeSpecAccessModeSharingEnum::Onewriter,
bollard::config::ClusterVolumeSpecAccessModeSharingEnum::ALL => ClusterVolumeSpecAccessModeSharingEnum::All,
bollard::secret::ClusterVolumeSpecAccessModeSharingEnum::EMPTY => ClusterVolumeSpecAccessModeSharingEnum::Empty,
bollard::secret::ClusterVolumeSpecAccessModeSharingEnum::NONE => ClusterVolumeSpecAccessModeSharingEnum::None,
bollard::secret::ClusterVolumeSpecAccessModeSharingEnum::READONLY => ClusterVolumeSpecAccessModeSharingEnum::Readonly,
bollard::secret::ClusterVolumeSpecAccessModeSharingEnum::ONEWRITER => ClusterVolumeSpecAccessModeSharingEnum::Onewriter,
bollard::secret::ClusterVolumeSpecAccessModeSharingEnum::ALL => ClusterVolumeSpecAccessModeSharingEnum::All,
}).unwrap_or_default(),
secrets: mode.secrets.unwrap_or_default().into_iter().map(|secret| ClusterVolumeSpecAccessModeSecrets {
key: secret.key,
@@ -116,10 +116,10 @@ impl DockerClient {
limit_bytes: range.limit_bytes,
}),
availability: mode.availability.map(|availability| match availability {
bollard::config::ClusterVolumeSpecAccessModeAvailabilityEnum::EMPTY => ClusterVolumeSpecAccessModeAvailabilityEnum::Empty,
bollard::config::ClusterVolumeSpecAccessModeAvailabilityEnum::ACTIVE => ClusterVolumeSpecAccessModeAvailabilityEnum::Active,
bollard::config::ClusterVolumeSpecAccessModeAvailabilityEnum::PAUSE => ClusterVolumeSpecAccessModeAvailabilityEnum::Pause,
bollard::config::ClusterVolumeSpecAccessModeAvailabilityEnum::DRAIN => ClusterVolumeSpecAccessModeAvailabilityEnum::Drain,
bollard::secret::ClusterVolumeSpecAccessModeAvailabilityEnum::EMPTY => ClusterVolumeSpecAccessModeAvailabilityEnum::Empty,
bollard::secret::ClusterVolumeSpecAccessModeAvailabilityEnum::ACTIVE => ClusterVolumeSpecAccessModeAvailabilityEnum::Active,
bollard::secret::ClusterVolumeSpecAccessModeAvailabilityEnum::PAUSE => ClusterVolumeSpecAccessModeAvailabilityEnum::Pause,
bollard::secret::ClusterVolumeSpecAccessModeAvailabilityEnum::DRAIN => ClusterVolumeSpecAccessModeAvailabilityEnum::Drain,
}).unwrap_or_default(),
}
}),
@@ -137,11 +137,11 @@ impl DockerClient {
.map(|status| ClusterVolumePublishStatus {
node_id: status.node_id,
state: status.state.map(|state| match state {
bollard::config::ClusterVolumePublishStatusStateEnum::EMPTY => ClusterVolumePublishStatusStateEnum::Empty,
bollard::config::ClusterVolumePublishStatusStateEnum::PENDING_PUBLISH => ClusterVolumePublishStatusStateEnum::PendingPublish,
bollard::config::ClusterVolumePublishStatusStateEnum::PUBLISHED => ClusterVolumePublishStatusStateEnum::Published,
bollard::config::ClusterVolumePublishStatusStateEnum::PENDING_NODE_UNPUBLISH => ClusterVolumePublishStatusStateEnum::PendingNodeUnpublish,
bollard::config::ClusterVolumePublishStatusStateEnum::PENDING_CONTROLLER_UNPUBLISH => ClusterVolumePublishStatusStateEnum::PendingControllerUnpublish,
bollard::secret::ClusterVolumePublishStatusStateEnum::EMPTY => ClusterVolumePublishStatusStateEnum::Empty,
bollard::secret::ClusterVolumePublishStatusStateEnum::PENDING_PUBLISH => ClusterVolumePublishStatusStateEnum::PendingPublish,
bollard::secret::ClusterVolumePublishStatusStateEnum::PUBLISHED => ClusterVolumePublishStatusStateEnum::Published,
bollard::secret::ClusterVolumePublishStatusStateEnum::PENDING_NODE_UNPUBLISH => ClusterVolumePublishStatusStateEnum::PendingNodeUnpublish,
bollard::secret::ClusterVolumePublishStatusStateEnum::PENDING_CONTROLLER_UNPUBLISH => ClusterVolumePublishStatusStateEnum::PendingControllerUnpublish,
}).unwrap_or_default(),
publish_context: status.publish_context.unwrap_or_default(),
})
+9 -6
View File
@@ -17,17 +17,20 @@
//! from the Komodo UI Settings page.
//!
//! To call the api, construct JSON bodies following
//! the schemas in [read], [mod@write], [execute], and so on.
//! the schemas given in [read], [mod@write], [execute], and so on.
//!
//! For example, this is an example body for [read::GetDeployment]:
//! ```json
//! {
//! "deployment": "my-deployment"
//! "type": "GetDeployment",
//! "params": {
//! "deployment": "66113df3abe32960b87018dd"
//! }
//! }
//! ```
//!
//! The request's parent module (eg. [read], [mod@write]) and name determines the http path which
//! must be used for the requests. For example, requests under [read] are made using http path `/read/{REQUEST_NAME}`.
//! The request's parent module (eg. [read], [mod@write]) determines the http path which
//! must be used for the requests. For example, requests under [read] are made using http path `/read`.
//!
//! ## Curl Example
//!
@@ -37,8 +40,8 @@
//! curl --header "Content-Type: application/json" \
//! --header "X-Api-Key: your_api_key" \
//! --header "X-Api-Secret: your_api_secret" \
//! --data '{ "id": "my-build", "config": { "version": "2.0.0" } }' \
//! https://komodo.example.com/write/UpdateBuild
//! --data '{ "type": "UpdateBuild", "params": { "id": "67076689ed600cfdd52ac637", "config": { "version": "1.15.9" } } }' \
//! https://komodo.example.com/write
//! ```
//!
//! ## Modules
+1 -7
View File
@@ -2,7 +2,7 @@ use mogh_resolver::Resolve;
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
use crate::entities::{ResourceTarget, toml::ResourcesToml};
use crate::entities::ResourceTarget;
use super::KomodoReadRequest;
@@ -54,9 +54,6 @@ pub struct ExportAllResourcesToToml {
/// Default: false
#[serde(default)]
pub include_user_groups: bool,
/// Pass an existing [ResourcesToml] to preserve
/// the meta configuration.
pub existing: Option<ResourcesToml>,
}
fn default_include_resources() -> bool {
@@ -98,9 +95,6 @@ pub struct ExportResourcesToToml {
/// Whether to include variables
#[serde(default)]
pub include_variables: bool,
/// Pass an existing [ResourcesToml] to preserve
/// the meta configuration.
pub existing: Option<ResourcesToml>,
}
#[typeshare]
+2 -35
View File
@@ -1,7 +1,5 @@
use clap::ValueEnum;
use mogh_resolver::Resolve;
use serde::{Deserialize, Serialize};
use strum::Display;
use typeshare::typeshare;
use crate::entities::{api_key::ApiKey, user::User};
@@ -109,7 +107,7 @@ pub type FindUserResponse = User;
description = "**Admin only.** Gets list of Komodo users.",
request_body(content = ListUsers),
responses(
(status = 200, description = "The list of users", body = Vec<User>),
(status = 200, description = "The list of users", body = ListUsersResponse),
),
)]
pub fn list_users() {}
@@ -123,42 +121,11 @@ pub fn list_users() {}
#[empty_traits(KomodoReadRequest)]
#[response(ListUsersResponse)]
#[error(mogh_error::Error)]
pub struct ListUsers {
/// Service user query options:
/// - Include (default)
/// - Exclude
/// - Only
#[serde(default)]
pub service_users: ServiceUserQueryBehavior,
}
pub struct ListUsers {}
#[typeshare]
pub type ListUsersResponse = Vec<User>;
#[typeshare]
#[derive(
Debug,
Clone,
Copy,
Default,
Serialize,
Deserialize,
ValueEnum,
Display,
)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
// Only strum serializes lowercase for clap compat.
#[strum(serialize_all = "lowercase")]
pub enum ServiceUserQueryBehavior {
/// Include service users in results. Default.
#[default]
Include,
/// Exclude service users from results.
Exclude,
/// Only include service users in results.
Only,
}
//
#[cfg(feature = "utoipa")]
@@ -51,7 +51,7 @@ pub struct CreateOnboardingKey {
/// 2. Remove Server 'address' configuration, allowing Periphery -> Core connection.
/// 3. Update existing Server's public keys.
#[serde(default)]
pub privileged: bool,
pub fix_existing_servers: bool,
/// Optional. New Servers copy this Server's config.
#[serde(default)]
pub copy_server: String,
@@ -109,7 +109,7 @@ pub struct UpdateOnboardingKey {
/// 1. Enable a disabled Server
/// 2. Remove Server 'address' configuration, allowing Periphery -> Core connection.
/// 3. Update existing Server's public keys.
pub privileged: Option<bool>,
pub fix_existing_servers: Option<bool>,
/// Update the copy server
pub copy_server: Option<String>,
/// Update whether to create Builder
@@ -122,7 +122,7 @@ impl UpdateOnboardingKey {
&& self.name.is_none()
&& self.expires.is_none()
&& self.tags.is_none()
&& self.privileged.is_none()
&& self.fix_existing_servers.is_none()
&& self.copy_server.is_none()
&& self.create_builder.is_none()
}
+5 -7
View File
@@ -6,8 +6,7 @@ use crate::entities::{
NoData,
server::ServerQuery,
terminal::{
ContainerTerminalMode, Terminal, TerminalRecreateMode,
TerminalTarget,
ContainerTerminalMode, TerminalRecreateMode, TerminalTarget,
},
};
@@ -22,24 +21,23 @@ use super::KomodoWriteRequest;
description = "Create a Terminal.",
request_body(content = CreateTerminal),
responses(
(status = 200, description = "The created terminal", body = Terminal),
(status = 200, description = "No data", body = NoData),
),
)]
pub fn create_terminal() {}
/// Create a Terminal.
/// Requires minimum Read + Terminal permission on the target Resource.
/// Response: [Terminal]
/// Response: [NoData]
#[typeshare]
#[derive(Debug, Clone, Serialize, Deserialize, Resolve)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[empty_traits(KomodoWriteRequest)]
#[response(Terminal)]
#[response(NoData)]
#[error(mogh_error::Error)]
pub struct CreateTerminal {
/// A name for the Terminal session.
/// If not specified, a default will be given.
pub name: Option<String>,
pub name: String,
/// The target to create terminal for
pub target: TerminalTarget,
/// The shell command (eg `bash`) to init the shell.
@@ -1,59 +0,0 @@
#[derive(Debug, Clone, clap::Subcommand)]
pub enum CreateCommand {
/// Create a new api key. (alias: `ak`)
#[clap(alias = "ak")]
ApiKey(CreateApiKey),
/// Create a new onboarding key. (alias: `ok`)
#[clap(alias = "ok")]
OnboardingKey(CreateOnboardingKey),
}
/// Create a new API key.
#[derive(Debug, Clone, clap::Parser)]
pub struct CreateApiKey {
/// Pass optional name for the api key
pub name: Option<String>,
/// The user username to create the API key for.
/// If `--use-api`, this is optional, and will create an api key for a service user.
/// If NOT `--use-api` (default), this field is REQUIRED.
#[arg(long = "for", short = 'f')]
pub for_user: Option<String>,
/// Pass api key expiry in number of days. Default: Unlimited.
#[arg(long, short = 'e')]
pub expires: Option<i64>,
/// Use the Komodo API rather than direct database connection.
/// This requires existing km credentials.
#[arg(long, short = 'a', default_value_t = false)]
pub use_api: bool,
}
/// Create a new onboarding key.
#[derive(Debug, Clone, clap::Parser)]
pub struct CreateOnboardingKey {
/// Pass optional name for the onboarding key
pub name: Option<String>,
/// Pass onboarding key expiry in number of days. Default: Unlimited.
#[arg(long, short = 'e')]
pub expires: Option<i64>,
/// Pass an existing private key, otherwise one will be generated. (alias: `pk`)
#[arg(long, alias = "pk", short = 'k')]
pub private_key: Option<String>,
/// Add creation tags to onboarding key.
/// Can be specified multiple times. (alias `t`)
#[arg(name = "tag", long, short = 't')]
pub tags: Vec<String>,
/// Make the onboarding key privileged.
#[arg(long, short = 'p', default_value_t = false)]
pub privileged: bool,
/// Optional. Onboarded Servers copy this Server's config. (aliases: `copy`, `server`)
#[arg(long, alias = "copy", alias = "server", short = 's')]
pub copy_server: Option<String>,
/// Optional. Whether to also create a Builder for the Server. (alias: `builder`)
#[arg(
long,
alias = "builder",
short = 'b',
default_value_t = false
)]
pub create_builder: bool,
}
@@ -5,7 +5,6 @@ use std::path::PathBuf;
use crate::api::execute::Execution;
pub mod container;
pub mod create;
pub mod database;
pub mod list;
pub mod terminal;
@@ -53,10 +52,6 @@ pub enum Command {
unsanitized: bool,
},
/// Print information about the connected Komodo Core. (alias: `core`)
#[clap(alias = "core")]
CoreInfo,
/// List Komodo resources (aliases: `ls`, `resources`)
#[clap(alias = "ls", alias = "resources")]
List(list::List),
@@ -71,13 +66,6 @@ pub enum Command {
)]
Execute(Execute),
/// Create resources. (aliases: `new`, `cr`)
#[clap(alias = "new", alias = "cr")]
Create {
#[command(subcommand)]
command: create::CreateCommand,
},
/// Update resource configuration. (alias: `set`)
#[clap(alias = "set")]
Update {
+1 -1
View File
@@ -37,7 +37,7 @@ pub struct SwarmConfigListItem {
}
/// Swarm config details.
///
///
/// This would be just "SwarmConfig", but that would
/// conflict with the Swarm (Komodo resource) Config type,
/// which is also SwarmConfig.
+1 -1
View File
@@ -43,7 +43,7 @@ pub struct SwarmStackListItem {
/// All entities related to docker stack available over CLI.
/// Returned by:
/// ```shell
/// ```
/// docker stack services --format json <STACK>
/// docker stack ps --format json <STACK>
/// ```
@@ -53,7 +53,7 @@ pub struct OnboardingKey {
/// 2. Remove Server 'address' configuration, allowing Periphery -> Core connection.
/// 3. Update existing Server's public keys.
#[serde(default)]
pub privileged: bool,
pub fix_existing_servers: bool,
/// Optional. If specified, copy this Server config when initializing
/// the Server.

Some files were not shown because too many files have changed in this diff Show More