summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog5
-rw-r--r--doc/usage.mdwn17
-rw-r--r--src/Propellor/CmdLine.hs40
-rw-r--r--src/Propellor/PrivData/Paths.hs3
-rw-r--r--src/Propellor/Server.hs22
-rw-r--r--src/Propellor/Types.hs4
6 files changed, 61 insertions, 30 deletions
diff --git a/debian/changelog b/debian/changelog
index a44d72af..4d264f4d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,8 +3,9 @@ propellor (1.0.1) UNRELEASED; urgency=medium
* propellor --spin can now deploy propellor to hosts that do not have
git, ghc, or apt-get. This is accomplished by uploading a fairly
portable precompiled tarball of propellor.
- * --spin host --via host causes propellor to bounce through an intermediate
- host, which handles any necessary provisioning of the host being spun.
+ * --spin target --via relay causes propellor to bounce through an
+ intermediate relay host, which handles any necessary provisioning
+ of the target host.
-- Joey Hess <joeyh@debian.org> Sat, 22 Nov 2014 00:12:35 -0400
diff --git a/doc/usage.mdwn b/doc/usage.mdwn
index 42797049..7baba507 100644
--- a/doc/usage.mdwn
+++ b/doc/usage.mdwn
@@ -20,11 +20,18 @@ action as needed to satisfy the configured properties of the local host.
# OPTIONS
-* --spin hostname
-
- Causes propellor to automatically install itself on the specified host,
- or if it's already installed there, push any updates. Propellor is then
- run on the host, to satisfy its configured properties.
+* --spin targethost [--via relayhost]
+
+ Causes propellor to automatically install itself on the specified target
+ host, or if it's already installed there, push any updates. Propellor is
+ then run on the target host, to satisfy its configured properties.
+
+ When run with --via, propellor sshes to the relay host and runs
+ `propellor --spin hostname` from there. This can be useful when
+ propellor is installing itself, since most of the data transfer
+ is done between relay host and target host. Note that propellor
+ uses ssh agent forwarding to make this work, and the relay host
+ sees any privdata belonging to the target host.
* --add-key keyid
diff --git a/src/Propellor/CmdLine.hs b/src/Propellor/CmdLine.hs
index ec2ca7ed..c681a08d 100644
--- a/src/Propellor/CmdLine.hs
+++ b/src/Propellor/CmdLine.hs
@@ -24,7 +24,7 @@ usage h = hPutStrLn h $ unlines
[ "Usage:"
, " propellor"
, " propellor hostname"
- , " propellor --spin hostname"
+ , " propellor --spin targethost [--via relayhost]"
, " propellor --add-key keyid"
, " propellor --set field context"
, " propellor --dump field context"
@@ -41,7 +41,8 @@ processCmdLine :: IO CmdLine
processCmdLine = go =<< getArgs
where
go ("--run":h:[]) = return $ Run h
- go ("--spin":h:[]) = return $ Spin h
+ go ("--spin":h:[]) = return $ Spin h Nothing
+ go ("--spin":h:"--via":r:[]) = return $ Spin h (Just r)
go ("--add-key":k:[]) = return $ AddKey k
go ("--set":f:c:[]) = withprivfield f c Set
go ("--dump":f:c:[]) = withprivfield f c Dump
@@ -50,8 +51,8 @@ processCmdLine = go =<< getArgs
go ("--help":_) = do
usage stdout
exitFailure
- go ("--update":h:[]) = return $ Update h
- go ("--boot":h:[]) = return $ Update h -- for back-compat
+ go ("--update":_:[]) = return $ Update Nothing
+ go ("--boot":_:[]) = return $ Update Nothing -- for back-compat
go ("--continue":s:[]) = case readish s of
Just cmdline -> return $ Continue cmdline
Nothing -> errorMessage $ "--continue serialization failure (" ++ s ++ ")"
@@ -89,15 +90,16 @@ defaultMain hostlist = do
go _ (DockerChain hn cid) = Docker.chain hostlist hn cid
go _ (DockerInit hn) = Docker.init hn
go _ (GitPush fin fout) = gitPushHelper fin fout
- go _ (Update _) = forceConsole >> fetchFirst (onlyprocess update)
- go True cmdline@(Spin _) = buildFirst cmdline $ go False cmdline
+ go _ (Update Nothing) = forceConsole >> fetchFirst (onlyprocess (update Nothing))
+ go _ (Update (Just h)) = forceConsole >> fetchFirst (update (Just h))
+ go True cmdline@(Spin _ _) = buildFirst cmdline $ go False cmdline
go True cmdline = updateFirst cmdline $ go False cmdline
- go False (Spin hn) = withhost hn $ spin hn
+ go False (Spin hn r) = withhost hn $ spin hn r
go False cmdline@(SimpleRun hn) = buildFirst cmdline $
go False (Run hn)
go False (Run hn) = ifM ((==) 0 <$> getRealUserID)
( onlyprocess $ withhost hn mainProperties
- , go True (Spin hn)
+ , go True (Spin hn Nothing)
)
withhost :: HostName -> (Host -> IO ()) -> IO ()
@@ -148,8 +150,8 @@ updateFirst' cmdline next = ifM fetchOrigin
, next
)
-spin :: HostName -> Host -> IO ()
-spin hn hst = do
+spin :: HostName -> Maybe HostName -> Host -> IO ()
+spin target relay hst = do
void $ actionMessage "Git commit" $
gitCommit [Param "--allow-empty", Param "-a", Param "-m", Param "propellor spin"]
-- Push to central origin repo first, if possible.
@@ -160,15 +162,18 @@ spin hn hst = do
boolSystem "git" [Param "push"]
cacheparams <- toCommand <$> sshCachingParams hn
+ when (isJust relay) $
+ void $ boolSystem "ssh-add" []
-- Install, or update the remote propellor.
- updateServer hn hst $ withBothHandles createProcessSuccess
+ updateServer target relay hst $ withBothHandles createProcessSuccess
(proc "ssh" $ cacheparams ++ [user, updatecmd])
-- And now we can run it.
unlessM (boolSystem "ssh" (map Param $ cacheparams ++ ["-t", user, runcmd])) $
error $ "remote propellor failed"
where
+ hn = fromMaybe target relay
user = "root@"++hn
mkcmd = shellWrap . intercalate " ; "
@@ -183,10 +188,17 @@ spin hn hst = do
, "else " ++ intercalate " && "
[ "cd " ++ localdir
, "if ! test -x ./propellor; then make deps build; fi"
- , "./propellor --boot " ++ hn
+ , if isNothing relay
+ -- Still using --boot for back-compat...
+ then "./propellor --boot " ++ target
+ else "./propellor --continue " ++
+ shellEscape (show (Update (Just target)))
]
, "fi"
]
- runcmd = mkcmd
- [ "cd " ++ localdir ++ " && ./propellor --continue " ++ shellEscape (show (SimpleRun hn)) ]
+ runcmd = mkcmd [ "cd " ++ localdir ++ " && ./propellor " ++ cmd ]
+ cmd = if isNothing relay
+ then "--continue " ++ shellEscape (show (SimpleRun target))
+ else "--spin " ++ shellEscape target
+
diff --git a/src/Propellor/PrivData/Paths.hs b/src/Propellor/PrivData/Paths.hs
index 1922a31e..9f791b76 100644
--- a/src/Propellor/PrivData/Paths.hs
+++ b/src/Propellor/PrivData/Paths.hs
@@ -10,3 +10,6 @@ privDataFile = privDataDir </> "privdata.gpg"
privDataLocal :: FilePath
privDataLocal = privDataDir </> "local"
+
+privDataRelay :: String -> FilePath
+privDataRelay host = privDataDir </> "relay" </> host
diff --git a/src/Propellor/Server.hs b/src/Propellor/Server.hs
index 19a2c901..e2d6552f 100644
--- a/src/Propellor/Server.hs
+++ b/src/Propellor/Server.hs
@@ -29,13 +29,16 @@ import Utility.SafeCommand
-- Update the privdata, repo url, and git repo over the ssh
-- connection, talking to the user's local propellor instance which is
-- running the updateServer
-update :: IO ()
-update = do
+update :: Maybe HostName -> IO ()
+update forhost = do
whenM hasOrigin $
req NeedRepoUrl repoUrlMarker setRepoUrl
+
makePrivDataDir
+ createDirectoryIfMissing True (takeDirectory privfile)
req NeedPrivData privDataMarker $
- writeFileProtected privDataLocal
+ writeFileProtected privfile
+
whenM hasOrigin $
req NeedGitPush gitPushMarker $ \_ -> do
hin <- dup stdInput
@@ -52,12 +55,17 @@ update = do
, Param $ "./propellor --gitpush " ++ show hin ++ " " ++ show hout
, Param "."
]
+
+ -- When --spin --relay is run, get a privdata file
+ -- to be relayed to the target host.
+ privfile = maybe privDataLocal privDataRelay forhost
-- The connect action should ssh to the remote host and run the provided
-- calback action.
-updateServer :: HostName -> Host -> (((Handle, Handle) -> IO ()) -> IO ()) -> IO ()
-updateServer hn hst connect = connect go
+updateServer :: HostName -> Maybe HostName -> Host -> (((Handle, Handle) -> IO ()) -> IO ()) -> IO ()
+updateServer target relay hst connect = connect go
where
+ hn = fromMaybe target relay
go (toh, fromh) = do
let loop = go (toh, fromh)
v <- (maybe Nothing readish <$> getMarked fromh statusMarker)
@@ -77,12 +85,12 @@ updateServer hn hst connect = connect go
hClose toh
hClose fromh
sendGitClone hn
- updateServer hn hst connect
+ updateServer hn relay hst connect
(Just NeedPrecompiled) -> do
hClose toh
hClose fromh
sendPrecompiled hn
- updateServer hn hst connect
+ updateServer hn relay hst connect
Nothing -> return ()
sendRepoUrl :: Handle -> IO ()
diff --git a/src/Propellor/Types.hs b/src/Propellor/Types.hs
index e7d63547..e4cbf981 100644
--- a/src/Propellor/Types.hs
+++ b/src/Propellor/Types.hs
@@ -142,7 +142,7 @@ instance ActionResult Result where
data CmdLine
= Run HostName
- | Spin HostName
+ | Spin HostName (Maybe HostName)
| SimpleRun HostName
| Set PrivDataField Context
| Dump PrivDataField Context
@@ -150,7 +150,7 @@ data CmdLine
| ListFields
| AddKey String
| Continue CmdLine
- | Update HostName
+ | Update (Maybe HostName)
| DockerInit HostName
| DockerChain HostName String
| ChrootChain HostName FilePath Bool Bool