2024-06-04 18:50:38 +00:00
|
|
|
{- git-annex command
|
|
|
|
-
|
|
|
|
- Copyright 2024 Joey Hess <id@joeyh.name>
|
|
|
|
-
|
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Command.UpdateProxy where
|
|
|
|
|
|
|
|
import Command
|
2024-06-14 19:03:20 +00:00
|
|
|
import qualified Annex
|
2024-06-04 18:50:38 +00:00
|
|
|
import Logs.Proxy
|
2024-06-26 15:24:55 +00:00
|
|
|
import Logs.Cluster
|
2024-06-04 18:50:38 +00:00
|
|
|
import Annex.UUID
|
|
|
|
import qualified Remote as R
|
|
|
|
import qualified Types.Remote as R
|
2024-08-07 16:27:24 +00:00
|
|
|
import Annex.SpecialRemote.Config
|
2024-06-04 18:50:38 +00:00
|
|
|
import Utility.SafeOutput
|
|
|
|
|
|
|
|
import qualified Data.Map as M
|
|
|
|
import qualified Data.Set as S
|
|
|
|
|
|
|
|
cmd :: Command
|
|
|
|
cmd = noMessages $ command "updateproxy" SectionSetup
|
|
|
|
"update records with proxy configuration"
|
|
|
|
paramNothing (withParams seek)
|
|
|
|
|
|
|
|
seek :: CmdParams -> CommandSeek
|
|
|
|
seek = withNothing (commandAction start)
|
|
|
|
|
|
|
|
start :: CommandStart
|
|
|
|
start = startingCustomOutput (ActionItemOther Nothing) $ do
|
|
|
|
rs <- R.remoteList
|
2024-08-07 16:27:24 +00:00
|
|
|
remoteproxies <- S.fromList . map mkproxy
|
|
|
|
<$> filterM isproxy rs
|
2024-06-26 17:21:51 +00:00
|
|
|
clusterproxies <- getClusterProxies remoteproxies
|
2024-06-26 15:24:55 +00:00
|
|
|
let proxies = S.union remoteproxies clusterproxies
|
2024-06-04 18:50:38 +00:00
|
|
|
u <- getUUID
|
|
|
|
oldproxies <- fromMaybe mempty . M.lookup u <$> getProxies
|
|
|
|
if oldproxies == proxies
|
|
|
|
then liftIO $ putStrLn "No proxy changes to record."
|
|
|
|
else do
|
|
|
|
describechanges oldproxies proxies
|
|
|
|
recordProxies proxies
|
|
|
|
next $ return True
|
|
|
|
where
|
|
|
|
describechanges oldproxies proxies =
|
|
|
|
forM_ (S.toList $ S.union oldproxies proxies) $ \p ->
|
|
|
|
case (S.member p oldproxies, S.member p proxies) of
|
|
|
|
(False, True) -> liftIO $
|
|
|
|
putStrLn $ safeOutput $
|
|
|
|
"Started proxying for " ++ proxyRemoteName p
|
|
|
|
(True, False) -> liftIO $
|
|
|
|
putStrLn $ safeOutput $
|
|
|
|
"Stopped proxying for " ++ proxyRemoteName p
|
|
|
|
_ -> noop
|
2024-06-14 18:21:50 +00:00
|
|
|
|
2024-06-14 19:03:20 +00:00
|
|
|
mkproxy r = Proxy (R.uuid r) (R.name r)
|
2024-08-07 16:27:24 +00:00
|
|
|
|
|
|
|
isproxy r
|
|
|
|
| remoteAnnexProxy (R.gitconfig r) || not (null (remoteAnnexClusterNode (R.gitconfig r))) =
|
|
|
|
checkCanProxy r "Cannot proxy to this special remote."
|
|
|
|
| otherwise = pure False
|
|
|
|
|
|
|
|
checkCanProxy :: Remote -> String -> Annex Bool
|
|
|
|
checkCanProxy r cannotmessage =
|
|
|
|
ifM (R.isExportSupported r)
|
|
|
|
( if annexObjects (R.config r)
|
|
|
|
then pure True
|
|
|
|
else do
|
|
|
|
warnannexobjects
|
|
|
|
pure False
|
|
|
|
, pure True
|
|
|
|
)
|
|
|
|
where
|
|
|
|
warnannexobjects = warning $ UnquotedString $ unwords
|
|
|
|
[ R.name r
|
|
|
|
, "is configured with exporttree=yes, but without"
|
|
|
|
, "annexobjects=yes."
|
|
|
|
, cannotmessage
|
|
|
|
, "Suggest you run: git-annex enableremote"
|
|
|
|
, R.name r
|
|
|
|
, "annexobjects=yes"
|
|
|
|
]
|
2024-06-14 19:03:20 +00:00
|
|
|
|
2024-06-26 15:24:55 +00:00
|
|
|
-- Automatically proxy nodes of any cluster this repository is configured
|
|
|
|
-- to serve as a gateway for. Also proxy other cluster nodes that are
|
|
|
|
-- themselves proxied via other remotes.
|
2024-06-26 17:21:51 +00:00
|
|
|
getClusterProxies :: S.Set Proxy -> Annex (S.Set Proxy)
|
|
|
|
getClusterProxies remoteproxies = do
|
|
|
|
myclusters <- (map mkclusterproxy . M.toList . annexClusters)
|
2024-06-26 15:24:55 +00:00
|
|
|
<$> Annex.getGitConfig
|
|
|
|
remoteproxiednodes <- findRemoteProxiedClusterNodes
|
2024-06-26 17:21:51 +00:00
|
|
|
let myproxieduuids = S.map proxyRemoteUUID remoteproxies
|
|
|
|
<> S.fromList (map proxyRemoteUUID myclusters)
|
2024-06-26 15:24:55 +00:00
|
|
|
-- filter out nodes we proxy for from the remote proxied nodes
|
|
|
|
-- to avoid cycles
|
|
|
|
let remoteproxiednodes' = filter
|
2024-06-26 17:21:51 +00:00
|
|
|
(\n -> proxyRemoteUUID n `S.notMember` myproxieduuids)
|
2024-06-26 15:24:55 +00:00
|
|
|
remoteproxiednodes
|
2024-06-26 17:21:51 +00:00
|
|
|
return (S.fromList (myclusters ++ remoteproxiednodes'))
|
2024-06-26 15:24:55 +00:00
|
|
|
where
|
2024-06-14 19:03:20 +00:00
|
|
|
mkclusterproxy (remotename, cu) =
|
|
|
|
Proxy (fromClusterUUID cu) remotename
|
2024-06-26 15:24:55 +00:00
|
|
|
|
|
|
|
findRemoteProxiedClusterNodes :: Annex [Proxy]
|
|
|
|
findRemoteProxiedClusterNodes = do
|
|
|
|
myclusters <- (S.fromList . M.elems . annexClusters)
|
|
|
|
<$> Annex.getGitConfig
|
|
|
|
clusternodes <- clusterNodeUUIDs <$> getClusters
|
|
|
|
let isproxiedclusternode r
|
2024-06-26 16:56:16 +00:00
|
|
|
| isJust (remoteAnnexProxiedBy (R.gitconfig r)) =
|
2024-06-26 15:24:55 +00:00
|
|
|
case M.lookup (ClusterNodeUUID (R.uuid r)) clusternodes of
|
|
|
|
Nothing -> False
|
|
|
|
Just s -> not $ S.null $
|
|
|
|
S.intersection s myclusters
|
|
|
|
| otherwise = False
|
|
|
|
(map asproxy . filter isproxiedclusternode)
|
|
|
|
<$> R.remoteList
|
|
|
|
where
|
|
|
|
asproxy r = Proxy (R.uuid r) (R.name r)
|