hashicorp / serf

Service orchestration and management tool.
https://github.com/hashicorp/serf/blob/master/docs/index.html.markdown
Mozilla Public License 2.0
5.88k stars 596 forks source link

Allow additional output options, and filtering members by -role=<role> and -state=<state> #55

Closed kamilion closed 10 years ago

kamilion commented 11 years ago

Current behavior:

$ serf members
router    10.0.1.69    alive    uplink-router
ubuntu    10.0.5.253    alive    actor
livecd    10.0.5.252    alive    actor

New behaviors (perhaps for 0.2.1?)

Role Filter feature request:

$ serf members -role=actor
ubuntu    10.0.5.253    alive    actor
livecd    10.0.5.252    alive    actor

State Filter feature request:

$ serf members -state=alive
router    10.0.1.69    alive    uplink-router
ubuntu    10.0.5.253    alive    actor
livecd    10.0.5.252    alive    actor

Output options feature request:

JSON support is already in core for loading configuration.

$ serf members -json
{
  "members": [
    "10.0.1.69": [ name:"router", state:"alive", role:"uplink-router"],
    "10.0.5.253": [ name:"ubuntu", state:"alive", role:"actor"],
    "10.0.5.252": [ name:"livecd", state:"alive", role:"actor"]
  ]
}

Optionally, if it's easily available for implementation, CSV would also be helpful for 'cut'.

$ serf members -csv
name,ip,state,role
router,10.0.1.69,alive,uplink-router
ubuntu,10.0.5.253,alive,actor
livecd,10.0.5.252,alive,actor

And a -one option would also be quite helpful.

$ serf members -one -csv -state=alive -role=uplink-router | sed "1d" | cut -d ',' -f 2
10.0.1.69

Give me an actor, please:

$ serf members -detailed -one -json -state=alive -role=actor
{
  "members": [
    "10.0.1.252": [ name:"livecd", state:"alive", role:"actor", protocol: 1, protocols: [0, 1]]
  ]
}

Feel free to skip the CSV support, as it's just as easy to

serf members | sed "s/    /\t/g" | cut -f 2

since cut won't take more than a single character as a delimiter.

But if you're using serf with something like python and the 'sh' library, boy it sure is nice to use a CSVReader or json to deal with preformatted shell input.

import json, pprint
from sh import serf
# The serf binary ^ must be somewhere in your path for sh to find it.

# Check out http://amoffat.github.io/sh/#sub-commands
my_json_iter = serf.members("-json")  # Yields lines as __iter__
members_dict = json.load(my_json_iter)  # json.load iterates and json.loads expects a string.
pprint members_dict  # An an object comes out!

my_actor = "uplink-router"
pprint json.load(serf.members("-json","-role={}".format(my_actor))) # How bout a oneliner?

Having both may be overboard; however, JSON isn't exactly shellscript friendly.

mitchellh commented 11 years ago

I agree. Tagged. I may split this into other issues but will let you know.

kamilion commented 11 years ago

Had a discussion with phaxx on IRC last night, where we differed in opinion on how to make use of serf in our respective environments.

Using the -json output specifier would allow us to keep a joincache of cluster members by ourselves, in whatever fashion we wish. He clued me into the jq shell tool that can pipe and transform json, and it really would not be very hard to take the output of serf members -json, mash it a little in shell and spit out a new serf config.json with a 'last known cluster members' to rejoin.

Now, in my environment, where my 'actors' are behind a partially routed network segment, I'd have to do something slightly differently than everyone else to say, make sure that the 10.0.5.* members didn't try to joincache a 10.0.1.* address. So it sort of makes sense to deal with this from outside the serf executable.

CSV support would be very welcome on windows where Powershell can natively consume csv data into .net objects and pass them around with pipes, and other common tools people have on their machine already like Excel, LO.org Calc, GNumeric and most anything that is meant to deal with SQL can just gobble CSV wholesale.

Here's the jist of our conversation, for future reference:

[04:25:39] <phaxx> has anyone created debian/ubuntu packages yet? with init scripts and all that.
[01:45:57] <Kamilion> woo. Lucky number 55. Posted an issue about filtering serf members: https://github.com/hashicorp/serf/issues/55
[02:15:16] <Kamilion> phaxx: And here's some init units for you. Upstart & systemd included and tested. <3  https://github.com/hashicorp/serf/issues/56
[02:18:07] <Kamilion> If you're not running fedora/debian+systemd or ubuntu+upstart; I'm not going to bother writing an actual boilerplated init.d script, so you're on your own.
[04:16:23] <phaxx> Kamilion: nice, thanks! exactly what I needed.
[04:17:25] <phaxx> perhaps someone could explain some behaviour that is puzzling me: when stopping serf on one node and restarting it, it doesn't rejoin the cluster. it stays in the 'left' state. when killing it with -9 and restarting it, the other nodes will contact it and it will rejoin.
[04:18:18] <phaxx> what is the right way to have an agent rejoin without having to manually issue a join command and pick another active node?
[04:18:40] <phaxx> it doesn't look like it stores any local state that would help it with this, but perhaps I missed it.
[06:09:09] <Kamilion> Hm, not sure offhand.
[06:13:01] <Kamilion> the init units i provided will ensure surf leaves the cluster on a 'service serf restart' or stop. I believe that may not be the behavior you're looking for. Just comment out "kill signal INT" or "KillSignal=SIGINT" and serf will not leave the cluster gracefully. Other members will continue probing for it's return, I suppose?
[06:13:40] <phaxx> yeah, that's the only solution I've come up with so far.
[06:13:44] <Kamilion> I just provided it with a json containing five IP addresses of somewhere in the cluster
[06:14:14] <Kamilion> and it seems to find it's way in, for me.
[06:14:24] <phaxx> from reading about serf's intended use, I expected it to behave more like riak where a cluster join or leave operation is somewhat permanent and all nodes keep a 'ring' file to bootstrap themselves.
[06:14:46] <phaxx> the presence of the force-leave option fits with that model.
[06:15:11] <Kamilion> my /etc/serf/config.json looks like this:
[06:15:11] <Kamilion> http://hastebin.com/fewekejufo.apache
[06:15:14] <phaxx> I was surprised to see a serf agent do an orderly leave when given a ^C during my testing.
[06:15:23] <phaxx> hmm.
[06:15:39] <phaxx> that's good, but I think the burden of maintaining that list shouldn't be on the user.
[06:16:21] <phaxx> it just doesn't make it as resilient as perhaps it should be.
[06:16:33] <Kamilion> one of my roles is an 'uplink-router' which sits on two or more subnets.
[06:17:05] <Kamilion> two nodes don't have to be able to directly connect to eachother. (but it helps)
[06:17:11] phaxx nods
[06:17:14] <phaxx> yeah, that's nice.
[06:18:12] <Kamilion> I wouldn't be suprised if a cache option appeared shortly for folks who wanted behavior like you.
[06:18:35] <phaxx> I'd be pretty pleased with that.
[06:19:08] <Kamilion> however, for me, it wouldn't work out so well. Part of the reason I'm using serf is that my 'actor' LiveCDs do not have any permanant storage.
[06:19:29] <Kamilion> I can now discover a server with a storage role.
[06:19:33] <phaxx> ah, interesting use of it.
[06:20:19] <phaxx> the cache option wouldn't interfere with you, I think - you'd just be restricted to bootstrapping an agent with a join command every time you start it
[06:20:32] <Kamilion> correct; the cache would just be discarded when the livecd shut down.
[06:20:43] <Kamilion> for everyone else though, it'd probably be handy.
[06:20:47] phaxx nods
[06:21:18] <phaxx> the addition of the cache and making 'leave cluster on agent shutdown' optional would be perfect.
[06:21:18] <Kamilion> of course, if issue #55 goes through; one could simply rewrite their config file with a post-start or pre-stop
[06:21:35] <Kamilion> by spitting out the current member list as json
[06:22:10] <phaxx> yes, building this cache on top of what is described in issue 55 makes sense.
[06:22:18] <phaxx> nicely user servicable and understandable.
[06:22:28] <Kamilion> it's one of those unixy things, being able to use | and such sanely.
[06:22:53] <phaxx> yup
[06:23:12] <Kamilion> and the -csv proposal tends to target windows users more
[06:24:03] <Kamilion> powershell can pipe csv into excel with like, five lines
[06:24:30] <phaxx> heh.
[06:24:38] <Kamilion> or chop it up any other which way; since csv is one of those things powershell can pass around easily. Not so much json.
[06:25:08] <Kamilion> CSV's also more familiar to .cmd and .bat scripters too. heh.
[06:25:34] <phaxx> it's a strange world there, I'm happy enough in unixland.
[06:25:53] <phaxx> as for json, the jq utility is very handy: http://stedolan.github.io/jq/
[06:26:07] <phaxx> it's still not a nice format to work with.
[06:26:12] <Kamilion> eh, I got a lot of places where serf would be handy... including a gtk+ interface that can run on windows. So having serf there too is A++
[06:26:23] <phaxx> hmm.
[06:26:25] <Kamilion> ah heck, gotta add that then
[06:26:31] Kamilion ^Cs another iso build
[06:35:12] <Kamilion> jq added to the iso
[06:37:24] <Kamilion> thanks for the push towards jq, this will come in handy!
mitchellh commented 11 years ago

Yeah I mentioned this in a previous issue somewhere, but I think the answer will be a -format flag that can output a variety of formats.

bbaugher commented 10 years ago

Is there an issue tracking the -format functionality?

armon commented 10 years ago

@bbaugher : opened a new issue here: https://github.com/hashicorp/serf/issues/97