Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix CLI port argument bug. #407

Merged
merged 6 commits into from
Jun 13, 2019
Merged

Fix CLI port argument bug. #407

merged 6 commits into from
Jun 13, 2019

Conversation

paweljakubas
Copy link
Contributor

@paweljakubas paweljakubas commented Jun 12, 2019

Issue Number

#401

Overview

  • I have added integration tests illustrating the problem
  • I have changed server by introducing PortOption datatype and introduced logic decided by team discussion
  • I have adopted exe cli

Comments

Copy link
Member

@jonathanknowles jonathanknowles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @paweljakubas

Thanks for looking at this issue!

I think this PR is generally good, though I also think there are some areas that we should fix. I've highlighted these areas in comments, along with some suggestions. I'd be interested to hear your thoughts.

Cheers!

@@ -139,15 +140,19 @@ import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Network.Wai.Handler.Warp as Warp


data PortOption = RandomPort | ExactPort (Maybe Warp.Port)
deriving Show
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By using the Maybe type here, I think it's not obvious what the semantics are if we specify ExactPort Nothing.

Perhaps we can make this clearer by using the following options:

-- | Specifies a port on which the application server will listen.
data PortOption
    = DefaultPort
        -- ^ Listen on the default port (see 'defaultPort').
    | RandomPort
        -- ^ Select an unused port at random on which to listen.
    | SpecificPort Warp.Port
        -- ^ Listen on a specific port. 
    deriving Show

And then separately define:

-- | The default port on which to listen. The application server will listen
--   on this port if 'start' is called with 'DefaultPort'.
defaultPort :: Warp.Port
defaultPort = 9080

What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been addressed 👍

lib/core/src/Cardano/Wallet/Api/Server.hs Outdated Show resolved Hide resolved
@@ -762,6 +769,8 @@ createWalletViaCLI args mnemonics secondFactor passphrase = do
err <- TIO.hGetContents stderr
return (c, T.unpack out, err)



Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -139,15 +140,19 @@ import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Network.Wai.Handler.Warp as Warp


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T.unpack err `shouldContain` "Ok.\n"
out `shouldContain` walletName
checkSimpleCreateWallet
(Just "1337")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the relevance of the number 1337? Is it an arbitrarily-chosen number, or should it be the same as a number somewhere else?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid the hard-coded number here indeed. Or at the very least, avoid repeating it through the whole file 🙏

lib/http-bridge/test/integration/Main.hs Outdated Show resolved Hide resolved
lib/http-bridge/test/integration/Main.hs Outdated Show resolved Hide resolved
@jonathanknowles jonathanknowles changed the title port arg bug Fix CLI port argument bug. Jun 13, 2019
@rvl rvl force-pushed the paweljakubas/401/port-arg-bug branch from fb2f74a to 160a1dc Compare June 13, 2019 06:22
exe/launcher/Main.hs Outdated Show resolved Hide resolved
] ++ dbArg
] ++ portArg ++ bridgePortArg ++ dbArg
portArg = maybe ["--random-port"] (\p -> ["--port", T.unpack (toText p)]) wp
bridgePortArg = ["--bridge-port", T.unpack (toText np)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bridgePortArg = ["--bridge-port", T.unpack (toText np)]
args = mconcat
[ [ "server" ]
, [ "--network", if net == "local" then "testnet" else net ]
, maybe ["--random-port"] (\p -> ["--port", showT p]) wp
, [ "--bridge-port", showT np ]
]
showT = T.unpack . toText

@@ -140,7 +140,7 @@ and can be run "offline". (e.g. 'generate mnemonic')
⚠️ Options are positional (--a --b is not equivalent to --b --a) ! ⚠️

Usage:
cardano-wallet server [--network=STRING] [--port=INT] [--bridge-port=INT] [--database=FILE]
cardano-wallet server [--network=STRING] [--port=INT] [--random-port] [--bridge-port=INT] [--database=FILE]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here about --port=INT and --random-port being mutually exclusive.

T.unpack err `shouldContain` "Ok.\n"
out `shouldContain` walletName
checkSimpleCreateWallet
(Just "1337")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid the hard-coded number here indeed. Or at the very least, avoid repeating it through the whole file 🙏

Just port ->
[ "exec", "--", "cardano-wallet"
, "wallet", "create", "--port", port
] ++ args
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
] ++ args
let portArg =
maybe [] (\p -> ["--port", p]) portM
let fullArgs =
[ "exec", "--", "cardano-wallet", "wallet", "create" ]
++ portArg ++ args

