Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit 601bb43

Browse files
Merge #361
361: allow persisting safemode flag r=disassembler a=cleverca22 Co-authored-by: Michael Bishop <[email protected]>
2 parents a85014d + fcd827e commit 601bb43

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

cardano-launcher/app/Main.hs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import Cardano.X509.Configuration (TLSConfiguration)
4646
import Control.Exception.Safe (throwM)
4747

4848
import System.FilePath ((</>))
49+
import System.IO (hClose)
4950

5051
--------------------------------------------------------------------------------
5152
-- Main
@@ -131,11 +132,14 @@ main = silence $ do
131132
throwM $ LauncherOptionsError (show err)
132133
Right lo -> pure lo
133134

134-
let lockFile = loStateDir launcherOptions </> "daedalus_lockfile"
135+
let stateDir :: FilePath
136+
stateDir = loStateDir launcherOptions
137+
138+
let lockFile = stateDir </> "daedalus_lockfile"
135139
Trace.logNotice baseTrace $ "Locking file so that multiple applications won't run at same time"
136140
-- Check if it's locked or not. Will throw an exception if the
137141
-- application is already running.
138-
_ <- checkIfApplicationIsRunning lockFile
142+
lockHandle <- checkIfApplicationIsRunning lockFile
139143

140144
let workingDir = loWorkingDirectory launcherOptions
141145

@@ -187,6 +191,10 @@ main = silence $ do
187191
daedalusBin
188192
updaterExecutionFunction
189193
updaterData
194+
stateDir
195+
196+
-- release the lock on the lock file
197+
hClose lockHandle
190198

191199
-- Exit the program with exit code.
192200
exitWith exitCode

cardano-launcher/src/Cardano/Shell/Application.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ instance Show ApplicationError where
5353
-- it can find the app state dir by config, or from the server environment. It can release
5454
-- the lock file on shutdown (ok, that's actually automatic, but it fits
5555
-- into the framework as a nice example).
56-
checkIfApplicationIsRunning :: FilePath -> IO ()
56+
checkIfApplicationIsRunning :: FilePath -> IO Handle
5757
checkIfApplicationIsRunning lockFilePath = do
5858

5959
fileExist <- doesFileExist lockFilePath
@@ -71,4 +71,4 @@ checkIfApplicationIsRunning lockFilePath = do
7171
throwM ApplicationAlreadyRunningException
7272

7373
-- Otherwise, all is good.
74-
return ()
74+
return lockfileHandle

cardano-launcher/src/Cardano/Shell/Launcher.hs

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ module Cardano.Shell.Launcher
1111
-- * Functions
1212
, runLauncher
1313
, runWalletProcess
14+
, saveSafeMode
15+
, readSafeMode
1416
-- * Critical exports (testing)
1517
, DaedalusExitCode (..)
1618
, handleDaedalusExitCode
@@ -27,6 +29,8 @@ module Cardano.Shell.Launcher
2729
import Cardano.Prelude hiding (onException)
2830

2931
import Prelude (Show (..))
32+
import Data.Aeson (FromJSON, ToJSON(toJSON), genericParseJSON, genericToJSON, defaultOptions)
33+
import Data.Yaml as Y
3034
import qualified System.Process as Process
3135
import Turtle (system)
3236

@@ -74,6 +78,25 @@ data WalletMode
7478
| WalletModeSafe
7579
deriving (Eq, Show)
7680

81+
instance FromJSON WalletMode where
82+
parseJSON (String "safe") = pure WalletModeSafe
83+
parseJSON (String "normal") = pure WalletModeNormal
84+
parseJSON _ = pure WalletModeNormal
85+
86+
instance ToJSON WalletMode where
87+
toJSON WalletModeNormal = String "normal"
88+
toJSON WalletModeSafe = String "safe"
89+
90+
data SafeModeConfig = SafeModeConfig
91+
{ smcSafeMode :: WalletMode
92+
} deriving (Generic, Show)
93+
94+
instance FromJSON SafeModeConfig where
95+
parseJSON = genericParseJSON defaultOptions
96+
97+
instance ToJSON SafeModeConfig where
98+
toJSON = genericToJSON defaultOptions
99+
77100
-- | All the important exit codes. Since we cover "other" cases as well, this is a total mapping.
78101
-- That is good.
79102
-- TODO(KS): We could extend this to try to encode some interesting properties about it.
@@ -125,6 +148,22 @@ instance Isomorphism DaedalusExitCode ExitCode where
125148
-- Functions
126149
--------------------------------------------------------------------------------
127150

