Skip to content

Commit

Permalink
Adds MountSettings
Browse files Browse the repository at this point in the history
With MountSettings a user is able to specify a list of known
usernames/hosts configurations with ports and private ssh keys.

The settings are stored as a [MountSettings] value in a
~/.vadosettings file.

If the file is absent or vado has failed to read it then the settings
are defaulted to standart vagrant ones.
  • Loading branch information
Daniil Frumin committed Jun 24, 2013
1 parent ffad8b1 commit 5c4adb5
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 32 deletions.
33 changes: 28 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,34 @@ and makes vim work nicely).
vagrant
=======

This is not tied to vagrant, but can be used with it and is
faster than 'vagrant ssh'. If the user detected in 'mount'
is 'vagrant' and the host is '127.0.0.1' then it will default to
port 2222 and use '~/.vagrant.d/insecure_private_key' for
authentication.
This is not tied to vagrant, but can be used with it and is faster
than 'vagrant ssh'. If the user and host detected in 'mount' are
specified in the '~/.vadosettings' file, then the specified key and
port will be used. If the file is not present or incorrectly formatted
then the default settings for vagrant will be used:
- User: vagrant
- Host: 127.0.0.1
- Port: 2222
- Key file: ~/.vagrant.d/insecure_private_key

### Example '.vadosettings' file

```haskell
[
MountSettings {
sshfsUser = "vagrant"
, sshfsHost = "localhost"
, sshfsPort = 2222
, idFile = "/Users/dan/.vagrant.d/insecure_private_key"
},
MountSettings {
sshfsUser = "vagrant"
, sshfsHost = "server.local"
, sshfsPort = 2233
, idFile = "/Users/dan/keys/local_server_key"
}
]
```


install
Expand Down
13 changes: 7 additions & 6 deletions src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import System.Environment (getArgs)
import Data.List (isPrefixOf)
import System.Exit (exitWith, ExitCode(..))
import System.Process (rawSystem)
import System.Process.Vado (getMountPoint, vado)
import System.Process.Vado (getMountPoint, vado, readSettings, defMountSettings)

-- | Main function for vado
main = do
Expand All @@ -33,21 +33,22 @@ main = do
(sshopts,cmd:rest) -> do
currentDir <- getCurrentDirectory
mbMountPoint <- getMountPoint currentDir
ms <- readSettings
case mbMountPoint of
Left mp -> vado mp currentDir sshopts cmd rest
Left mp -> vado mp ms currentDir sshopts cmd rest
>>= rawSystem "ssh" >>= exitWith
Right err -> hPutStrLn stderr err >> (exitWith $ ExitFailure 1)
_ -> do
defSettings <- defMountSettings
hPutStrLn stderr $
"Usage vado [ssh options] command [args]\n\n"

++ "The command will be run in the directoy on the remote\n"
++ "machine that corrisponds to the current directory locally.\n\n"

++ "The ssh options must start with a dash '-'.\n"
++ "If the mount point is '[email protected]'\n"
++ "then the most common vagrant connection options\n"
++ " -p2222 and -i~/.vagrant.d/insecure_private_key\n"
++ "are included automatically."
++ "You can specify port and key location settings\n"
++ "in the ~/.vadosettings file.\nExample contents:\n"
++ show [defSettings]
exitWith $ ExitFailure 1

81 changes: 60 additions & 21 deletions src/System/Process/Vado.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
-----------------------------------------------------------------------------
--
-- Module : System.Process.Vado
Expand All @@ -20,18 +21,22 @@ module System.Process.Vado (
MountPoint(..)
, parseMountPoint
, getMountPoint
, MountSettings(..)
, readSettings
, defMountSettings
, vado
) where

import Control.Applicative ((<$>))
import Data.Text (pack, unpack, Text)
import Data.List (isPrefixOf)
import Data.List (isPrefixOf, find)
import Data.Monoid (mconcat)
import Data.Attoparsec.Text (parse, string, Parser, IResult(..))
import qualified Data.Attoparsec.Text as P (takeWhile1)
import Data.Text.IO (hPutStrLn)
import System.FilePath (addTrailingPathSeparator, makeRelative, (</>))
import Data.Maybe (catMaybes)
import Data.Maybe (catMaybes, fromMaybe)
import Text.Read (readMaybe)
import System.Exit (ExitCode)
import System.Process (readProcess)
import System.Directory (getHomeDirectory, getCurrentDirectory)
Expand All @@ -48,6 +53,26 @@ instance Show MountPoint where
show MountPoint {..} = unpack (mconcat [remoteUser, "@", remoteHost, ":"])
++ remoteDir ++ " on " ++ localDir ++ " "