db <- MVar.newDBLayer
let tl = HttpBridge.newTransactionLayer
wallet <- newWalletLayer nullTracer block0 db nl tl
Server.start (putMVar port) walletListen wallet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea and a good way to test that the random port binding works as expected 🎉

@@ -158,6 +168,8 @@ main = hspec $ do
-- some places where it's less annoying.
(UseHandle h)

mkBaseUrl port = "http://localhost:" <> T.pack (show port) <> "/"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably need toText here instead of show since we have port :: Port I believe.

@@ -71,13 +77,17 @@ main = hspec $ do
describe "Cardano.WalletSpec" Wallet.spec
describe "Cardano.Wallet.HttpBridge.NetworkSpec" HttpBridge.spec
describe "CLI commands not requiring bridge" MnemonicsCLI.spec
beforeAll startCluster $ afterAll killCluster $ after tearDown $ do
beforeAll (startCluster ListenOnRandomPort) $ afterAll killCluster $ after tearDown $ do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be a problem for the API spec as long as we sort out the baseUrl in the manager, but the CLI specs also need to know about the port; So we probably gotta add it to the Context I believe.

Copy link
Contributor Author

@paweljakubas paweljakubas Jun 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I change it from IO () to IO Warp.Port in start Server in Cardano.Wallet.Api.Server now we need to accommodate it in integration tests. And we will be able to use it when random port mode is ON in integration tests


let defaultPort = 8090
beforeAll (startCluster (ListenOnPort defaultPort)) $ afterAll killCluster $ after tearDown $ do
describe "Port tests using wallets CLI" (WalletsCLI.specPorts defaultPort)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the rationale for making this one completely separated ? It's quite heavy to start a whole new cluster. Perhaps what we really need here is simply to start another wallet server listening on given port. That can be tested without requiring a new cluster.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. That'd also, sort of, test the case of two wallet's attached to a single server.

-> String
-> (ExitCode -> IO ())
-> (String -> IO ())
-> (String -> IO ())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not found of this helper, it's really "stringly-typed" and is more cryptic than readable IMO. I'd rather inline it in all the test above as it reads better inlined.

@@ -118,16 +123,16 @@ nodeHttpBridgeOn stateDir port net =
] ++ networkArg
networkArg = maybe [] (\d -> ["--networks-dir", d]) stateDir

walletOn :: Maybe FilePath -> Port "Wallet" -> Port "Node" -> String -> Command
walletOn :: Maybe FilePath -> Maybe (Port "Wallet") -> Port "Node" -> String -> Command
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is now too long (https://github.com/input-output-hk/cardano-wallet/wiki/Coding-Standards#limit-line-length-to-80-characters).

Suggest:

Suggested change
walletOn :: Maybe FilePath -> Maybe (Port "Wallet") -> Port "Node" -> String -> Command
walletOn
:: Maybe FilePath
-> Maybe (Port "Wallet")
-> Port "Node"
-> String
-> Command

@@ -170,17 +179,17 @@ startOnSocket settings socket wl = Warp.runSettingsSocket settings socket
application :: Application
application = serve (Proxy @("v2" :> Api t)) server

-- | Run an action with a TCP socket bound to a port. If no port is specified,
-- | Run an action with a TCP socket bound to a port. If random port is chosen
-- then an unused port will be selected at random.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment sounds a bit tautological. Suggest:

Suggested change
-- then an unused port will be selected at random.
-- | Run an action with a TCP socket bound to a port specified by the `Listen`
-- parameter.

describe "Wallets API endpoint tests" Wallets.spec
describe "Transactions API endpoint tests" Transactions.spec
describe "Addresses API endpoint tests" Addresses.spec
describe "Wallets CLI tests" WalletsCLI.spec
describe "Transactions CLI tests" TransactionsCLI.spec
describe "Addresses CLI tests" AddressesCLI.spec

let defaultPort = 8090
beforeAll (startCluster (ListenOnPort defaultPort)) $ afterAll killCluster $ after tearDown $ do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(c, out, err) <- createWalletViaCLI [walletName] mnemonics "\n" passphrase portM
exitCodeCheck c
errCheck (T.unpack err)
outCheck out
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this check just landed here in this method, because it was there in the code in the first place :) Actually it is quite poor and I was planning to add more detailed checks (like here: https://github.com/input-output-hk/cardano-wallet/blob/master/lib/core/test/integration/Test/Integration/Scenario/CLI/Transactions.hs#L92-L97) but didn't get there yet for Wallets.sh. (ofc that's not in scope of this pr)

For that matter, I'd be rather for separating action and assertion not to be in a single method (but perhaps, that's just a personal preference)

