packages feed

net-spider-cli (empty) → 0.1.0.0

raw patch · 13 files changed

+397/−0 lines, 13 filesdep +aesondep +basedep +doctestsetup-changed

Dependencies added: aeson, base, doctest, doctest-discover, greskell-core, hashable, hspec, net-spider, net-spider-cli, optparse-applicative, text

Files

+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for net-spider-cli++## 0.1.0.0  -- 2019-08-04++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2019, Toshio Ito++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Toshio Ito nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,6 @@+# net-spider-cli+++## Author++Toshio Ito <debug.ito@gmail.com>
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ net-spider-cli.cabal view
@@ -0,0 +1,71 @@+name:                   net-spider-cli+version:                0.1.0.0+author:                 Toshio Ito <debug.ito@gmail.com>+maintainer:             Toshio Ito <debug.ito@gmail.com>+license:                BSD3+license-file:           LICENSE+synopsis:               CLI option parsers for NetSpider objects+description:            CLI option parsers for NetSpider objects. See "NetSpider.CLI".+category:               Database+cabal-version:          >= 1.10+build-type:             Simple+extra-source-files:     README.md, ChangeLog.md+homepage:               https://github.com/debug-ito/net-spider+bug-reports:            https://github.com/debug-ito/net-spider/issues++library+  default-language:     Haskell2010+  hs-source-dirs:       src+  ghc-options:          -Wall -fno-warn-unused-imports+  default-extensions:   OverloadedStrings, StrictData+  -- other-extensions:     +  exposed-modules:      NetSpider.CLI,+                        NetSpider.CLI.Spider,+                        NetSpider.CLI.Snapshot+  -- other-modules:        +  build-depends:        base >=4.11.1.0 && <4.13,+                        net-spider >=0.3.1.0 && <0.4,+                        optparse-applicative >=0.14.3.0 && <0.16,+                        aeson >=1.2.4 && <1.5,+                        hashable >=1.2.6.1 && <1.3,+                        greskell-core >=0.1.2.4 && <0.2,+                        text >=1.2.2.2 && <1.3++-- executable net-spider-cli+--   default-language:     Haskell2010+--   hs-source-dirs:       app+--   main-is:              Main.hs+--   ghc-options:          -Wall -fno-warn-unused-imports+--   -- other-modules:        +--   default-extensions:   OverloadedStrings, StrictData+--   -- other-extensions:     +--   build-depends:        base++test-suite spec+  type:                 exitcode-stdio-1.0+  default-language:     Haskell2010+  hs-source-dirs:       test+  ghc-options:          -Wall -fno-warn-unused-imports "-with-rtsopts=-M512m"+  main-is:              Spec.hs+  default-extensions:   OverloadedStrings, StrictData+  -- other-extensions:     +  other-modules:        NetSpider.CLI.SpiderSpec,+                        NetSpider.CLI.SnapshotSpec,+                        NetSpider.CLI.TestCommon+  build-depends:        base, net-spider-cli, net-spider, optparse-applicative,+                        hspec >=2.4.4+                        ++test-suite doctest+  type:                 exitcode-stdio-1.0+  default-language:     Haskell2010+  hs-source-dirs:       test+  ghc-options:          -Wall -fno-warn-unused-imports "-with-rtsopts=-M512m"+  main-is:              DocTest.hs+  build-depends:        base,+                        doctest >=0.13 && <0.17,+                        doctest-discover >=0.1.0.7 && <0.3++source-repository head+  type:                 git+  location:             https://github.com/debug-ito/net-spider.git
+ src/NetSpider/CLI.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE OverloadedStrings, StrictData #-}+-- |+-- Module: NetSpider.CLI+-- Description: CLI option parsers for NetSpider objects+-- Maintainer: Toshio Ito <debug.ito@gmail.com>+--+-- This module defines CLI option parsers for NetSpider objects, such+-- as configuration for Spider object and a query for a snapshot+-- graph. The option parsers are based on 'Parser' from+-- "Options.Applicative" (optparse-applicative package), so you can+-- easily integrade those parsers into the CLI option parser of your+-- own executable program.+module NetSpider.CLI+       ( module NetSpider.CLI.Spider,+         module NetSpider.CLI.Snapshot+       ) where++import Options.Applicative (Parser)++import NetSpider.CLI.Spider+import NetSpider.CLI.Snapshot
+ src/NetSpider/CLI/Snapshot.hs view
@@ -0,0 +1,81 @@+-- |+-- Module: NetSpider.CLI.Snapshot+-- Description: CLI option parser for Query for snapshot graphs+-- Maintainer: Toshio Ito <toshio9.ito@toshiba.co.jp>+--+-- This module defines CLI option parser for 'Q.Query' for snapshot+-- graphs.+module NetSpider.CLI.Snapshot+  ( parserSnapshotQuery,+    SnapshotConfig(..)+  ) where++import Control.Applicative ((<$>), (<*>), many)+import qualified NetSpider.Query as Q+import qualified Options.Applicative as Opt+import NetSpider.Interval (interval, parseTimeIntervalEnd)++-- | Configuration for option parser for Snapshot 'Q.Query'.+data SnapshotConfig n na fla sla =+  SnapshotConfig+  { nodeIDReader :: Opt.ReadM n,+    -- ^ Parser that reads a CLI option to generate a node ID.+    basisSnapshotQuery :: Q.Query n na fla sla,+    -- ^ Basis for queries for snapshot graphs. Fields in this basis+    -- are overwritten by CLI options.+    startsFromAsArguments :: Bool+    -- ^ If 'True', the 'Q.startsFrom' field is read from CLI+    -- arguments. If 'False', arguments are not parsed. In either+    -- case, \"-s\" option is always parsed to generate+    -- 'Q.startsFrom'.+  }++-- | CLI option parser for 'Q.Query'.+parserSnapshotQuery :: SnapshotConfig n na fla sla+                    -> Opt.Parser (Q.Query n na fla sla)+parserSnapshotQuery conf = fmap fromParsedElement the_parser+  where+    basis = basisSnapshotQuery conf+    fromParsedElement (sf, ti) = basis { Q.startsFrom = sf, Q.timeInterval = ti }+    the_parser = (,) <$> ((++) <$> pStartsFrom <*> pStartsFromArgs) <*> pTimeInterval+    rNodeID = nodeIDReader conf+    nodeID_metavar = "NODE-ID"+    pStartsFrom = many $ Opt.option rNodeID $ mconcat+                  [ Opt.short 's',+                    Opt.long "starts-from",+                    Opt.help "ID of a node from which the Spider starts traversing the history graph. You can specify this option multiple times.",+                    Opt.metavar nodeID_metavar+                  ]+    pStartsFromArgs = if not $ startsFromAsArguments conf+                      then pure []+                      else many $ Opt.argument rNodeID $ mconcat+                           [ Opt.help $ "Same as -s option.",+                             Opt.metavar $ nodeID_metavar+                           ]+    pTimeInterval = interval <$> pTimeLower <*> pTimeUpper+    pTimeLower = Opt.option (Opt.eitherReader parseTimeIntervalEnd) $ mconcat+                 [ Opt.short 'f',+                   Opt.long "time-from",+                   Opt.help ( "Lower bound of query timestamp. "+                              ++ "Local findings with timestamp newer than this value are used to create the snapshot graph. "+                              ++ "ISO 8601 format is used for timestamps (e.g. `2019-03-22T10:20:12+09:00`). "+                              ++ "The timezone is optional. "+                              ++ "By default, the lower bound is inclusive. "+                              ++ "Add prefix 'x' to make it exclusive (e.g. `x2019-03-22T10:20:12+09:00`). "+                              ++ "Prefix of 'i' explicitly mark the lower bound is inclusive. "+                              ++ "Special value `x-inf` indicates there is no lower bound. " +                              ++ "Default: x-inf"),+                   Opt.metavar "TIMESTAMP",+                   Opt.value (Q.NegInf, False)+                 ]+    pTimeUpper = Opt.option (Opt.eitherReader parseTimeIntervalEnd) $ mconcat+                 [ Opt.short 't',+                   Opt.long "time-to",+                   Opt.help ( "Upper bound of query timestamp. "+                              ++ "Local findings with timestamp older than this value are used to create the snapshot graph. "+                              ++ "See --time-from for format of timestamps. "+                              ++ "Special value `x+inf` indicates there is no upper bound. " +                              ++ "Default: x+inf"),+                   Opt.metavar "TIMESTAMP",+                   Opt.value (Q.PosInf, False)+                 ]
+ src/NetSpider/CLI/Spider.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE OverloadedStrings, StrictData #-}+-- |+-- Module: NetSpider.CLI.Spider+-- Description: CLI option parser for Spider's Config+-- Maintainer: Toshio Ito <toshio9.ito@toshiba.co.jp>+--+-- This module define CLI option parser for 'SpiderConfig'.+module NetSpider.CLI.Spider+  ( parserSpiderConfig,+    SpiderConfig+  ) where++import Control.Applicative ((<$>), (<*>), many, pure)+import Data.Greskell.Greskell (toGremlin)+import Data.Monoid (mconcat)+import Data.Text (unpack)+import qualified NetSpider.Spider.Config as SConf+import qualified NetSpider.Spider as Sp+import qualified Options.Applicative as Opt++-- | 'SConf.Config' of the Spider.+type SpiderConfig = SConf.Config++-- | Command-line option parser for 'SConf.Config' of 'Spider'.+parserSpiderConfig :: Opt.Parser (SpiderConfig n na fla)+parserSpiderConfig =+  SConf.Config <$> host <*> port <*> node_id_key <*> log_thresh+  where+    host = Opt.strOption $ mconcat+           [ Opt.long "host",+             Opt.help "Hostname or address of Gremlin Server",+             Opt.metavar "HOSTNAME",+             Opt.value "localhost",+             Opt.showDefault+           ]+    port = Opt.option Opt.auto $ mconcat+           [ Opt.long "port",+             Opt.help "Port number of Gremlin Server WebSocket endpoint",+             Opt.metavar "PORT",+             Opt.value 8182,+             Opt.showDefault+           ]+    node_id_key = Opt.strOption $ mconcat+                  [ Opt.long "node-id-key",+                    Opt.help "Name of vertex attriute that stores Node ID.",+                    Opt.metavar "KEY",+                    Opt.value "@node_id",+                    Opt.showDefaultWith (unpack . toGremlin)+                  ]+    log_thresh = fmap (logLevelFromVerbosity . length) $ many $ Opt.flag' () $ mconcat+                 [ Opt.short 'v',+                   Opt.long "verbose",+                   Opt.help "Verbose log output. Specify multiple times to make it more verbose."+                 ]++logLevelFromVerbosity :: Int -> SConf.LogLevel+logLevelFromVerbosity 2 = SConf.LevelDebug+logLevelFromVerbosity 1 = SConf.LevelInfo+logLevelFromVerbosity _ = SConf.LevelWarn
+ test/DocTest.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF doctest-discover #-}
+ test/NetSpider/CLI/SnapshotSpec.hs view
@@ -0,0 +1,68 @@+module NetSpider.CLI.SnapshotSpec (main,spec) where++import NetSpider.Interval (interval, Extended(..))+import NetSpider.Query+  ( startsFrom, defQuery, timeInterval,+    foundNodePolicy, policyAppend+  )+import NetSpider.Timestamp (fromEpochMillisecond)+import qualified Options.Applicative as Opt+import Test.Hspec++import NetSpider.CLI.TestCommon (runP)+import NetSpider.CLI.Snapshot (SnapshotConfig(..), parserSnapshotQuery)++defConfig :: SnapshotConfig Int () () ()+defConfig =+  SnapshotConfig+  { nodeIDReader = Opt.auto,+    basisSnapshotQuery = (defQuery []) { foundNodePolicy = policyAppend },+    startsFromAsArguments = False+  }++main :: IO ()+main = hspec spec++spec :: Spec+spec = describe "parserSnapshotQuery" $ do+  specify "default" $ do+    let (Right got) = runP (parserSnapshotQuery defConfig) []+    startsFrom got `shouldBe` []+    timeInterval got `shouldBe` interval (NegInf, False) (PosInf, False)+    foundNodePolicy got `shouldBe` policyAppend+  specify "time-from" $ do+    let (Right got) = runP (parserSnapshotQuery defConfig)+                      ["--time-from", "2019-02-19T11:12:00"]+    timeInterval got `shouldBe`+      interval (Finite $ fromEpochMillisecond 1550574720000, True)+               (PosInf, False)+  specify "time-to with exclusive" $ do+    let (Right got) = runP (parserSnapshotQuery defConfig)+                      ["--time-to", "x2017-12-20T19:22:02"]+    timeInterval got `shouldBe`+      interval (NegInf, False)+               (Finite $ fromEpochMillisecond 1513797722000, False)+  specify "both time-from and time-to with inclusive" $ do+    let (Right got) = runP (parserSnapshotQuery defConfig)+                      ["-f", "i2018-10-11T14:13:33", "-t", "i2018-10-11T14:13:50.332"]+    timeInterval got `shouldBe`+      interval (Finite $ fromEpochMillisecond 1539267213000, True)+               (Finite $ fromEpochMillisecond 1539267230332, True)+  specify "explicit infinity" $ do+    let (Right got) = runP (parserSnapshotQuery defConfig)+                      ["--time-from", "-inf", "--time-to", "+inf"]+    timeInterval got `shouldBe` interval (NegInf, True) (PosInf, True)+  specify "multiple starts-from" $ do+    let (Right got) = runP (parserSnapshotQuery defConfig)+                      ["-s", "10", "-s", "12", "-s", "15"]+    startsFrom got `shouldBe` [10,12,15]+  let argsConfig = defConfig { startsFromAsArguments = True }+  specify "startsFromAsArguments" $ do+    let (Right got) = runP (parserSnapshotQuery argsConfig)+                      ["143", "200", "473","21"]+    startsFrom got `shouldBe` [143, 200, 473, 21]+  specify "startsFromAsArguments - -s still enabled" $ do+    let (Right got) = runP (parserSnapshotQuery argsConfig)+                      ["90", "-s", "181"]+    startsFrom got `shouldBe` [181, 90]+
+ test/NetSpider/CLI/SpiderSpec.hs view
@@ -0,0 +1,31 @@+module NetSpider.CLI.SpiderSpec (main,spec) where++import Data.Monoid (mempty)+import NetSpider.Spider.Config (Config(..), LogLevel(..))+import Test.Hspec++import NetSpider.CLI.Spider (parserSpiderConfig)++import NetSpider.CLI.TestCommon (runP)++main :: IO ()+main = hspec spec++spec :: Spec+spec = describe "parserSpiderConfig" $ do+  specify "host and port" $ do+    let (Right sconf) = runP parserSpiderConfig+                        [ "--host", "foo.example.com",+                          "--port", "18822",+                          "--node-id-key", "@foo"+                        ]+    wsHost sconf `shouldBe` "foo.example.com"+    wsPort sconf `shouldBe` 18822+    nodeIdKey sconf `shouldBe` "@foo"+  specify "verbosity" $ do+    let (Right warn) = runP parserSpiderConfig []+        (Right info) = runP parserSpiderConfig ["-v"]+        (Right debug) = runP parserSpiderConfig ["-vv"]+    logThreshold warn `shouldBe` LevelWarn+    logThreshold info `shouldBe` LevelInfo+    logThreshold debug `shouldBe` LevelDebug
+ test/NetSpider/CLI/TestCommon.hs view
@@ -0,0 +1,21 @@+-- |+-- Module: NetSpider.CLI.TestCommon+-- Description: common utils for test+-- Maintainer: Toshio Ito <toshio9.ito@toshiba.co.jp>+--+-- +module NetSpider.CLI.TestCommon+  ( runP+  ) where++import qualified Options.Applicative as Opt++runP :: Opt.Parser a -> [String] -> Either String a+runP p args = toEither $ Opt.execParserPure prefs pinfo args+  where+    prefs = Opt.prefs mempty+    pinfo = Opt.info p mempty+    toEither (Opt.Success a) = Right a+    toEither (Opt.Failure f) = Left $ show f+    toEither (Opt.CompletionInvoked c) = Left $ show c+
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}