blob: b6d38d0693bdf2b77140882a6792682dc62c98d7 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
-- | This is a simple line-based protocol used for communication between
-- a local and remote propellor. It's sent over a ssh channel, and lines of
-- the protocol can be interspersed with other, non-protocol lines
-- that should be passed through to be displayed.
--
-- Avoid making backwards-incompatible changes to this protocol,
-- since propellor needs to use this protocol to update itself to new
-- versions speaking newer versions of the protocol.
module Propellor.Protocol where
import Data.List
import Propellor
data Stage = NeedGitClone | NeedRepoUrl | NeedPrivData | NeedGitPush | NeedPrecompiled
deriving (Read, Show, Eq)
type Marker = String
type Marked = String
statusMarker :: Marker
statusMarker = "STATUS"
privDataMarker :: String
privDataMarker = "PRIVDATA "
repoUrlMarker :: String
repoUrlMarker = "REPOURL "
gitPushMarker :: String
gitPushMarker = "GITPUSH"
toMarked :: Marker -> String -> String
toMarked = (++)
fromMarked :: Marker -> Marked -> Maybe String
fromMarked marker s
| marker `isPrefixOf` s = Just $ drop (length marker) s
| otherwise = Nothing
sendMarked :: Handle -> Marker -> String -> IO ()
sendMarked h marker s = do
debug ["sent marked", marker]
sendMarked' h marker s
sendMarked' :: Handle -> Marker -> String -> IO ()
sendMarked' h marker s = do
-- Prefix string with newline because sometimes a
-- incomplete line has been output, and the marker needs to
-- come at the start of a line.
hPutStrLn h ("\n" ++ toMarked marker s)
hFlush h
getMarked :: Handle -> Marker -> IO (Maybe String)
getMarked h marker = go =<< catchMaybeIO (hGetLine h)
where
go Nothing = return Nothing
go (Just l) = case fromMarked marker l of
Nothing -> do
unless (null l) $
hPutStrLn stderr l
getMarked h marker
Just v -> do
debug ["received marked", marker]
return (Just v)
req :: Stage -> Marker -> (String -> IO ()) -> IO ()
req stage marker a = do
debug ["requested marked", marker]
sendMarked' stdout statusMarker (show stage)
maybe noop a =<< getMarked stdin marker
|