-- | Mount point settings
data MountSettings = MountSettings {
sshfsUser :: Text
, sshfsHost :: Text
, sshfsPort :: Int
, idFile :: FilePath
} deriving (Show, Read)

-- | Default mount settings for vagrant
defMountSettings :: IO MountSettings
defMountSettings = do
homeDir <- getHomeDirectory
return MountSettings {
sshfsUser = "vagrant"
, sshfsHost = "127.0.0.1"
, sshfsPort = 2222
, idFile = homeDir </> ".vagrant.d/insecure_private_key"
}


-- | Parser for a line of output from the 'mount' command
mountPointParser :: Parser MountPoint
mountPointParser = do
Expand Down Expand Up @@ -89,33 +114,47 @@ getMountPoint dir = do
_ -> "The following remote mount points were not suitable\n"
++ concatMap (\mp -> " " ++ show mp ++ "\n") mountPoints


-- | Read a list of predefined mount points from the
-- ~/.vadosettings files
readSettings :: IO [MountSettings]
readSettings = do
homeDir <- getHomeDirectory
settings :: Maybe [MountSettings] <- readMaybe <$>
readFile (homeDir </> ".vadosettings")
defaultSettings <- defMountSettings
return $ fromMaybe [defaultSettings] settings

-- | Get a list of arguments to pass to ssh to run command on a remote machine
-- in the directory that is mounted locally
vado :: MountPoint -- ^ Mount point found using 'getMountPoint'
-> FilePath -- ^ Local directory you want the command to run in.
-- Normally this will be the same directory
-- you passed to 'getMountPoint'.
-- The vado will run the command in the remote
-- directory that maps to this one.
-> [String] -- ^ Options to pass to ssh. If the mount point is '[email protected]'
-- then the most common vagrant connection options
-- ('-p2222' and '-i~/.vagrant.d/insecure_private_key')
-- are included automatically
-> FilePath -- ^ Command to run
-> [String] -- ^ Arguments to pass to the command
-> IO [String] -- ^ Full list of arguments that should be passed to ssh
vado MountPoint{..} cwd sshopts cmd args = do
vado :: MountPoint -- ^ Mount point found using 'getMountPoint'
-> [MountSettings] -- ^ SSH settings from the '.vadosettings' files
-> FilePath -- ^ Local directory you want the command to run in.
-- Normally this will be the same directory
-- you passed to 'getMountPoint'.
-- The vado will run the command in the remote
-- directory that maps to this one.
-> [String] -- ^ Options to pass to ssh. If the mount point is '[email protected]'
-- then the most common vagrant connection options
-- ('-p2222' and '-i~/.vagrant.d/insecure_private_key')
-- are included automatically
-> FilePath -- ^ Command to run
-> [String] -- ^ Arguments to pass to the command
-> IO [String] -- ^ Full list of arguments that should be passed to ssh
vado MountPoint{..} settings cwd sshopts cmd args = do
homeDir <- getHomeDirectory
-- Work out where the current directory is on the remote machine
let destinationDir = remoteDir </> makeRelative localDir cwd
-- Run ssh with
return $
[unpack $ mconcat [remoteUser, "@", remoteHost]]
++ case (remoteUser, remoteHost) of
("vagrant","127.0.0.1") -> -- Default options for vagrant
["-p2222",
"-i" ++ homeDir </> ".vagrant.d/insecure_private_key"]
_ -> []
++ case find (\MountSettings{..} ->
remoteUser == sshfsUser
&& remoteHost == sshfsHost) settings of
Just MountSettings{..} ->
[ "-p" ++ show sshfsPort
, "-i" ++ idFile ]
Nothing -> []
++ sshopts
++ ["cd", translate destinationDir, "&&", cmd]
++ args
Expand Down

0 comments on commit 5c4adb5

Please sign in to comment.