Skip to content

Commit

Permalink
Add --port-file and --dar flags in daml sandbox (#12505)
Browse files Browse the repository at this point in the history
* Add some compatibility flags in daml sandbox

Part of #11831

This PR is just to make it easier to migrate to the new sandbox.
I changed the behavior of --port-file to output a simple port (the
old behavior can be obtained with --canton-port-file instead, which
outputs all the port files of each participant), and I added a --dar
option to upload a dar after setting up the sandbox.

In addition, I made the `daml sandbox` command output something on
startup & success. The previous version was completely silent, so
you couldn't tell just from running it whether it was succesful.

However, I did discover that `--static-time` was accidentally
a no-op. Upon enabling it, I find that sim-clock doesn't work,
it causes canton to hang. This seems like a canton issue, but
needs further investigation.

For testing, I'm using --port-file and --dar in the quickstart
integration test, and --canton-port-file in the other canton
sandbox test.

changelog_begin
changelog_end

* redundant message

* Allow multiple --dar arguments
  • Loading branch information
sofiafaro-da authored Jan 20, 2022
1 parent 3c8a646 commit 7880d54
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 43 deletions.
52 changes: 37 additions & 15 deletions daml-assistant/daml-helper/src/DA/Daml/Helper/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
module DA.Daml.Helper.Main (main) where

import Control.Exception.Safe
import Control.Monad
import Control.Monad.Extra
import DA.Bazel.Runfiles
import Data.Foldable
import Data.List.Extra
import Numeric.Natural
import Options.Applicative.Extended
import System.Environment
import System.Exit
import System.IO
import System.IO.Extra
import System.Process (showCommandForUser)
import System.Process.Typed (unsafeProcessHandle)
import Text.Read (readMaybe)

import DA.Signals
Expand All @@ -24,6 +25,7 @@ import DA.Daml.Helper.Start
import DA.Daml.Helper.Studio
import DA.Daml.Helper.Util
import DA.Daml.Helper.Codegen
import DA.PortFile

main :: IO ()
main = do
Expand Down Expand Up @@ -70,9 +72,11 @@ data Command
| Codegen { lang :: Lang, remainingArguments :: [String] }
| PackagesList {flags :: LedgerFlags}
| CantonSandbox
{ ports :: CantonOptions
, remainingArguments :: [String]
}
{ cantonOptions :: CantonOptions
, portFileM :: Maybe FilePath
, darPaths :: [FilePath]
, remainingArguments :: [String]
}

data AppTemplate
= AppTemplateDefault
Expand Down Expand Up @@ -408,15 +412,22 @@ commandParser = subparser $ fold
, help "Timeout of gRPC operations in seconds. Defaults to 60s. Must be > 0."
]

