From b45952f43f6ef52f7468e13f6bfff979e8647ba5 Mon Sep 17 00:00:00 2001 From: John Ky Date: Sat, 25 May 2024 23:24:00 +1000 Subject: [PATCH 1/5] Move ClientCommand to Cardano.CLI.Commands module --- cardano-cli/cardano-cli.cabal | 1 + cardano-cli/src/Cardano/CLI/Commands.hs | 27 +++++++++++++++++++++++++ cardano-cli/src/Cardano/CLI/Run.hs | 21 +++---------------- 3 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 cardano-cli/src/Cardano/CLI/Commands.hs diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 35b9ec613c..d36b464237 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -55,6 +55,7 @@ library Cardano.CLI.Byron.Tx Cardano.CLI.Byron.UpdateProposal Cardano.CLI.Byron.Vote + Cardano.CLI.Commands Cardano.CLI.Environment Cardano.CLI.EraBased.Commands Cardano.CLI.EraBased.Commands.Address diff --git a/cardano-cli/src/Cardano/CLI/Commands.hs b/cardano-cli/src/Cardano/CLI/Commands.hs new file mode 100644 index 0000000000..bfca2303d5 --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Commands.hs @@ -0,0 +1,27 @@ +{-# LANGUAGE GADTs #-} + +module Cardano.CLI.Commands + ( ClientCommand(..) + ) where + +import Cardano.CLI.Byron.Commands (ByronCommand) +import Cardano.CLI.EraBased.Commands +import Cardano.CLI.Legacy.Commands +import Cardano.CLI.Run.Ping (PingCmd (..)) + +import Options.Applicative.Types (ParserInfo (..), ParserPrefs (..)) + +-- | Sub-commands of 'cardano-cli'. +data ClientCommand = + AnyEraCommand AnyEraCommand + + -- | Byron Related Commands + | ByronCommand ByronCommand + + -- | Legacy shelley-based Commands + | LegacyCmds LegacyCmds + + | CliPingCommand PingCmd + + | forall a. Help ParserPrefs (ParserInfo a) + | DisplayVersion diff --git a/cardano-cli/src/Cardano/CLI/Run.hs b/cardano-cli/src/Cardano/CLI/Run.hs index ffef05dca9..6c96b66fed 100644 --- a/cardano-cli/src/Cardano/CLI/Run.hs +++ b/cardano-cli/src/Cardano/CLI/Run.hs @@ -10,16 +10,16 @@ module Cardano.CLI.Run , runClientCommand ) where -import Cardano.CLI.Byron.Commands (ByronCommand) import Cardano.CLI.Byron.Run (ByronClientCmdError, renderByronClientCmdError, runByronClientCommand) +import Cardano.CLI.Commands import Cardano.CLI.EraBased.Commands import Cardano.CLI.EraBased.Run import Cardano.CLI.Legacy.Commands import Cardano.CLI.Legacy.Run (runLegacyCmds) import Cardano.CLI.Render (customRenderHelp) -import Cardano.CLI.Run.Ping (PingClientCmdError (..), PingCmd (..), - renderPingClientCmdError, runPingCmd) +import Cardano.CLI.Run.Ping (PingClientCmdError (..), renderPingClientCmdError, + runPingCmd) import Cardano.CLI.Types.Errors.CmdError import Cardano.Git.Rev (gitRev) @@ -41,21 +41,6 @@ import qualified System.IO as IO import Paths_cardano_cli (version) --- | Sub-commands of 'cardano-cli'. -data ClientCommand = - AnyEraCommand AnyEraCommand - - -- | Byron Related Commands - | ByronCommand ByronCommand - - -- | Legacy shelley-based Commands - | LegacyCmds LegacyCmds - - | CliPingCommand PingCmd - - | forall a. Help ParserPrefs (ParserInfo a) - | DisplayVersion - data ClientCommandErrors = ByronClientError ByronClientCmdError | CmdError Text CmdError From 38e9fe797ef0a4cda67f01a0e76efb6dc763cfbf Mon Sep 17 00:00:00 2001 From: John Ky Date: Sat, 25 May 2024 23:29:21 +1000 Subject: [PATCH 2/5] Move PingCmd to Cardano.CLI.Commands.Ping --- cardano-cli/cardano-cli.cabal | 1 + cardano-cli/src/Cardano/CLI/Commands/Ping.hs | 21 ++++++++++++++++++++ cardano-cli/src/Cardano/CLI/Run/Ping.hs | 15 +------------- 3 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 cardano-cli/src/Cardano/CLI/Commands/Ping.hs diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index d36b464237..28209b855c 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -56,6 +56,7 @@ library Cardano.CLI.Byron.UpdateProposal Cardano.CLI.Byron.Vote Cardano.CLI.Commands + Cardano.CLI.Commands.Ping Cardano.CLI.Environment Cardano.CLI.EraBased.Commands Cardano.CLI.EraBased.Commands.Address diff --git a/cardano-cli/src/Cardano/CLI/Commands/Ping.hs b/cardano-cli/src/Cardano/CLI/Commands/Ping.hs new file mode 100644 index 0000000000..60c1e0f07a --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Commands/Ping.hs @@ -0,0 +1,21 @@ +module Cardano.CLI.Commands.Ping + ( EndPoint(..) + , PingCmd(..) + ) where + +import Data.Word + +data EndPoint = + HostEndPoint String + | UnixSockEndPoint String + deriving (Eq, Show) + +data PingCmd = PingCmd + { pingCmdCount :: !Word32 + , pingCmdEndPoint :: !EndPoint + , pingCmdPort :: !String + , pingCmdMagic :: !Word32 + , pingCmdJson :: !Bool + , pingCmdQuiet :: !Bool + , pingOptsHandshakeQuery :: !Bool + } deriving (Eq, Show) diff --git a/cardano-cli/src/Cardano/CLI/Run/Ping.hs b/cardano-cli/src/Cardano/CLI/Run/Ping.hs index a52e96ac47..03f6dfc35b 100644 --- a/cardano-cli/src/Cardano/CLI/Run/Ping.hs +++ b/cardano-cli/src/Cardano/CLI/Run/Ping.hs @@ -11,8 +11,8 @@ module Cardano.CLI.Run.Ping , parsePingCmd ) where +import Cardano.CLI.Commands.Ping import Cardano.CLI.Pretty - import qualified Cardano.Network.Ping as CNP import Control.Applicative ((<|>)) @@ -27,7 +27,6 @@ import Control.Tracer (Tracer (..)) import Data.List (foldl') import qualified Data.List as L import qualified Data.List as List -import Data.Word (Word32) import Network.Socket (AddrInfo) import qualified Network.Socket as Socket import qualified Options.Applicative as Opt @@ -37,8 +36,6 @@ import qualified System.IO as IO newtype PingClientCmdError = PingClientCmdError [(AddrInfo, SomeException)] -data EndPoint = HostEndPoint String | UnixSockEndPoint String deriving (Eq, Show) - maybeHostEndPoint :: EndPoint -> Maybe String maybeHostEndPoint = \case HostEndPoint host -> Just host @@ -49,16 +46,6 @@ maybeUnixSockEndPoint = \case HostEndPoint _ -> Nothing UnixSockEndPoint sock -> Just sock -data PingCmd = PingCmd - { pingCmdCount :: !Word32 - , pingCmdEndPoint :: !EndPoint - , pingCmdPort :: !String - , pingCmdMagic :: !Word32 - , pingCmdJson :: !Bool - , pingCmdQuiet :: !Bool - , pingOptsHandshakeQuery :: !Bool - } deriving (Eq, Show) - pingClient :: Tracer IO CNP.LogMsg -> Tracer IO String -> PingCmd -> [CNP.NodeVersion] -> AddrInfo -> IO () pingClient stdout stderr cmd = CNP.pingClient stdout stderr opts where opts = CNP.PingOpts From f326ad313a9d73a0e330a693757badc76fab296f Mon Sep 17 00:00:00 2001 From: John Ky Date: Sat, 25 May 2024 23:44:41 +1000 Subject: [PATCH 3/5] Move ping command parser to Cardano.CLI.Options.Ping --- cardano-cli/cardano-cli.cabal | 1 + cardano-cli/src/Cardano/CLI/Commands.hs | 2 +- cardano-cli/src/Cardano/CLI/Options.hs | 2 +- cardano-cli/src/Cardano/CLI/Options/Ping.hs | 91 +++++++++++++++++++++ cardano-cli/src/Cardano/CLI/Run/Ping.hs | 87 +------------------- 5 files changed, 95 insertions(+), 88 deletions(-) create mode 100644 cardano-cli/src/Cardano/CLI/Options/Ping.hs diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 28209b855c..15758e6822 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -140,6 +140,7 @@ library Cardano.CLI.Legacy.Run.TextView Cardano.CLI.Legacy.Run.Transaction Cardano.CLI.Options + Cardano.CLI.Options.Ping Cardano.CLI.OS.Posix Cardano.CLI.Parser Cardano.CLI.Pretty diff --git a/cardano-cli/src/Cardano/CLI/Commands.hs b/cardano-cli/src/Cardano/CLI/Commands.hs index bfca2303d5..c994a79c02 100644 --- a/cardano-cli/src/Cardano/CLI/Commands.hs +++ b/cardano-cli/src/Cardano/CLI/Commands.hs @@ -5,9 +5,9 @@ module Cardano.CLI.Commands ) where import Cardano.CLI.Byron.Commands (ByronCommand) +import Cardano.CLI.Commands.Ping (PingCmd (..)) import Cardano.CLI.EraBased.Commands import Cardano.CLI.Legacy.Commands -import Cardano.CLI.Run.Ping (PingCmd (..)) import Options.Applicative.Types (ParserInfo (..), ParserPrefs (..)) diff --git a/cardano-cli/src/Cardano/CLI/Options.hs b/cardano-cli/src/Cardano/CLI/Options.hs index 81f70f412e..4b0b1656d3 100644 --- a/cardano-cli/src/Cardano/CLI/Options.hs +++ b/cardano-cli/src/Cardano/CLI/Options.hs @@ -15,9 +15,9 @@ import Cardano.CLI.Environment (EnvCli) import Cardano.CLI.EraBased.Commands import Cardano.CLI.EraBased.Options.Common import Cardano.CLI.Legacy.Options (parseLegacyCmds) +import Cardano.CLI.Options.Ping (parsePingCmd) import Cardano.CLI.Render (customRenderHelp) import Cardano.CLI.Run (ClientCommand (..)) -import Cardano.CLI.Run.Ping (parsePingCmd) import Data.Foldable import Options.Applicative diff --git a/cardano-cli/src/Cardano/CLI/Options/Ping.hs b/cardano-cli/src/Cardano/CLI/Options/Ping.hs new file mode 100644 index 0000000000..b16cf1a45c --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Options/Ping.hs @@ -0,0 +1,91 @@ +{-# LANGUAGE TypeApplications #-} + +module Cardano.CLI.Options.Ping + ( parsePingCmd + ) where + +import Cardano.CLI.Commands.Ping +import qualified Cardano.Network.Ping as CNP + +import Control.Applicative ((<|>)) +import qualified Options.Applicative as Opt +import qualified Prettyprinter as PP + +parsePingCmd :: Opt.Parser PingCmd +parsePingCmd = Opt.hsubparser $ mconcat + [ Opt.metavar "ping" + , Opt.command "ping" $ Opt.info pPing $ Opt.progDescDoc $ Just $ mconcat + [ PP.pretty @String "Ping a cardano node either using node-to-node or node-to-client protocol. " + , PP.pretty @String "It negotiates a handshake and keeps sending keep alive messages." + ] + ] + +pHost :: Opt.Parser String +pHost = + Opt.strOption $ mconcat + [ Opt.long "host" + , Opt.short 'h' + , Opt.metavar "HOST" + , Opt.help "Hostname/IP, e.g. relay.iohk.example." + ] + +pUnixSocket :: Opt.Parser String +pUnixSocket = + Opt.strOption $ mconcat + [ Opt.long "unixsock" + , Opt.short 'u' + , Opt.metavar "SOCKET" + , Opt.help "Unix socket, e.g. file.socket." + ] + +pEndPoint :: Opt.Parser EndPoint +pEndPoint = fmap HostEndPoint pHost <|> fmap UnixSockEndPoint pUnixSocket + +pPing :: Opt.Parser PingCmd +pPing = PingCmd + <$> ( Opt.option Opt.auto $ mconcat + [ Opt.long "count" + , Opt.short 'c' + , Opt.metavar "COUNT" + , Opt.help $ mconcat + [ "Stop after sending count requests and receiving count responses. " + , "If this option is not specified, ping will operate until interrupted. " + ] + , Opt.value maxBound + ] + ) + <*> pEndPoint + <*> ( Opt.strOption $ mconcat + [ Opt.long "port" + , Opt.short 'p' + , Opt.metavar "PORT" + , Opt.help "Port number, e.g. 1234." + , Opt.value "3001" + ] + ) + <*> ( Opt.option Opt.auto $ mconcat + [ Opt.long "magic" + , Opt.short 'm' + , Opt.metavar "MAGIC" + , Opt.help "Network magic." + , Opt.value CNP.mainnetMagic + ] + ) + <*> ( Opt.switch $ mconcat + [ Opt.long "json" + , Opt.short 'j' + , Opt.help "JSON output flag." + ] + ) + <*> ( Opt.switch $ mconcat + [ Opt.long "quiet" + , Opt.short 'q' + , Opt.help "Quiet flag, CSV/JSON only output" + ] + ) + <*> ( Opt.switch $ mconcat + [ Opt.long "query-versions" + , Opt.short 'Q' + , Opt.help "Query the supported protocol versions using the handshake protocol and terminate the connection." + ] + ) diff --git a/cardano-cli/src/Cardano/CLI/Run/Ping.hs b/cardano-cli/src/Cardano/CLI/Run/Ping.hs index 03f6dfc35b..8133aac498 100644 --- a/cardano-cli/src/Cardano/CLI/Run/Ping.hs +++ b/cardano-cli/src/Cardano/CLI/Run/Ping.hs @@ -1,21 +1,17 @@ {-# LANGUAGE LambdaCase #-} -{-# LANGUAGE TypeApplications #-} {- HLINT ignore "Move brackets to avoid $" -} module Cardano.CLI.Run.Ping - ( PingCmd(..) - , PingClientCmdError(..) + ( PingClientCmdError(..) , renderPingClientCmdError , runPingCmd - , parsePingCmd ) where import Cardano.CLI.Commands.Ping import Cardano.CLI.Pretty import qualified Cardano.Network.Ping as CNP -import Control.Applicative ((<|>)) import Control.Concurrent.Class.MonadSTM.Strict (StrictTMVar) import qualified Control.Concurrent.Class.MonadSTM.Strict as STM import Control.Exception (SomeException) @@ -29,8 +25,6 @@ import qualified Data.List as L import qualified Data.List as List import Network.Socket (AddrInfo) import qualified Network.Socket as Socket -import qualified Options.Applicative as Opt -import qualified Prettyprinter as PP import qualified System.Exit as IO import qualified System.IO as IO @@ -112,82 +106,3 @@ runPingCmd options = do renderPingClientCmdError :: PingClientCmdError -> Doc ann renderPingClientCmdError = \case PingClientCmdError es -> mconcat $ List.intersperse "\n" $ pshow <$> es - -parsePingCmd :: Opt.Parser PingCmd -parsePingCmd = Opt.hsubparser $ mconcat - [ Opt.metavar "ping" - , Opt.command "ping" $ Opt.info pPing $ Opt.progDescDoc $ Just $ mconcat - [ PP.pretty @String "Ping a cardano node either using node-to-node or node-to-client protocol. " - , PP.pretty @String "It negotiates a handshake and keeps sending keep alive messages." - ] - ] - -pHost :: Opt.Parser String -pHost = - Opt.strOption $ mconcat - [ Opt.long "host" - , Opt.short 'h' - , Opt.metavar "HOST" - , Opt.help "Hostname/IP, e.g. relay.iohk.example." - ] - -pUnixSocket :: Opt.Parser String -pUnixSocket = - Opt.strOption $ mconcat - [ Opt.long "unixsock" - , Opt.short 'u' - , Opt.metavar "SOCKET" - , Opt.help "Unix socket, e.g. file.socket." - ] - -pEndPoint :: Opt.Parser EndPoint -pEndPoint = fmap HostEndPoint pHost <|> fmap UnixSockEndPoint pUnixSocket - -pPing :: Opt.Parser PingCmd -pPing = PingCmd - <$> ( Opt.option Opt.auto $ mconcat - [ Opt.long "count" - , Opt.short 'c' - , Opt.metavar "COUNT" - , Opt.help $ mconcat - [ "Stop after sending count requests and receiving count responses. " - , "If this option is not specified, ping will operate until interrupted. " - ] - , Opt.value maxBound - ] - ) - <*> pEndPoint - <*> ( Opt.strOption $ mconcat - [ Opt.long "port" - , Opt.short 'p' - , Opt.metavar "PORT" - , Opt.help "Port number, e.g. 1234." - , Opt.value "3001" - ] - ) - <*> ( Opt.option Opt.auto $ mconcat - [ Opt.long "magic" - , Opt.short 'm' - , Opt.metavar "MAGIC" - , Opt.help "Network magic." - , Opt.value CNP.mainnetMagic - ] - ) - <*> ( Opt.switch $ mconcat - [ Opt.long "json" - , Opt.short 'j' - , Opt.help "JSON output flag." - ] - ) - <*> ( Opt.switch $ mconcat - [ Opt.long "quiet" - , Opt.short 'q' - , Opt.help "Quiet flag, CSV/JSON only output" - ] - ) - <*> ( Opt.switch $ mconcat - [ Opt.long "query-versions" - , Opt.short 'Q' - , Opt.help "Query the supported protocol versions using the handshake protocol and terminate the connection." - ] - ) From 116a342ae3b1f17b9c9646d06d1f638218d617fe Mon Sep 17 00:00:00 2001 From: John Ky Date: Thu, 30 May 2024 01:33:55 +1000 Subject: [PATCH 4/5] New debug log-epoch-state command --- cardano-cli/cardano-cli.cabal | 7 +++ cardano-cli/src/Cardano/CLI/Commands.hs | 2 + cardano-cli/src/Cardano/CLI/Commands/Debug.hs | 8 +++ .../CLI/Commands/Debug/LogEpochState.hs | 22 +++++++ cardano-cli/src/Cardano/CLI/Options.hs | 5 ++ cardano-cli/src/Cardano/CLI/Options/Debug.hs | 63 +++++++++++++++++++ cardano-cli/src/Cardano/CLI/Options/Ping.hs | 2 + cardano-cli/src/Cardano/CLI/Orphans.hs | 24 +++++++ cardano-cli/src/Cardano/CLI/Run.hs | 6 ++ cardano-cli/src/Cardano/CLI/Run/Debug.hs | 24 +++++++ .../Cardano/CLI/Run/Debug/LogEpochState.hs | 44 +++++++++++++ .../cardano-cli-golden/files/golden/help.cli | 13 ++++ .../golden/help/debug_log-epoch-state.cli | 19 ++++++ 13 files changed, 239 insertions(+) create mode 100644 cardano-cli/src/Cardano/CLI/Commands/Debug.hs create mode 100644 cardano-cli/src/Cardano/CLI/Commands/Debug/LogEpochState.hs create mode 100644 cardano-cli/src/Cardano/CLI/Options/Debug.hs create mode 100644 cardano-cli/src/Cardano/CLI/Orphans.hs create mode 100644 cardano-cli/src/Cardano/CLI/Run/Debug.hs create mode 100644 cardano-cli/src/Cardano/CLI/Run/Debug/LogEpochState.hs create mode 100644 cardano-cli/test/cardano-cli-golden/files/golden/help/debug_log-epoch-state.cli diff --git a/cardano-cli/cardano-cli.cabal b/cardano-cli/cardano-cli.cabal index 15758e6822..3964bfbb9d 100644 --- a/cardano-cli/cardano-cli.cabal +++ b/cardano-cli/cardano-cli.cabal @@ -57,6 +57,8 @@ library Cardano.CLI.Byron.Vote Cardano.CLI.Commands Cardano.CLI.Commands.Ping + Cardano.CLI.Commands.Debug + Cardano.CLI.Commands.Debug.LogEpochState Cardano.CLI.Environment Cardano.CLI.EraBased.Commands Cardano.CLI.EraBased.Commands.Address @@ -140,13 +142,17 @@ library Cardano.CLI.Legacy.Run.TextView Cardano.CLI.Legacy.Run.Transaction Cardano.CLI.Options + Cardano.CLI.Options.Debug Cardano.CLI.Options.Ping + Cardano.CLI.Orphans Cardano.CLI.OS.Posix Cardano.CLI.Parser Cardano.CLI.Pretty Cardano.CLI.Read Cardano.CLI.Render Cardano.CLI.Run + Cardano.CLI.Run.Debug + Cardano.CLI.Run.Debug.LogEpochState Cardano.CLI.Run.Ping Cardano.CLI.TopHandler Cardano.CLI.Types.Common @@ -208,6 +214,7 @@ library , cardano-git-rev ^>= 0.2.2 , cardano-ledger-api , cardano-ledger-byron >= 1.0.1.0 + , cardano-ledger-shelley , cardano-ping ^>= 0.2.0.13 , cardano-prelude , cardano-slotting ^>= 0.2.0.0 diff --git a/cardano-cli/src/Cardano/CLI/Commands.hs b/cardano-cli/src/Cardano/CLI/Commands.hs index c994a79c02..e1499afa11 100644 --- a/cardano-cli/src/Cardano/CLI/Commands.hs +++ b/cardano-cli/src/Cardano/CLI/Commands.hs @@ -5,6 +5,7 @@ module Cardano.CLI.Commands ) where import Cardano.CLI.Byron.Commands (ByronCommand) +import Cardano.CLI.Commands.Debug import Cardano.CLI.Commands.Ping (PingCmd (..)) import Cardano.CLI.EraBased.Commands import Cardano.CLI.Legacy.Commands @@ -22,6 +23,7 @@ data ClientCommand = | LegacyCmds LegacyCmds | CliPingCommand PingCmd + | CliDebugCmds DebugCmds | forall a. Help ParserPrefs (ParserInfo a) | DisplayVersion diff --git a/cardano-cli/src/Cardano/CLI/Commands/Debug.hs b/cardano-cli/src/Cardano/CLI/Commands/Debug.hs new file mode 100644 index 0000000000..e746143a13 --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Commands/Debug.hs @@ -0,0 +1,8 @@ +module Cardano.CLI.Commands.Debug + ( DebugCmds (..) + ) where + +import Cardano.CLI.Commands.Debug.LogEpochState + +newtype DebugCmds = + DebugLogEpochStateCmd LogEpochStateCmdArgs diff --git a/cardano-cli/src/Cardano/CLI/Commands/Debug/LogEpochState.hs b/cardano-cli/src/Cardano/CLI/Commands/Debug/LogEpochState.hs new file mode 100644 index 0000000000..cff38428ae --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Commands/Debug/LogEpochState.hs @@ -0,0 +1,22 @@ +{-# LANGUAGE DataKinds #-} + +module Cardano.CLI.Commands.Debug.LogEpochState + ( LogEpochStateCmdArgs(..) + , Configuration + ) where + +import Cardano.Api + +import Cardano.CLI.Orphans () + +-- | A phantom type to represent the configuration file. +data Configuration + +-- | The arguments for the 'debug log-epoch-state' command. +-- +-- This command will connect to a local node and log the epoch state. +data LogEpochStateCmdArgs = LogEpochStateCmdArgs + { nodeSocketPath :: !SocketPath + , configurationFile :: !(NodeConfigFile 'In) + , outputFilePath :: !(File Configuration 'Out) + } deriving Show diff --git a/cardano-cli/src/Cardano/CLI/Options.hs b/cardano-cli/src/Cardano/CLI/Options.hs index 4b0b1656d3..b8ff620dd5 100644 --- a/cardano-cli/src/Cardano/CLI/Options.hs +++ b/cardano-cli/src/Cardano/CLI/Options.hs @@ -15,6 +15,7 @@ import Cardano.CLI.Environment (EnvCli) import Cardano.CLI.EraBased.Commands import Cardano.CLI.EraBased.Options.Common import Cardano.CLI.Legacy.Options (parseLegacyCmds) +import Cardano.CLI.Options.Debug import Cardano.CLI.Options.Ping (parsePingCmd) import Cardano.CLI.Render (customRenderHelp) import Cardano.CLI.Run (ClientCommand (..)) @@ -55,6 +56,7 @@ parseClientCommand envCli = , parseTopLevelLegacy envCli , parseByron envCli , parsePing + , parseDebug envCli , backwardsCompatibilityCommands envCli , parseDisplayVersion (opts envCli) ] @@ -71,6 +73,9 @@ parseByron mNetworkId = parsePing :: Parser ClientCommand parsePing = CliPingCommand <$> parsePingCmd +parseDebug :: EnvCli -> Parser ClientCommand +parseDebug envCli = CliDebugCmds <$> parseDebugCmds envCli + parseAnyEra :: EnvCli -> Parser ClientCommand parseAnyEra envCli = AnyEraCommand <$> pAnyEraCommand envCli diff --git a/cardano-cli/src/Cardano/CLI/Options/Debug.hs b/cardano-cli/src/Cardano/CLI/Options/Debug.hs new file mode 100644 index 0000000000..f5255ab785 --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Options/Debug.hs @@ -0,0 +1,63 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE ScopedTypeVariables #-} + +{- HLINT ignore "Use <$>" -} +{- HLINT ignore "Move brackets to avoid $" -} + +module Cardano.CLI.Options.Debug + ( parseDebugCmds + ) where + +import Cardano.Api.Shelley hiding (QueryInShelleyBasedEra (..)) + +import Cardano.CLI.Commands.Debug +import Cardano.CLI.Commands.Debug.LogEpochState +import Cardano.CLI.Environment +import Cardano.CLI.EraBased.Options.Common + +import Data.Foldable +import Options.Applicative hiding (help, str) +import qualified Options.Applicative as Opt + +parseDebugCmds :: EnvCli -> Parser DebugCmds +parseDebugCmds envCli = + Opt.hsubparser $ mconcat + [ Opt.metavar "debug commands" + , Opt.commandGroup "debug commands" + , Opt.command "debug" + $ Opt.info (pDebugCmds envCli) + $ Opt.progDesc "Debug commands" + ] + +pDebugCmds :: EnvCli -> Parser DebugCmds +pDebugCmds envCli = + asum + [ subParser "log-epoch-state" + $ Opt.info pLogEpochStateCmdArgs + $ Opt.progDesc + $ mconcat + [ "Log epoch state of a running node." + , " This command will connect to a local node and log the epoch state to a file." + , " The log file format is line delimited JSON." + , " The command will not terminate." + ] + ] + where + pLogEpochStateCmdArgs :: Parser DebugCmds + pLogEpochStateCmdArgs = + fmap DebugLogEpochStateCmd $ + LogEpochStateCmdArgs + <$> pSocketPath envCli + <*> pNodeConfigurationFileIn + <*> pFileOutDirection "out-file" "Output filepath of the log file. The log file format is line delimited JSON." + +pNodeConfigurationFileIn :: Parser (NodeConfigFile In) +pNodeConfigurationFileIn = + fmap File $ Opt.strOption $ mconcat + [ Opt.long "node-configuration-file" + , Opt.metavar "FILE" + , Opt.help "Input filepath of the node configuration file." + , Opt.completer (Opt.bashCompleter "file") + ] diff --git a/cardano-cli/src/Cardano/CLI/Options/Ping.hs b/cardano-cli/src/Cardano/CLI/Options/Ping.hs index b16cf1a45c..e903099873 100644 --- a/cardano-cli/src/Cardano/CLI/Options/Ping.hs +++ b/cardano-cli/src/Cardano/CLI/Options/Ping.hs @@ -1,5 +1,7 @@ {-# LANGUAGE TypeApplications #-} +{- HLINT ignore "Move brackets to avoid $" -} + module Cardano.CLI.Options.Ping ( parsePingCmd ) where diff --git a/cardano-cli/src/Cardano/CLI/Orphans.hs b/cardano-cli/src/Cardano/CLI/Orphans.hs new file mode 100644 index 0000000000..361a8fce4b --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Orphans.hs @@ -0,0 +1,24 @@ +{-# OPTIONS_GHC -Wno-orphans #-} + +module Cardano.CLI.Orphans + ( + ) where + +import Cardano.Api + +import qualified Cardano.Ledger.Api as L +import qualified Cardano.Ledger.Shelley.LedgerState as L + +import Data.Aeson + +-- TODO upstream this orphaned instance to the ledger +instance (L.EraTxOut ledgerera, L.EraGov ledgerera) => ToJSON (L.NewEpochState ledgerera) where + toJSON (L.NewEpochState nesEL nesBprev nesBCur nesEs nesRu nesPd _stashedAvvm)= + object + [ "currentEpoch" .= nesEL + , "priorBlocks" .= nesBprev + , "currentEpochBlocks" .= nesBCur + , "currentEpochState" .= nesEs + , "rewardUpdate" .= nesRu + , "currentStakeDistribution" .= nesPd + ] diff --git a/cardano-cli/src/Cardano/CLI/Run.hs b/cardano-cli/src/Cardano/CLI/Run.hs index 6c96b66fed..9268fc4dbd 100644 --- a/cardano-cli/src/Cardano/CLI/Run.hs +++ b/cardano-cli/src/Cardano/CLI/Run.hs @@ -18,6 +18,7 @@ import Cardano.CLI.EraBased.Run import Cardano.CLI.Legacy.Commands import Cardano.CLI.Legacy.Run (runLegacyCmds) import Cardano.CLI.Render (customRenderHelp) +import Cardano.CLI.Run.Debug import Cardano.CLI.Run.Ping (PingClientCmdError (..), renderPingClientCmdError, runPingCmd) import Cardano.CLI.Types.Errors.CmdError @@ -45,6 +46,7 @@ data ClientCommandErrors = ByronClientError ByronClientCmdError | CmdError Text CmdError | PingClientError PingClientCmdError + | DebugCmdError DebugCmdError runClientCommand :: ClientCommand -> ExceptT ClientCommandErrors IO () runClientCommand = \case @@ -56,6 +58,8 @@ runClientCommand = \case firstExceptT (CmdError (renderLegacyCommand cmds)) $ runLegacyCmds cmds CliPingCommand cmds -> firstExceptT PingClientError $ runPingCmd cmds + CliDebugCmds cmds -> + firstExceptT DebugCmdError $ runDebugCmds cmds Help pprefs allParserInfo -> runHelp pprefs allParserInfo DisplayVersion -> @@ -69,6 +73,8 @@ renderClientCommandError = \case renderByronClientCmdError err PingClientError err -> renderPingClientCmdError err + DebugCmdError err -> + renderDebugCmdError err runDisplayVersion :: ExceptT ClientCommandErrors IO () runDisplayVersion = do diff --git a/cardano-cli/src/Cardano/CLI/Run/Debug.hs b/cardano-cli/src/Cardano/CLI/Run/Debug.hs new file mode 100644 index 0000000000..72353c82dc --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Run/Debug.hs @@ -0,0 +1,24 @@ +{-# LANGUAGE LambdaCase #-} + +module Cardano.CLI.Run.Debug + ( DebugCmdError(..) + , runLogEpochStateCmd + , runDebugCmds + , renderDebugCmdError + ) where + +import Cardano.CLI.Commands.Debug +import Cardano.CLI.Run.Debug.LogEpochState + +import Control.Monad.IO.Class +import Control.Monad.Trans.Except +import Prettyprinter + +data DebugCmdError = DebugCmdFailed + +runDebugCmds :: DebugCmds -> ExceptT DebugCmdError IO () +runDebugCmds = \case + DebugLogEpochStateCmd cmd -> liftIO $ runLogEpochStateCmd cmd + +renderDebugCmdError :: DebugCmdError -> Doc ann +renderDebugCmdError DebugCmdFailed = "Debug command failed" diff --git a/cardano-cli/src/Cardano/CLI/Run/Debug/LogEpochState.hs b/cardano-cli/src/Cardano/CLI/Run/Debug/LogEpochState.hs new file mode 100644 index 0000000000..af6106b8ed --- /dev/null +++ b/cardano-cli/src/Cardano/CLI/Run/Debug/LogEpochState.hs @@ -0,0 +1,44 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Cardano.CLI.Run.Debug.LogEpochState + ( runLogEpochStateCmd + ) where + +import Cardano.Api +import qualified Cardano.Api as Api + +import Cardano.CLI.Commands.Debug.LogEpochState +import Cardano.CLI.Orphans () + +import qualified Data.Aeson as Aeson +import qualified Data.ByteString.Lazy as LBS +import qualified System.IO as IO + +runLogEpochStateCmd + :: LogEpochStateCmdArgs + -> IO () +runLogEpochStateCmd + LogEpochStateCmdArgs + { nodeSocketPath + , configurationFile + , outputFilePath = File outputFilePath + } = do + LBS.appendFile outputFilePath "" + + result <- runExceptT $ foldEpochState + configurationFile + nodeSocketPath + Api.QuickValidation + (EpochNo maxBound) + () + (\(AnyNewEpochState sbe nes) _ _ -> do + liftIO $ LBS.appendFile outputFilePath + $ shelleyBasedEraConstraints sbe (Aeson.encode nes) <> "\n" + pure ConditionNotMet + ) + + case result of + Right _ -> pure () + Left e -> IO.hPutStrLn IO.stderr $ "Error: " <> show e diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli index 7b90873625..1ed44f99c8 100644 --- a/cardano-cli/test/cardano-cli-golden/files/golden/help.cli +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help.cli @@ -10,6 +10,7 @@ Usage: cardano-cli | Legacy commands | byron | ping + | debug commands | version ) @@ -12369,6 +12370,18 @@ Usage: cardano-cli ping [-c|--count COUNT] Ping a cardano node either using node-to-node or node-to-client protocol. It negotiates a handshake and keeps sending keep alive messages. +Usage: cardano-cli debug log-epoch-state + + Debug commands + +Usage: cardano-cli debug log-epoch-state --socket-path SOCKET_PATH + --node-configuration-file FILE + --out-file FILE + + Log epoch state of a running node. This command will connect to a local node + and log the epoch state to a file. The log file format is line delimited JSON. + The command will not terminate. + Usage: cardano-cli genesis --genesis-output-dir FILEPATH --start-time POSIXSECONDS --protocol-parameters-file FILEPATH diff --git a/cardano-cli/test/cardano-cli-golden/files/golden/help/debug_log-epoch-state.cli b/cardano-cli/test/cardano-cli-golden/files/golden/help/debug_log-epoch-state.cli new file mode 100644 index 0000000000..442eb5b4f2 --- /dev/null +++ b/cardano-cli/test/cardano-cli-golden/files/golden/help/debug_log-epoch-state.cli @@ -0,0 +1,19 @@ +Usage: cardano-cli debug log-epoch-state --socket-path SOCKET_PATH + --node-configuration-file FILE + --out-file FILE + + Log epoch state of a running node. This command will connect to a local node + and log the epoch state to a file. The log file format is line delimited JSON. + The command will not terminate. + +Available options: + --socket-path SOCKET_PATH + Path to the node socket. This overrides the + CARDANO_NODE_SOCKET_PATH environment variable. The + argument is optional if CARDANO_NODE_SOCKET_PATH is + defined and mandatory otherwise. + --node-configuration-file FILE + Input filepath of the node configuration file. + --out-file FILE Output filepath of the log file. The log file format + is line delimited JSON. + -h,--help Show this help text From 2a51ce503f9e724290e4cfda56e5935dec8adae9 Mon Sep 17 00:00:00 2001 From: John Ky Date: Sat, 1 Jun 2024 10:32:33 +1000 Subject: [PATCH 5/5] Add missing merge_group trigger for shellcheck and actionlint workflows --- .github/workflows/actionlint.yml | 1 + .github/workflows/shellcheck.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index d4b3873196..26aed8aead 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -1,6 +1,7 @@ name: Actionlint on: + merge_group: pull_request: jobs: diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index 6bdb89c27b..a5d0fa60f7 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -7,6 +7,7 @@ name: Shellcheck # is consistent with the one of developers. on: + merge_group: pull_request: jobs: