Skip to content

Commit

Permalink
Change default sandbox to canton (#12438)
Browse files Browse the repository at this point in the history
* Change default sandbox to canton.

Some progress on #11831

* made `daml start` use canton sandbox by default
  * changed the non-ledger api ports to use free ports by default
    (still haven't tried using port 0 instead of `getFreePort`).
* renamed `daml sandbox-canton` to `daml sandbox`
* implement a `--static-time` option for `daml sandbox` that sets the
  canton clock type parameter to `sim-clock`
* moved the quickstart-java integration test to use the new sandbox
  * the test uses `--static-time`, but doesn't really depend on it

changelog_begin
changelog_end

* fix parens

* fix hot reload test

* reinstant --sandbox-kv in create-daml-app test for now

* fix damlStart test
  • Loading branch information
sofiafaro-da authored Jan 18, 2022
1 parent ab16a54 commit b2a7f9e
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 196 deletions.
12 changes: 6 additions & 6 deletions daml-assistant/daml-helper/src/DA/Daml/Helper/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ commandParser = subparser $ fold
, command "run-jar" (info runJarCmd forwardOptions)
, command "codegen" (info (codegenCmd <**> helper) forwardOptions)
, command "packages" (info (packagesCmd <**> helper) packagesCmdInfo)
, command "sandbox-canton" (info (cantonSandboxCmd <**> helper) cantonSandboxCmdInfo)
, command "sandbox" (info (cantonSandboxCmd <**> helper) cantonSandboxCmdInfo)
]
where

Expand Down Expand Up @@ -166,13 +166,13 @@ commandParser = subparser $ fold

sandboxChoiceOpt =
flag' SandboxKV (long "sandbox-kv" <> help "Deprecated. Run with Sandbox KV.")
<|> flag' SandboxCanton (long "sandbox-canton" <> help "Run with Canton Sandbox. The 2.0 default.")
<|> flag SandboxCanton SandboxCanton (long "sandbox-canton" <> help "Run with Canton Sandbox. The 2.0 default.")
<*> sandboxCantonPortSpecOpt

sandboxCantonPortSpecOpt = do
adminApiSpec <- sandboxPortOpt "canton-admin-api-port" "Port number for the canton admin API (--sandbox-canton only)"
domainPublicApiSpec <- sandboxPortOpt "canton-domain-public-port" "Port number for the canton domain public API (--sandbox-canton only)"
domainAdminApiSpec <- sandboxPortOpt "canton-domain-admin-port" "Port number for the canton domain admin API (--sandbox-canton only)"
adminApiSpec <- sandboxPortOpt "sandbox-admin-api-port" "Port number for the canton admin API (--sandbox-canton only)"
domainPublicApiSpec <- sandboxPortOpt "sandbox-domain-public-port" "Port number for the canton domain public API (--sandbox-canton only)"
domainAdminApiSpec <- sandboxPortOpt "sandbox-domain-admin-port" "Port number for the canton domain admin API (--sandbox-canton only)"
pure SandboxCantonPortSpec {..}

navigatorPortOption = NavigatorPort <$> option auto
Expand Down Expand Up @@ -415,7 +415,7 @@ commandParser = subparser $ fold
<*> option auto (long "domain-public-port" <> value 6867)
<*> option auto (long "domain-admin-port" <> value 6868)
<*> optional (option str (long "port-file" <> metavar "PATH"))
)
<*> (StaticTime <$> switch (long "static-time")))
<*> many (argument str (metavar "ARG"))

cantonSandboxCmdInfo =
Expand Down
19 changes: 10 additions & 9 deletions daml-assistant/daml-helper/src/DA/Daml/Helper/Start.hs
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,20 @@ navigatorURL (NavigatorPort p) = "http://localhost:" <> show p

-- | Use SandboxPortSpec to determine a sandbox port number.
-- This is racy thanks to getFreePort, but there's no good alternative at the moment.
getPortForSandbox :: Int -> Maybe SandboxPortSpec -> IO Int
getPortForSandbox defaultPort = \case
Nothing -> pure defaultPort
Just (SpecifiedPort port) -> pure (unSandboxPort port)
Just FreePort -> fromIntegral <$> getFreePort
getPortForSandbox :: SandboxPortSpec -> Maybe SandboxPortSpec -> IO Int
getPortForSandbox defaultPortSpec portSpecM =
case fromMaybe defaultPortSpec portSpecM of
SpecifiedPort port -> pure (unSandboxPort port)
FreePort -> fromIntegral <$> getFreePort

