bloodhound-1.0.0.0: tests/Test/ClusterHealthSpec.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module Test.ClusterHealthSpec where
import Data.List qualified as L
import Data.Text qualified as T
import Database.Bloodhound.Common.Client qualified as Client
import TestsUtils.Common
import TestsUtils.Import
spec :: Spec
spec = do
describe "cluster health API" $ do
it "returns cluster health information" $
withTestEnv $ do
health <- Client.getClusterHealth
liftIO $ clusterHealthClusterName health `shouldSatisfy` (not . T.null)
liftIO $ clusterHealthNumberOfNodes health `shouldSatisfy` (> 0)
liftIO $ clusterHealthNumberOfDataNodes health `shouldSatisfy` (> 0)
it "returns valid health status" $
withTestEnv $ do
health <- Client.getClusterHealth
liftIO $ clusterHealthStatus health `shouldSatisfy` (`elem` [ClusterHealthGreen, ClusterHealthYellow, ClusterHealthRed])
it "returns shard information" $
withTestEnv $ do
health <- Client.getClusterHealth
liftIO $ clusterHealthActivePrimaryShards health `shouldSatisfy` (>= 0)
liftIO $ clusterHealthActiveShards health `shouldSatisfy` (>= 0)
-- ------------------------------------------------------------------ --
-- Per-index + options (bloodhound-04f.4.1.7) --
-- ------------------------------------------------------------------ --
it "getClusterHealthForIndex returns health for a specific index" $
withTestEnv $ do
let idx = [qqIndexName|bloodhound-tests-cluster-health-per-index|]
_ <- tryPerformBHRequest $ deleteIndex idx
_ <-
performBHRequest $
createIndex
(IndexSettings (ShardCount 1) (ReplicaCount 0) defaultIndexMappingsLimits)
idx
health <- Client.getClusterHealthForIndex idx
liftIO $ clusterHealthStatus health `shouldSatisfy` (`elem` [ClusterHealthGreen, ClusterHealthYellow, ClusterHealthRed])
liftIO $ clusterHealthActivePrimaryShards health `shouldSatisfy` (>= 0)
_ <- tryPerformBHRequest $ deleteIndex idx
pure ()
it "getClusterHealthWith defaultClusterHealthOptions returns a usable response" $
withTestEnv $ do
health <- Client.getClusterHealthWith defaultClusterHealthOptions
liftIO $ clusterHealthClusterName health `shouldSatisfy` (not . T.null)
it "getClusterHealthWith accepts level=indices (passthrough)" $
withTestEnv $ do
let opts =
defaultClusterHealthOptions
{ choLevel = Just ClusterHealthLevelIndices
}
health <- Client.getClusterHealthWith opts
-- The base fields are always present regardless of level; the
-- indices/shards breakdown is accepted but not modelled yet.
liftIO $ clusterHealthNumberOfNodes health `shouldSatisfy` (> 0)
it "waitForYellowIndex still returns a health record (regression)" $
withTestEnv $ do
let idx = [qqIndexName|bloodhound-tests-cluster-health-wait-yellow|]
_ <- tryPerformBHRequest $ deleteIndex idx
_ <-
performBHRequest $
createIndex
(IndexSettings (ShardCount 1) (ReplicaCount 0) defaultIndexMappingsLimits)
idx
status <- performBHRequest $ waitForYellowIndex idx
liftIO $ healthStatusStatus status `shouldSatisfy` (`elem` ["green", "yellow"])
_ <- tryPerformBHRequest $ deleteIndex idx
pure ()
-- ------------------------------------------------------------------ --
-- clusterHealthOptionsParams: pure URI rendering (no ES required) --
-- ------------------------------------------------------------------ --
describe "clusterHealthOptionsParams URI rendering" $ do
let normalize :: [(T.Text, Maybe T.Text)] -> [(T.Text, Maybe T.Text)]
normalize = L.sort
it "defaultClusterHealthOptions emits no params" $
clusterHealthOptionsParams defaultClusterHealthOptions
`shouldBe` []
it "renders level via renderClusterHealthLevel" $ do
let opts =
defaultClusterHealthOptions
{ choLevel = Just ClusterHealthLevelShards
}
clusterHealthOptionsParams opts
`shouldBe` [("level", Just "shards")]
it "renders wait_for_status as the status string" $ do
let opts =
defaultClusterHealthOptions
{ choWaitForStatus = Just ClusterHealthGreen
}
clusterHealthOptionsParams opts
`shouldBe` [("wait_for_status", Just "green")]
it "renders wait_for_active_shards via ActiveShardCount" $ do
let opts =
defaultClusterHealthOptions
{ choWaitForActiveShards = Just AllActiveShards
}
clusterHealthOptionsParams opts
`shouldBe` [("wait_for_active_shards", Just "all")]
it "renders wait_for_nodes verbatim" $ do
let opts =
defaultClusterHealthOptions
{ choWaitForNodes = Just "ge(2)"
}
clusterHealthOptionsParams opts
`shouldBe` [("wait_for_nodes", Just "ge(2)")]
it "renders booleans as lowercase true/false" $ do
let opts =
defaultClusterHealthOptions
{ choWaitForNoRelocatingShards = Just True,
choWaitForNoInitializingShards = Just False,
choLocal = Just True
}
normalize (clusterHealthOptionsParams opts)
`shouldBe` [ ("local", Just "true"),
("wait_for_no_initializing_shards", Just "false"),
("wait_for_no_relocating_shards", Just "true")
]
it "renders master_timeout and timeout as <n><suffix>" $ do
let opts =
defaultClusterHealthOptions
{ choMasterTimeout = Just (TimeUnitSeconds, 30),
choTimeout = Just (TimeUnitMilliseconds, 500)
}
normalize (clusterHealthOptionsParams opts)
`shouldBe` [ ("master_timeout", Just "30s"),
("timeout", Just "500ms")
]
it "emits every param together when all are set" $ do
let opts =
defaultClusterHealthOptions
{ choLevel = Just ClusterHealthLevelIndices,
choLocal = Just True,
choMasterTimeout = Just (TimeUnitMinutes, 1),
choWaitForStatus = Just ClusterHealthYellow,
choWaitForActiveShards = Just (ActiveShards 2),
choWaitForNodes = Just "le(3)",
choWaitForNoRelocatingShards = Just True,
choWaitForNoInitializingShards = Just True,
choTimeout = Just (TimeUnitSeconds, 10)
}
normalize (clusterHealthOptionsParams opts)
`shouldBe` [ ("level", Just "indices"),
("local", Just "true"),
("master_timeout", Just "1m"),
("timeout", Just "10s"),
("wait_for_active_shards", Just "2"),
("wait_for_no_initializing_shards", Just "true"),
("wait_for_no_relocating_shards", Just "true"),
("wait_for_nodes", Just "le(3)"),
("wait_for_status", Just "yellow")
]