propellor spin
This commit is contained in:
parent
36469bc07d
commit
9172b79612
|
@ -70,15 +70,10 @@ spin host = do
|
|||
url <- getUrl
|
||||
void $ gitCommit [Param "--allow-empty", Param "-a", Param "-m", Param "propellor spin"]
|
||||
void $ boolSystem "git" [Param "push"]
|
||||
privdata <- gpgDecrypt (privDataFile host)
|
||||
withBothHandles createProcessSuccess (proc "ssh" [user, bootstrapcmd url]) $ \(toh, fromh) -> do
|
||||
status <- getstatus fromh `catchIO` error "protocol error"
|
||||
case status of
|
||||
NeedKeyRing -> do
|
||||
d <- w82s . BL.unpack . B64.encode
|
||||
<$> BL.readFile keyring
|
||||
senddata toh keyring keyringMarker d
|
||||
HaveKeyRing -> noop
|
||||
go url =<< gpgDecrypt (privDataFile host)
|
||||
where
|
||||
go url privdata = withBothHandles createProcessSuccess (proc "ssh" [user, bootstrapcmd]) $ \(toh, fromh) -> do
|
||||
let finish = do
|
||||
senddata toh (privDataFile host) privDataMarker privdata
|
||||
hClose toh
|
||||
|
||||
|
@ -86,22 +81,36 @@ spin host = do
|
|||
void $ tryIO $ forever $
|
||||
showremote =<< hGetLine fromh
|
||||
hClose fromh
|
||||
status <- getstatus fromh `catchIO` error "protocol error"
|
||||
case status of
|
||||
HaveKeyRing -> finish
|
||||
NeedKeyRing -> do
|
||||
d <- w82s . BL.unpack . B64.encode
|
||||
<$> BL.readFile keyring
|
||||
senddata toh keyring keyringMarker d
|
||||
finish
|
||||
NeedGitClone -> do
|
||||
hClose toh
|
||||
hClose fromh
|
||||
sendGitClone host url
|
||||
go url privdata
|
||||
|
||||
where
|
||||
user = "root@"++host
|
||||
bootstrapcmd url = shellWrap $ intercalate " && "
|
||||
|
||||
bootstrapcmd = shellWrap $ intercalate " && "
|
||||
[ intercalate " ; "
|
||||
[ "if [ ! -d " ++ localdir ++ " ]"
|
||||
, "then " ++ intercalate " && "
|
||||
[ "apt-get -y install git"
|
||||
, "git clone " ++ url ++ " " ++ localdir
|
||||
, "echo " ++ toMarked statusMarker (show NeedGitClone)
|
||||
]
|
||||
, "fi"
|
||||
]
|
||||
, "cd " ++ localdir
|
||||
, "make pull build"
|
||||
, "make build"
|
||||
, "./propellor --boot " ++ host
|
||||
]
|
||||
|
||||
getstatus :: Handle -> IO BootStrapStatus
|
||||
getstatus h = do
|
||||
l <- hGetLine h
|
||||
|
@ -110,6 +119,7 @@ spin host = do
|
|||
showremote l
|
||||
getstatus h
|
||||
Just status -> return status
|
||||
|
||||
showremote s = putStrLn s
|
||||
senddata toh f marker s = do
|
||||
putStr $ "Sending " ++ f ++ " (" ++ show (length s) ++ " bytes) to " ++ host ++ "..."
|
||||
|
@ -118,7 +128,27 @@ spin host = do
|
|||
hFlush toh
|
||||
putStrLn "done"
|
||||
|
||||
data BootStrapStatus = HaveKeyRing | NeedKeyRing
|
||||
sendGitClone :: HostName -> String -> IO ()
|
||||
sendGitClone host url = do
|
||||
putStrLn $ "Pushing git repository to " ++ host
|
||||
withTmpFile "gitbundle" $ \tmp _ -> do
|
||||
-- TODO: ssh connection caching, or better push method
|
||||
-- with less connections.
|
||||
void $ boolSystem "git" [Param "bundle", Param "create", File tmp, Param "HEAD"]
|
||||
void $ boolSystem "scp" [File tmp, Param ("root@"++host++":"++remotebundle)]
|
||||
void $ boolSystem "ssh" [Param ("root@"++host), Param unpackcmd]
|
||||
where
|
||||
remotebundle = "/usr/local/propellor.git"
|
||||
unpackcmd = shellWrap $ intercalate " && "
|
||||
[ "git clone " ++ remotebundle ++ " " ++ localdir
|
||||
, "cd " ++ localdir
|
||||
, "git checkout -b master"
|
||||
, "git remote rm origin"
|
||||
, "git remote add origin " ++ url
|
||||
, "rm -f " ++ remotebundle
|
||||
]
|
||||
|
||||
data BootStrapStatus = HaveKeyRing | NeedKeyRing | NeedGitClone
|
||||
deriving (Read, Show, Eq)
|
||||
|
||||
type Marker = String
|
||||
|
|
27
README
27
README
|
@ -6,10 +6,13 @@ properties, taking action as necessary when a property is not yet met.
|
|||
|
||||
The design is intentionally very minimal.
|
||||
|
||||
Propellor lives in a git repository, and so to set it up it's cloned
|
||||
to a system, and "make" can be used to pull down any new changes,
|
||||
and compile and run propellor. This can be done by a cron job, or
|
||||
a local propellor on your laptop can ssh in and run it.
|
||||
Propellor lives in a git repository. You'll typically want to have
|
||||
the repository checked out on a laptop, in order to make changes and push
|
||||
them out to hosts. Each host will also have a clone of the repository,
|
||||
and in that clone "make" can be used to build and run propellor.
|
||||
This can be done by a cron job (which propellor can set up),
|
||||
or a remote host can be triggered to update by running propellor
|
||||
on your laptop: propellor --spin $host
|
||||
|
||||
Properties are defined using Haskell. Edit config.hs to get started.
|
||||
|
||||
|
@ -26,9 +29,15 @@ and so it's easy to factor out things like classes of hosts as desired.
|
|||
## bootstrapping and private data
|
||||
|
||||
To bootstrap propellor on a new host, use: propellor --spin $host
|
||||
This looks up the git repository's remote.origin.url (or remote.deploy.url
|
||||
if available) and logs into the host, clones the url (if not already
|
||||
done), and sets up and runs propellor in /usr/local/propellor
|
||||
|
||||
That clones the local git repository to the remote host (securely over ssh
|
||||
and without needing any central server!), if it doesn't already have
|
||||
a clone.
|
||||
|
||||
The repository on the remote host will have its origin set to the local git
|
||||
repository's remote.origin.url (or remote.deploy.url if available).
|
||||
This way, when propellor is run on the remote host, it can contact
|
||||
whatever central git repository you're using.
|
||||
|
||||
Private data such as passwords, ssh private keys, etc should not be checked
|
||||
into a propellor git repository in the clear, unless you want to restrict
|
||||
|
@ -43,8 +52,8 @@ for available fields.
|
|||
|
||||
## using git://... securely
|
||||
|
||||
It's often easiest to deploy propellor to a host by cloning a git:// or
|
||||
http:// repository rather than by cloning over ssh://. To avoid a MITM
|
||||
It's often easiest for a remote host to use a git:// or http://
|
||||
url to its origin repository, rather than ssh://. So, to avoid a MITM
|
||||
attack, propellor checks that the top commit in the git repository is gpg
|
||||
signed by a trusted gpg key, and refuses to deploy it otherwise.
|
||||
|
||||
|
|
Loading…
Reference in New Issue