determineCantonOptions :: Maybe SandboxPortSpec -> SandboxCantonPortSpec -> FilePath -> IO CantonOptions
determineCantonOptions ledgerApiSpec SandboxCantonPortSpec{..} portFile = do
ledgerApi <- getPortForSandbox 6865 ledgerApiSpec
adminApi <- getPortForSandbox 6866 adminApiSpec
domainPublicApi <- getPortForSandbox 6867 domainPublicApiSpec
domainAdminApi <- getPortForSandbox 6868 domainAdminApiSpec
ledgerApi <- getPortForSandbox (SpecifiedPort (SandboxPort 6865)) ledgerApiSpec
adminApi <- getPortForSandbox FreePort adminApiSpec
domainPublicApi <- getPortForSandbox FreePort domainPublicApiSpec
domainAdminApi <- getPortForSandbox FreePort domainAdminApiSpec
let portFileM = Just portFile -- TODO allow canton port file to be passed in from command line?
let staticTime = StaticTime False
pure CantonOptions {..}

withSandbox :: StartOptions -> FilePath -> [String] -> [String] -> (Process () () () -> SandboxPort -> IO a) -> IO a
Expand Down
50 changes: 13 additions & 37 deletions daml-assistant/daml-helper/src/DA/Daml/Helper/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ module DA.Daml.Helper.Util
, runCantonSandbox
, withCantonSandbox
, getLogbackArg
, waitForConnectionOnPort
, waitForHttpServer
, tokenFor
, StaticTime(..)
, CantonOptions(..)
, decodeCantonSandboxPort
) where
Expand All @@ -38,7 +38,6 @@ import Data.Maybe
import qualified Data.Text as T
import qualified Network.HTTP.Simple as HTTP
import qualified Network.HTTP.Types as HTTP
import Network.Socket
import System.Directory
import System.FilePath
import System.IO
Expand Down Expand Up @@ -196,34 +195,6 @@ damlSdkJarFolder = "daml-sdk"
damlSdkJar :: FilePath
damlSdkJar = damlSdkJarFolder </> "daml-sdk.jar"

-- | `waitForConnectionOnPort numTries processHandle sleep port` tries to establish a TCP connection
-- on the given port, in a given number of tries. Between each connection request it checks that a
-- certain process is still alive and calls `sleep`.
waitForConnectionOnPort :: Int -> ProcessHandle -> IO () -> Int -> IO ()
waitForConnectionOnPort 0 _processHandle _sleep port = do
hPutStrLn stderr ("Failed to connect to port " <> show port <> " in time.")
exitFailure
waitForConnectionOnPort numTries processHandle sleep port = do
let hints = defaultHints { addrFlags = [AI_NUMERICHOST, AI_NUMERICSERV], addrSocketType = Stream }
addr : _ <- getAddrInfo (Just hints) (Just "127.0.0.1") (Just $ show port)
r <- tryIO $ checkConnection addr
case r of
Right _ -> pure ()
Left _ -> do
sleep
status <- getProcessExitCode processHandle
case status of
Nothing -> waitForConnectionOnPort (numTries-1) processHandle sleep port
Just exitCode -> do
hPutStrLn stderr ("Failed to connect to port " <> show port
<> " before process exited with " <> show exitCode)
exitFailure
where
checkConnection addr = bracket
(socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr))
close
(\s -> connect s (addrAddress addr))

-- | `waitForHttpServer numTries processHandle sleep url headers` tries to establish an HTTP connection on
-- the given URL with the given headers, in a given number of tries. Between each connection request
-- it checks that a certain process is still alive and calls `sleep`.
Expand Down Expand Up @@ -283,19 +254,28 @@ withCantonSandbox options remainingArgs k = do
BSL.writeFile config (cantonConfig options)
withJar cantonJar [] ("daemon" : "-c" : config : "--auto-connect-local" : remainingArgs) k

newtype StaticTime = StaticTime Bool

data CantonOptions = CantonOptions
{ ledgerApi :: Int
, adminApi :: Int
, domainPublicApi :: Int
, domainAdminApi :: Int
, portFileM :: Maybe FilePath
, staticTime :: StaticTime
}

cantonConfig :: CantonOptions -> BSL.ByteString
cantonConfig CantonOptions{..} =
Aeson.encode $ Aeson.object
[ "canton" Aeson..= Aeson.object (
[ "participants" Aeson..= Aeson.object
[ "canton" Aeson..= Aeson.object
[ "parameters" Aeson..= Aeson.object ( concat
[ [ "ports-file" Aeson..= portFile | Just portFile <- [portFileM] ]
, [ "clock" Aeson..= Aeson.object
[ "type" Aeson..= ("sim-clock" :: T.Text) ]
| StaticTime True <- [] ]
] )
, "participants" Aeson..= Aeson.object
[ "sandbox" Aeson..= Aeson.object
[ storage
, "admin-api" Aeson..= port adminApi
Expand All @@ -309,11 +289,7 @@ cantonConfig CantonOptions{..} =
, "admin-api" Aeson..= port domainAdminApi
]
]
] ++
[ "parameters" Aeson..= Aeson.object
[ "ports-file" Aeson..= portFile ]
| Just portFile <- [portFileM]
] )
]
]
where
port p = Aeson.object [ "port" Aeson..= p ]
Expand Down
Loading

0 comments on commit b2a7f9e

Please sign in to comment.