cantonSandboxCmd = CantonSandbox
<$> (CantonOptions
<$> option auto (long "port" <> value 6865)
<*> option auto (long "admin-api-port" <> value 6866)
<*> 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"))
cantonSandboxCmd = do
cantonOptions <- do
cantonLedgerApi <- option auto (long "port" <> value 6865)
cantonAdminApi <- option auto (long "admin-api-port" <> value 6866)
cantonDomainPublicApi <- option auto (long "domain-public-port" <> value 6867)
cantonDomainAdminApi <- option auto (long "domain-admin-port" <> value 6868)
cantonPortFileM <- optional $ option str (long "canton-port-file" <> metavar "PATH"
<> help "File to write canton participant ports when ready")
cantonStaticTime <- StaticTime <$> switch (long "static-time")
pure CantonOptions{..}
portFileM <- optional $ option str (long "port-file" <> metavar "PATH"
<> help "File to write ledger API port when ready")
darPaths <- many $ option str (long "dar" <> metavar "PATH"
<> help "DAR file to upload to sandbox")
remainingArguments <- many (argument str (metavar "ARG"))
pure CantonSandbox {..}

cantonSandboxCmdInfo =
forwardOptions
Expand Down Expand Up @@ -459,4 +470,15 @@ runCommand = \case
LedgerExport {..} -> runLedgerExport flags remainingArguments
LedgerNavigator {..} -> runLedgerNavigator flags remainingArguments
Codegen {..} -> runCodegen lang remainingArguments
CantonSandbox {..} -> runCantonSandbox ports remainingArguments
CantonSandbox {..} ->
withCantonPortFile cantonOptions $ \cantonOptions cantonPortFile ->
withCantonSandbox cantonOptions remainingArguments $ \ph -> do
putStrLn "Starting Canton sandbox."
sandboxPort <- readPortFileWith decodeCantonSandboxPort (unsafeProcessHandle ph) maxRetries cantonPortFile
putStrLn ("Listening at port " <> show sandboxPort)
forM_ darPaths $ \darPath -> do
runLedgerUploadDar ((defaultLedgerFlags Grpc) {fPortM = Just sandboxPort}) (Just darPath)
whenJust portFileM $ \portFile -> do
putStrLn ("Writing ledger API port to " <> portFile)
writeFileUTF8 portFile (show sandboxPort)
putStrLn "Canton sandbox is ready."
12 changes: 6 additions & 6 deletions daml-assistant/daml-helper/src/DA/Daml/Helper/Start.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ getPortForSandbox defaultPortSpec portSpecM =

determineCantonOptions :: Maybe SandboxPortSpec -> SandboxCantonPortSpec -> FilePath -> IO CantonOptions
determineCantonOptions ledgerApiSpec SandboxCantonPortSpec{..} portFile = do
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
cantonLedgerApi <- getPortForSandbox (SpecifiedPort (SandboxPort 6865)) ledgerApiSpec
cantonAdminApi <- getPortForSandbox FreePort adminApiSpec
cantonDomainPublicApi <- getPortForSandbox FreePort domainPublicApiSpec
cantonDomainAdminApi <- getPortForSandbox FreePort domainAdminApiSpec
let cantonPortFileM = Just portFile -- TODO allow canton port file to be passed in from command line?
let cantonStaticTime = StaticTime False
pure CantonOptions {..}

withSandbox :: StartOptions -> FilePath -> [String] -> [String] -> (Process () () () -> SandboxPort -> IO a) -> IO a
Expand Down
38 changes: 25 additions & 13 deletions daml-assistant/daml-helper/src/DA/Daml/Helper/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module DA.Daml.Helper.Util
, runJar
, runCantonSandbox
, withCantonSandbox
, withCantonPortFile
, getLogbackArg
, waitForHttpServer
, tokenFor
Expand All @@ -41,7 +42,7 @@ import qualified Network.HTTP.Types as HTTP
import System.Directory
import System.FilePath
import System.IO
import System.IO.Extra (withTempFile)
import System.IO.Extra (withTempDir, withTempFile)
import System.Info.Extra
import System.Exit (exitFailure)
import System.Process (ProcessHandle, getProcessExitCode, showCommandForUser, terminateProcess)
Expand Down Expand Up @@ -254,39 +255,50 @@ withCantonSandbox options remainingArgs k = do
BSL.writeFile config (cantonConfig options)
withJar cantonJar [] ("daemon" : "-c" : config : "--auto-connect-local" : remainingArgs) k

-- | Obtain a path to use as canton portfile, and give updated options.
withCantonPortFile :: CantonOptions -> (CantonOptions -> FilePath -> IO a) -> IO a
withCantonPortFile options kont =
case cantonPortFileM options of
Nothing ->
withTempDir $ \ tempDir -> do
let portFile = tempDir </> "canton-portfile.json"
kont options { cantonPortFileM = Just portFile } portFile
Just portFile ->
kont options portFile

newtype StaticTime = StaticTime Bool

data CantonOptions = CantonOptions
{ ledgerApi :: Int
, adminApi :: Int
, domainPublicApi :: Int
, domainAdminApi :: Int
, portFileM :: Maybe FilePath
, staticTime :: StaticTime
{ cantonLedgerApi :: Int
, cantonAdminApi :: Int
, cantonDomainPublicApi :: Int
, cantonDomainAdminApi :: Int
, cantonPortFileM :: Maybe FilePath
, cantonStaticTime :: StaticTime
}

cantonConfig :: CantonOptions -> BSL.ByteString
cantonConfig CantonOptions{..} =
Aeson.encode $ Aeson.object
[ "canton" Aeson..= Aeson.object
[ "parameters" Aeson..= Aeson.object ( concat
[ [ "ports-file" Aeson..= portFile | Just portFile <- [portFileM] ]
[ [ "ports-file" Aeson..= portFile | Just portFile <- [cantonPortFileM] ]
, [ "clock" Aeson..= Aeson.object
[ "type" Aeson..= ("sim-clock" :: T.Text) ]
| StaticTime True <- [] ]
| StaticTime True <- [cantonStaticTime] ]
] )
, "participants" Aeson..= Aeson.object
[ "sandbox" Aeson..= Aeson.object
[ storage
, "admin-api" Aeson..= port adminApi
, "ledger-api" Aeson..= port ledgerApi
, "admin-api" Aeson..= port cantonAdminApi
, "ledger-api" Aeson..= port cantonLedgerApi
]
]
, "domains" Aeson..= Aeson.object
[ "local" Aeson..= Aeson.object
[ storage
, "public-api" Aeson..= port domainPublicApi
, "admin-api" Aeson..= port domainAdminApi
, "public-api" Aeson..= port cantonDomainPublicApi
, "admin-api" Aeson..= port cantonDomainAdminApi
]
]
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,14 @@ quickSandbox projDir = do
, "--domain-public-port", show domainPublicApiPort
, "--domain-admin-port", show domainAdminApiPort
, "--port-file", portFile
, "--static-time"
, "--dar", darFile
-- , "--static-time"
-- TODO https://github.com/digital-asset/daml/issues/11831
-- Re-enable once sim-clock is working.
])
{std_out = UseHandle devNull, create_group = True, cwd = Just projDir}
(_, _, _, sandboxPh) <- createProcess sandboxProc
_ <- readPortFileWith decodeCantonSandboxPort sandboxPh maxRetries (projDir </> portFile)
callCommandSilentIn projDir $ unwords
[ "daml ledger upload-dar"
, "--host=localhost"
, "--port=" <> show sandboxPort
, darFile
]
_ <- readPortFile sandboxPh maxRetries (projDir </> portFile)
pure $
QuickSandboxResource
{ quickProjDir = projDir
Expand Down Expand Up @@ -801,7 +798,7 @@ cantonTests = testGroup "daml sandbox"
, "--admin-api-port", show adminApiPort
, "--domain-public-port", show domainPublicApiPort
, "--domain-admin-port", show domainAdminApiPort
, "--port-file", portFile
, "--canton-port-file", portFile
] $ \ ph -> do
-- wait for port file to be written
_ <- readPortFileWith decodeCantonSandboxPort ph maxRetries portFile
Expand Down

0 comments on commit 7880d54

Please sign in to comment.