Rationale here is to simplify a bit the requirement and busy work with the launcher that
we're going to remove / merge into the wallet cli soon.
@KtorZ KtorZ force-pushed the paweljakubas/401/port-arg-bug branch from d1c9f90 to eb32f30 Compare June 13, 2019 16:13
Copy link
Member

@KtorZ KtorZ left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM. I've picked up the PR to resolve issues with the integration tests and reworked a bit the way integration scenario receive their corresponding port and made sure to thoroughly test every CLI commands.

@KtorZ KtorZ dismissed jonathanknowles’s stale review June 13, 2019 16:16

comments have been addressed or are now outdated 👍

@KtorZ
Copy link
Member

KtorZ commented Jun 13, 2019

@piotr-iohk May you have another quick look at the PR 🙏 , especially the integration test part. I used some generic-lens magic to avoid making numerous changes to the rest of the code. It's pretty neat in the end and enables a great coverage for all commands of the CLI:

--port CLI tests
    with default port
      PORT_01 - Can't reach server with wrong port (wallet list)
      PORT_01 - Can't reach server with wrong port (wallet create)
      PORT_01 - Can't reach server with wrong port (wallet get)
      PORT_01 - Can't reach server with wrong port (wallet delete)
      PORT_01 - Can't reach server with wrong port (wallet update)
      PORT_01 - Can't reach server with wrong port (transction create)
      PORT_01 - Can't reach server with wrong port (address list)
      PORT_02 - Can omit --port when server uses default port (wallet list)
      PORT_02 - Can omit --port when server uses default port (wallet create)
      PORT_02 - Can omit --port when server uses default port (wallet get)
      PORT_02 - Can omit --port when server uses default port (wallet delete)
      PORT_02 - Can omit --port when server uses default port (wallet update)
      PORT_02 - Can omit --port when server uses default port (transaction create)
      PORT_02 - Can omit --port when server uses default port (address list)
    with specified port
      PORT_01 - Can't reach server with wrong port (wallet list)
      PORT_01 - Can't reach server with wrong port (wallet create)
      PORT_01 - Can't reach server with wrong port (wallet get)
      PORT_01 - Can't reach server with wrong port (wallet delete)
      PORT_01 - Can't reach server with wrong port (wallet update)
      PORT_01 - Can't reach server with wrong port (transction create)
      PORT_01 - Can't reach server with wrong port (address list)
    with random port
      PORT_01 - Can't reach server with wrong port (wallet list)
      PORT_01 - Can't reach server with wrong port (wallet create)
      PORT_01 - Can't reach server with wrong port (wallet get)
      PORT_01 - Can't reach server with wrong port (wallet delete)
      PORT_01 - Can't reach server with wrong port (wallet update)
      PORT_01 - Can't reach server with wrong port (transction create)
      PORT_01 - Can't reach server with wrong port (address list)
      PORT_03 - random port != default port
      PORT_03 - Cannot omit --port when server uses random port (wallet list)
      PORT_03 - Cannot omit --port when server uses random port (wallet create)
      PORT_03 - Cannot omit --port when server uses random port (wallet get)
      PORT_03 - Cannot omit --port when server uses random port (wallet delete)
      PORT_03 - Cannot omit --port when server uses random port (wallet update)
      PORT_03 - Cannot omit --port when server uses random port (transaction create)
      PORT_03 - Cannot omit --port when server uses random port (address list)

let me know.

@KtorZ KtorZ force-pushed the paweljakubas/401/port-arg-bug branch from eb32f30 to 264c31f Compare June 13, 2019 16:42
@KtorZ KtorZ merged commit cb7744e into master Jun 13, 2019
@KtorZ KtorZ deleted the paweljakubas/401/port-arg-bug branch June 13, 2019 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants