alphaheavy / consul-haskell Goto Github PK
View Code? Open in Web Editor NEWA haskell client library for consul (consul.io)
License: BSD 3-Clause "New" or "Revised" License
A haskell client library for consul (consul.io)
License: BSD 3-Clause "New" or "Revised" License
Here I'm making a short list of key things to improve in consul-haskell
.
Bool
on errors.registerService :: ... -> m Bool
returns False
on any non-HTTP-200 response, discarding any useful error message, thus making it unclear how the caller should handle that case. Invalid request, or temporary loss of cluster leadership? The caller cannot tell.this is here instead of the where to prevent typechecking nastiness
ConsulClient
(like the Python bindings do).Maybe Datacenter
as an argument, but it is usually not used, and if used, usually the same.async
.async
package); use withAsync
or other safe helper utilities that the docs instruct to use instead.someFunctionality :: MonadIO m => ConsulClient -> FunctionalitySpecificRequestType -> m (Maybe FunctionalitySpecificResponseType)
someFunctionality client@ConsulClient{..} request dc = do
let hostnameWithScheme = hostWithScheme client
initReq <- createRequest hostnameWithScheme
ccPort
"/v1/functionalitySpecificPath"
Nothing
(Just $ BL.toStrict $ encode request)
False
dc
liftIO $ withResponse initReq ccManager $ \ response -> do
case responseStatus response of
x | x == status200 -> do
bodyParts <- brConsume $ responseBody response
return $ decode $ BL.fromStrict $ B.concat bodyParts
_ -> return Nothing
Hey Steve, do you plan to release this to hackage any time soon? I'd like to use it in a project (the key value functionality in particular).
> /tmp/stackage-build8$ stack unpack consul-haskell-0.3
Unpacked consul-haskell-0.3 to /tmp/stackage-build8/consul-haskell-0.3/
> /tmp/stackage-build8/consul-haskell-0.3$ runghc -clear-package-db -global-package-db -package-db=/var/stackage/work/builds/nightly/pkgdb Setup configure --package-db=clear --package-db=global --package-db=/var/stackage/work/builds/nightly/pkgdb --libdir=/var/stackage/work/builds/nightly/lib --bindir=/var/stackage/work/builds/nightly/bin --datadir=/var/stackage/work/builds/nightly/share --libexecdir=/var/stackage/work/builds/nightly/libexec --sysconfdir=/var/stackage/work/builds/nightly/etc --docdir=/var/stackage/work/builds/nightly/doc/consul-haskell-0.3 --htmldir=/var/stackage/work/builds/nightly/doc/consul-haskell-0.3 --haddockdir=/var/stackage/work/builds/nightly/doc/consul-haskell-0.3 --flags=
Configuring consul-haskell-0.3...
> /tmp/stackage-build8/consul-haskell-0.3$ runghc -clear-package-db -global-package-db -package-db=/var/stackage/work/builds/nightly/pkgdb Setup build
Building consul-haskell-0.3...
Preprocessing library consul-haskell-0.3...
src/Network/Consul/Types.hs:30:0: error:
warning: extra tokens at end of #ifdef directive
#ifdef __GLASGOW_HASKELL__ <710
^
[1 of 3] Compiling Network.Consul.Types ( src/Network/Consul/Types.hs, dist/build/Network/Consul/Types.o )
src/Network/Consul/Types.hs:31:1: warning: [-Wunused-imports]
The import of ‘Control.Applicative’ is redundant
except perhaps to import instances from ‘Control.Applicative’
To import instances alone, use: import Control.Applicative()
src/Network/Consul/Types.hs:32:1: warning: [-Wunused-imports]
The import of ‘Data.Traversable’ is redundant
except perhaps to import instances from ‘Data.Traversable’
To import instances alone, use: import Data.Traversable()
[2 of 3] Compiling Network.Consul.Internal ( src/Network/Consul/Internal.hs, dist/build/Network/Consul/Internal.o )
src/Network/Consul/Internal.hs:68:88: error:
Not in scope: ‘checkStatus’
src/Network/Consul/Internal.hs:69:41: error:
Not in scope: ‘checkStatus’
If the function receives an index then expect that consul is going to block until there's an update to the thing you are watching. maybe consul-haskell should automatically modify the request to not timeout if this index value is there.
[1 of 3] Compiling Network.Consul.Types ( src/Network/Consul/Types.hs, dist/build/Network/Consul/Types.o )
src/Network/Consul/Types.hs:295:10: error:
• Overlapping instances for ToJSON (Either (Text, Text) Text)
arising from a use of ‘aeson-1.0.2.1:Data.Aeson.Types.ToJSON.$dmtoEncoding’
Matching instances:
instance (ToJSON a, ToJSON b) => ToJSON (Either a b)
-- Defined in ‘aeson-1.0.2.1:Data.Aeson.Types.ToJSON’
instance ToJSON (Either (Text, Text) Text)
-- Defined at src/Network/Consul/Types.hs:295:10
• In the expression:
aeson-1.0.2.1:Data.Aeson.Types.ToJSON.$dmtoEncoding
@Either (Text, Text) Text
In an equation for ‘toEncoding’:
toEncoding
= aeson-1.0.2.1:Data.Aeson.Types.ToJSON.$dmtoEncoding
@Either (Text, Text) Text
In the instance declaration for ‘ToJSON (Either (Text, Text) Text)’
src/Network/Consul/Types.hs:295:10: error:
• Overlapping instances for ToJSON (Either (Text, Text) Text)
arising from a use of ‘aeson-1.0.2.1:Data.Aeson.Types.ToJSON.$dmtoJSONList’
Matching instances:
instance (ToJSON a, ToJSON b) => ToJSON (Either a b)
-- Defined in ‘aeson-1.0.2.1:Data.Aeson.Types.ToJSON’
instance ToJSON (Either (Text, Text) Text)
-- Defined at src/Network/Consul/Types.hs:295:10
• In the expression:
aeson-1.0.2.1:Data.Aeson.Types.ToJSON.$dmtoJSONList
@Either (Text, Text) Text
In an equation for ‘toJSONList’:
toJSONList
= aeson-1.0.2.1:Data.Aeson.Types.ToJSON.$dmtoJSONList
@Either (Text, Text) Text
In the instance declaration for ‘ToJSON (Either (Text, Text) Text)’
Finish implementing APIs from https://consul.io/docs/agent/http/catalog.html
Consul can do a lot. When writing tests, I want to look at a list and compare to confirm coverage.
The purpose of this issue is to scope out and document what should be tested against consul.
See here for example - https://github.com/alphaHeavy/consul-haskell/pull/49/checks?check_run_id=2287576964:
So the CI runner is unable to locate the consul
executable.
All jobs are failing with this error.
This intends to pick up where #55 left off.
Ideas:
$PATH
if we don't need itSee here: https://www.consul.io/api#authentication
We can include the Consul Token for authentication by either adding the X-Consul-Token
header or Bearer scheme Authorization header (Authorization: Bearer
).
We'll need functions for accepting and updating the token to use with the consul client. We'll also want this token to be optional (though highly encouraged, it's not required).
Swap master
for something more meaningful (and appropriate/reasonable). develop
seems to make a lot of sense for a few reasons:
main
has a neutral tone, it doesn't seem much more meaningful/purposeful than master
.Hello,
Thank you for your work creating and maintaining this library. There are a pending tasks/tickets and PRs piling up, so I'd like to ask: what are the project's plans for maintaining the library?
Would it make sense to put out a call for maintainers?
When you watch
something on Consul, it's a blocking HTTP request. Right now I'm passing in a managersettings to initializeConsulClient that disables the timeout when I want to watch things. This means I have to use two different consul clients & juggle them (because I don't want the no-timeout client used for non-watch requests.) Ideally I would manage my own manager & I could modify the request to never timeout if I wanted to watch data for changes on that one HTTP request.
Related to #2
Implement Status https://consul.io/docs/agent/http/status.html
https://github.com/dysinger/consul-haskell/blob/master/src/Network/Consul.hs#L37
It would be nice to pass in a manager here instead of having it constructed inside this initializeConsulClient.
Hi, is this package known to work with Consul 1.0, which has some breaking changes?
At NixOS/nixpkgs#35602 we're planning to upgrade to Consul 1.0 so we're trying to gather a list of packaged software that might break.
Thanks!
cc @nh2
Upstream has a doc with a list of client libs: https://www.consul.io/api/libraries-and-sdks.html
consul-haskell
is not on the list, and we should get it added.
In
Lines 392 to 401 in 4a9151c
I wait for Consul's port to be open before making requests to avoid race conditions between our tests and Consul not being ready.
Turns out this isn't enough, there is a time after which Consul will have opened the port but is still not ready. Evidenced by tests sometimes failing with http: Request PUT /v1/session/create, error: Missing node registration
:
Internal Session Tests
testCreateSession: 2020/01/20 17:09:30 [ERR] http: Request PUT /v1/session/create, error: Missing node registration from=127.0.0.1:51866
FAIL
tests/Main.hs:237:
testCreateSession: No session was created
testGetSessionInfo: 2020/01/20 17:09:30 [ERR] http: Request PUT /v1/session/create, error: Missing node registration from=127.0.0.1:51870
FAIL
tests/Main.hs:250:
testGetSessionInfo: No session was created
testRenewSession: 2020/01/20 17:09:30 [ERR] http: Request PUT /v1/session/create, error: Missing node registration from=127.0.0.1:51874
FAIL
tests/Main.hs:263:
testRenewSession: No session was created
testRenewNonexistentSession: OK
testDestroySession: OK
Very annoying; we'll have to have a more sophisticated check for Consul being ready.
See here: https://hackage.haskell.org/package/consul-haskell
Update that package with recent releases.
cc @nh2 can you help me with access to the package on hackage?
I was just messing around with this library, and I found that calling deregister service fails because it's making a GET
request when the API calls for a PUT
request.
Code example:
client <- initializeConsulClient "localhost" 8500 Nothing
print =<< getServices client Nothing Nothing
deregisterService client "test"
Results in output:
["test","consul"]
HttpExceptionRequest Request {
host = "localhost"
port = 8500
secure = False
requestHeaders = []
path = "/v1/agent/service/deregister/test"
queryString = ""
method = "GET"
proxy = Nothing
rawBody = False
redirectCount = 10
responseTimeout = ResponseTimeoutDefault
requestVersion = HTTP/1.1
}
(StatusCodeException (Response {responseStatus = Status {statusCode = 405, statusMessage = "Method Not Allowed"}, responseVersion = HTTP/1.1, responseHeaders = [("Allow","OPTIONS,PUT"),("Content-Type","text/plain; charset=utf-8"),("Vary","Accept-Encoding"),("X-Consul-Default-Acl-Policy","allow"),("Date","Sat, 03 Apr 2021 00:21:31 GMT"),("Content-Length","22")], responseBody = (), responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}) "method GET not allowed")
The following worked:
curl -XPUT localhost:8500/v1/agent/service/deregister/test
Consul version:
$ consul version
Consul v1.9.4
Revision 10bb6cb3b
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
This test code
Lines 308 to 323 in 85bf68a
connects to consul on port 8500 and inserts a TTL check.
When you build the package with tests enabled (which is what many build tools, in my case nix, do by default), this will mess with the consul on your machine.
It doesn't even delete the TTL check, so after the test executable runs, the TTL check will swiftly fail, possibly even paging you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.