151+
readSafeMode :: FilePath -> IO WalletMode
152+
readSafeMode stateDir = do
153+
let safeModeConfigFile = getSafeModeConfigPath stateDir
154+
decoded <- liftIO $ Y.decodeFileEither safeModeConfigFile
155+
case decoded of
156+
Right value -> pure $ smcSafeMode value
157+
Left _ -> pure WalletModeNormal
158+
159+
saveSafeMode :: FilePath -> WalletMode -> IO ()
160+
saveSafeMode stateDir mode = do
161+
let safeModeConfigFile = getSafeModeConfigPath stateDir
162+
Y.encodeFile safeModeConfigFile $ SafeModeConfig mode
163+
164+
getSafeModeConfigPath :: FilePath -> FilePath
165+
getSafeModeConfigPath stateDir = stateDir </> "safemode.yaml"
166+
128167
-- | Here we handle the exit codes.
129168
-- It's a simple mapping from exit code to actions that the launcher takes.
130169
--
@@ -165,25 +204,30 @@ runWalletProcess
165204
-> WalletRunner
166205
-> RunUpdateFunc
167206
-> UpdaterData
207+
-> FilePath
168208
-> IO ExitCode
169209
runWalletProcess
170210
logDep
171211
walletMode
172212
daedalusBin
173213
walletRunner
174214
runUpdateFunc
175-
updaterData = do
215+
updaterData
216+
stateDir = do
176217

177218
-- Parametrized by @WalletMode@ so we can change it on restart depending
178219
-- on the Daedalus exit code.
179220
let restart :: WalletMode -> IO ExitCode
180-
restart = \walletMode' -> runWalletProcess
221+
restart = \walletMode' -> do
222+
saveSafeMode stateDir walletMode'
223+
runWalletProcess
181224
logDep
182225
walletMode'
183226
daedalusBin
184227
walletRunner
185228
runUpdateFunc
186229
updaterData
230+
stateDir
187231

188232
-- Additional arguments we need to pass if it's a SAFE mode.
189233
let walletSafeModeArgs :: WalletArguments
@@ -269,8 +313,10 @@ runLauncher
269313
-> DaedalusBin
270314
-> RunUpdateFunc
271315
-> UpdaterData
316+
-> FilePath
272317
-> IO ExitCode
273-
runLauncher loggingDependencies walletRunner daedalusBin runUpdateFunc updaterData = do
318+
runLauncher loggingDependencies walletRunner daedalusBin runUpdateFunc updaterData stateDir = do
319+
safeMode <- readSafeMode stateDir
274320

275321
-- In the case the user wants to avoid installing the update now, we
276322
-- run the update (if there is one) when we have it downloaded.
@@ -283,11 +329,12 @@ runLauncher loggingDependencies walletRunner daedalusBin runUpdateFunc updaterDa
283329
-- You still want to run the wallet even if the update fails
284330
runWalletProcess
285331
loggingDependencies
286-
WalletModeNormal
332+
safeMode
287333
daedalusBin
288334
walletRunner
289335
runUpdateFunc
290336
updaterData
337+
stateDir
291338

292339
-- | Generation of the TLS certificates.
293340
-- This just covers the generation of the TLS certificates and nothing else.

cardano-launcher/test/LauncherSpec.hs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE ScopedTypeVariables #-}
2+
{-# OPTIONS_GHC -fno-warn-orphans #-}
23

34
module LauncherSpec where
45

@@ -21,9 +22,10 @@ import Cardano.Shell.CLI (LauncherOptionPath (..),
2122
decodeLauncherOption, setupEnvVars)
2223
import Cardano.Shell.Configuration (LauncherOptions (..),
2324
setWorkingDirectory)
24-
import Cardano.Shell.Launcher (DaedalusExitCode (..),
25+
import Cardano.Shell.Launcher (DaedalusExitCode (..), WalletMode (..),
2526
RestartRunner (..), UpdateRunner (..),
26-
handleDaedalusExitCode)
27+
handleDaedalusExitCode,
28+
readSafeMode, saveSafeMode)
2729
import Cardano.Shell.Launcher.Types (nullLogging)
2830

2931
-- | The simple launcher spec.
@@ -32,8 +34,18 @@ launcherSpec = do
3234
configurationSpec
3335
launcherSystemSpec
3436
setWorkingDirectorySpec
37+
safeModeSpec
3538
--generateTLSCertSpec
3639

40+
safeModeSpec :: Spec
41+
safeModeSpec =
42+
describe "safemode persisting system" $ modifyMaxSuccess (const 10000) $ do
43+
44+
prop "safemode roundtrips" $ \(mode :: WalletMode) -> monadicIO $ do
45+
run $ saveSafeMode "/tmp" mode
46+
readback <- run $ readSafeMode "/tmp"
47+
assert $ mode == readback
48+
3749
-- | The launcher system spec.
3850
launcherSystemSpec :: Spec
3951
launcherSystemSpec =
@@ -86,6 +98,9 @@ newtype ExitCodeNumber = ExitCodeNumber { getExitCodeNumber :: Int }
8698
instance Arbitrary ExitCodeNumber where
8799
arbitrary = ExitCodeNumber <$> elements [1, 2, 126, 127, 128, 130, 255]
88100

101+
instance Arbitrary WalletMode where
102+
arbitrary = elements [ WalletModeSafe, WalletModeNormal ]
103+
89104
-- | List of files we want to test on
90105
-- These are config files downloaded from Daedalus CI
91106
--

0 commit comments

Comments
 (0)