Skip to content

Commit cce84c1

Browse files
committed
Compare the resolved configuration and flag discrepancies
1 parent 2f4d576 commit cce84c1

5 files changed

Lines changed: 604 additions & 2 deletions

File tree

cardano-node/app/cardano-node.hs

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,32 @@
44
{-# LANGUAGE RankNTypes #-}
55
{-# LANGUAGE TemplateHaskell #-}
66

7+
import qualified Cardano.Configuration as Cfg
8+
import qualified Cardano.Configuration.CliArgs as CliArgs
9+
import qualified Cardano.Configuration.Commands as Cmds
710
import qualified Cardano.Crypto.Init as Crypto
811
import Cardano.Git.Rev (gitRev)
9-
import Cardano.Node.Configuration.POM (PartialNodeConfiguration (..))
12+
import Cardano.Node.Configuration.CardanoConfigAdapter
13+
(cardanoConfigToNodeConfiguration)
14+
import Cardano.Node.Configuration.CardanoConfigCompare
15+
(compareConfigurations)
16+
import Cardano.Node.Configuration.POM (NodeConfiguration (..),
17+
PartialNodeConfiguration (..), defaultPartialNodeConfiguration,
18+
makeNodeConfiguration, parseNodeConfigurationFP)
1019
import Cardano.Node.Handlers.TopLevel
1120
import Cardano.Node.Parsers (nodeCLIParser)
1221
import Cardano.Node.Run (runNode)
1322
import Cardano.Node.Tracing.Documentation (TraceDocumentationCmd (..),
1423
parseTraceDocumentationCmd, runTraceDocumentationCmd)
24+
import Cardano.Node.Types (ConfigYamlFilePath (..))
1525

16-
import Data.Monoid (Last (getLast))
26+
import Data.Monoid (Last (..))
1727
import qualified Data.Text as Text
1828
import qualified Data.Text.IO as Text
1929
import Data.Version (showVersion)
2030
import Options.Applicative
2131
import qualified Options.Applicative as Opt
32+
import System.Exit (exitFailure)
2233
import System.Info (arch, compilerName, compilerVersion, os)
2334
import System.IO (hPutStrLn, stderr)
2435

@@ -37,6 +48,7 @@ main = do
3748
runNode args
3849
TraceDocumentation tdc -> runTraceDocumentationCmd tdc
3950
VersionCmd -> runVersionCommand
51+
ConfigCmd act -> act
4052

4153
where
4254
p = Opt.prefs Opt.showHelpOnEmpty
@@ -56,6 +68,7 @@ main = do
5668
Opt.info (fmap RunCmd nodeCLIParser
5769
<|> fmap TraceDocumentation parseTraceDocumentationCmd
5870
<|> parseVersionCmd
71+
<|> fmap ConfigCmd configSubcommands
5972
<**> helper)
6073

6174
( Opt.fullDesc <>
@@ -66,6 +79,7 @@ main = do
6679
data Command = RunCmd PartialNodeConfiguration
6780
| TraceDocumentation TraceDocumentationCmd
6881
| VersionCmd
82+
| ConfigCmd (IO ())
6983

7084
-- Yes! A --version flag or version command. Either guess is right!
7185
parseVersionCmd :: Parser Command
@@ -105,3 +119,84 @@ command' c descr p =
105119
[ command c (info (p <**> helper) $ mconcat [ progDesc descr ])
106120
, metavar c
107121
]
122+
123+
-- cardano-config subcommands --------------------------------------------------
124+
125+
-- | The @migrate@, @schema@ and @resolve@ subcommands, spliced from the shared
126+
-- @cardano-config:commands@ sublibrary. @migrate@ and @schema@ are
127+
-- cardano-config's own commands, unchanged; @resolve@ is a node-specific variant
128+
-- (see 'resolveDualCommand') that additionally cross-checks the node's own parser
129+
-- against cardano-config's.
130+
configSubcommands :: Parser (IO ())
131+
configSubcommands =
132+
Opt.hsubparser
133+
( Opt.commandGroup "Configuration commands:"
134+
<> Cmds.migrateCommand
135+
<> Cmds.schemaCommand
136+
<> resolveDualCommand
137+
)
138+
139+
-- | A node-specific @resolve@: resolve the configuration with cardano-config
140+
-- (printing the result as YAML, exactly like cardano-config's own @resolve@),
141+
-- then re-resolve the same configuration with the node's own POM parser and
142+
-- report any discrepancies between the two. Exits non-zero when they disagree,
143+
-- so it doubles as a CI parity check while the node still has two parsers.
144+
resolveDualCommand :: Mod CommandFields (IO ())
145+
resolveDualCommand =
146+
command "resolve"
147+
( info
148+
(runDualResolve <$> Cmds.resolveOptionsParser)
149+
( progDesc
150+
( "Resolve a cardano-node configuration (defaults + file + CLI) with both the "
151+
<> "node and cardano-config parsers, print the result as YAML, and report any "
152+
<> "discrepancies between the two parsers (exit non-zero if they disagree)."
153+
)
154+
)
155+
)
156+
157+
runDualResolve :: Cmds.ResolveOptions -> IO ()
158+
runDualResolve resolveOpts@(Cmds.ResolveOptions cli _geneses) = do
159+
-- Print the resolved configuration using cardano-config's own renderer (which
160+
-- honours --with-geneses); this also terminates via 'die' if resolution fails.
161+
Cmds.runResolveCommand resolveOpts
162+
-- Cross-check: resolve the same inputs with the node's POM parser and diff.
163+
discrepancies <- resolveDiscrepancies cli
164+
case discrepancies of
165+
[] ->
166+
putStrLn "resolve: the node and cardano-config parsers agree on the resolved configuration."
167+
ds -> do
168+
hPutStrLn stderr $
169+
"resolve: " <> show (length ds)
170+
<> " discrepancy(ies) between the node and cardano-config parsers:"
171+
mapM_ (hPutStrLn stderr . (" - " <>)) ds
172+
exitFailure
173+
174+
-- | Resolve the configuration file (+ CLI) both ways and return the divergences.
175+
-- The node (POM) side takes its CLI-supplied, file-absent fields (topology /
176+
-- database / protocol files / socket) from the shared cardano-config resolution,
177+
-- so the diff reflects how the two parsers read the configuration FILE (plus the
178+
-- documented adapter gaps) rather than an independent — and necessarily
179+
-- asymmetric — CLI reverse-mapping.
180+
resolveDiscrepancies :: Cfg.CliArgs -> IO [String]
181+
resolveDiscrepancies cli = do
182+
(fileCfg, _warns) <- Cfg.parseConfigurationFiles configFp
183+
case Cfg.resolveConfiguration cli fileCfg of
184+
Left err -> pure ["cardano-config failed to resolve the configuration: " <> show err]
185+
Right (cfgNc, _) ->
186+
case cardanoConfigToNodeConfiguration cfgNc of
187+
Left adaptErr -> pure ["cardano-config configuration could not be adapted: " <> adaptErr]
188+
Right adaptedNc -> do
189+
filePartial <- parseNodeConfigurationFP (Just (ConfigYamlFilePath configFp))
190+
let withCli =
191+
(defaultPartialNodeConfiguration <> filePartial)
192+
{ pncConfigFile = Last (Just (ConfigYamlFilePath configFp))
193+
, pncTopologyFile = Last (Just (ncTopologyFile adaptedNc))
194+
, pncDatabaseFile = Last (Just (ncDatabaseFile adaptedNc))
195+
, pncProtocolFiles = Last (Just (ncProtocolFiles adaptedNc))
196+
, pncSocketConfig = Last (Just (ncSocketConfig adaptedNc))
197+
}
198+
case makeNodeConfiguration withCli of
199+
Left err -> pure ["node parser (makeNodeConfiguration) failed: " <> err]
200+
Right pomNc -> pure (compareConfigurations pomNc adaptedNc)
201+
where
202+
configFp = CliArgs.configFilePath cli

cardano-node/cardano-node.cabal

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ library
6060
hs-source-dirs: src
6161

6262
exposed-modules: Cardano.Node.Configuration.CardanoConfigAdapter
63+
Cardano.Node.Configuration.CardanoConfigCompare
6364
Cardano.Node.Configuration.NodeAddress
6465
Cardano.Node.Configuration.POM
6566
Cardano.Node.Configuration.LedgerDB
@@ -191,6 +192,7 @@ library
191192
, trace-resources ^>= 0.2.4
192193
, transformers
193194
, transformers-except
195+
, tree-diff
194196
, typed-protocols:{typed-protocols, stateful} >= 1.2
195197
, yaml
196198

@@ -210,6 +212,8 @@ executable cardano-node
210212
autogen-modules: Paths_cardano_node
211213

212214
build-depends: base
215+
, cardano-config
216+
, cardano-config:commands
213217
, cardano-crypto-class
214218
, cardano-git-rev
215219
, cardano-node
@@ -244,6 +248,18 @@ test-suite db-synthesizer-test
244248
, tasty
245249
, tasty-hunit
246250

251+
test-suite cardano-config-compare-test
252+
import: project-config
253+
hs-source-dirs: test/cardano-config-compare
254+
main-is: Main.hs
255+
type: exitcode-stdio-1.0
256+
257+
build-depends: base
258+
, cardano-config
259+
, cardano-node
260+
, tasty
261+
, tasty-hunit
262+
247263
test-suite cardano-node-test
248264
import: project-config
249265
, maybe-unix

0 commit comments

Comments
 (0)