[00:00] var m = make(map[string]int) [00:01] type T struct { name string } [01:26] * thumper is beginning to want proper inheritance in go... [01:26] * thumper sighs [01:28] * thumper has another thought... [01:28] gah, must finish something before starting another [01:28] * thumper puts head down again [02:22] davecheney: by splitting out the SetFlags from the Init, a bunch of tests are failing... [02:22] davecheney: as they are testing Init [02:22] davecheney: is there a place where we put helper test functions? [02:23] davecheney: for example, jujud/agent_test.go has a method called initCmd [02:23] which creates some flags, and calls init [02:23] I added the setflags to it, and I'd like to make the function more generally useful in other tests [02:27] * thumper guesses davecheney is at lunch [02:43] thumper: generally suite_test.go is a good start [02:43] but i think you have to leiway to create your own tradition [04:00] whoever thought that "c *C" were good params for tests should be given a very stern look [04:16] * thumper jumps through hoops [04:21] * thumper wonders if 1000 lines of diff are enough for first change to juju [04:27] thumper: i'd say most things are up for grabs if you are prepared to argue your case [04:27] hmm... [04:28] davecheney: are there dependencies between the juju-core packages that I have to make sure I don't screw up? [04:31] thumper: not sure i parsed that correctly [04:31] davecheney: there are tests lying around... [04:31] davecheney: and I want to put some common command test helper methods into juju-core/testing [04:32] kk [04:32] which would add a depencency on juju-core/cmd [04:32] which I don't think is there yet [04:32] likely to be fine? [04:32] sure [04:32] kk [04:32] I'm sure there is alreayd a dep between cmd/juju and cmd [04:33] thumper: go list -f '{{ .Imports }}' launchpad.net/juju-core/cmd/juju [04:33] ^ direct imports of cmd/juju [04:33] go list -f '{{ .Deps }}' launchpad.net/juju-core/cmd/juj [04:33] ^ all transitive deps [04:33] ah... [04:33] handy [04:33] I may try that shortly [04:50] holy shit [04:50] thumper: you got your rietveld account all set up for your mp? [04:50] realised that my tollerance for duplication in tests is way below some others [04:50] wallyworld_: no [04:51] thumper: it's not just tests - i'm finding Go to be very verbose [04:51] wallyworld_: this isn't go [04:51] it is just code [04:51] yeah agreed, it's also elsewhere [05:08] davecheney: umm... if I Ctrl-C the tests while running, have I left things behind that might cause further tests to hang? [05:10] thumper: in theory no [05:10] in practice [05:10] yes, you'll eventyualy leak enough mongo processes to run out of swap [05:11] if you put /tmpfs on swap, then you ahve to be doubly careful [05:11] as each mongo will write 200mb of journal files on startup [05:22] hmm... [05:22] ok, something to watch for then :) [05:22] I'm almost at the state of making all these tests pass again... [05:22] neat [05:22] hmm... [05:22] $ bzr diff | wc -l [05:22] 1467 [05:23] although, not quite that bad: 58 files changed, 223 insertions(+), 188 deletions(-) [05:23] and much of that is duplicated [05:24] ok, I hear the kids home [05:24] tests are running, pretty confident [05:24] tomorrow lets get this reviewed and landed [05:24] night all [05:25] night [05:26] got a branch ? [05:26] work up at lp:~thumper/juju-core/command-set-flags if you are curious [05:26] * thumper signs off [05:26] kk [05:26] and all tests passed \o/ [06:52] davecheney: hi, thanks for finding that data race. what tool did you use? [08:13] Morning [08:14] TheMue: morning! [08:25] dimitern, TheMue, heyhey [08:25] fwereade: hiya [08:25] fwereade, dimitern: Hi [08:25] dimitern, TheMue: fwiw I have a few constraints branches from last night up [08:25] fwereade: yeah, already on these [08:26] dimitern, you rock [08:26] TheMue, you have a trivial LGTM on the deletes branch [08:26] fwereade: Yep, thx, just doing the final merging and test. [08:28] mornin' all [08:28] rogpeppe: Hiya [08:28] TheMue: yo! [08:28] rogpeppe: morning [08:28] dimitern: hi! [10:23] fwereade: you've got 2 reviews [10:23] dimitern, tyvm [10:35] rogpeppe, ping [10:35] fwereade: pong [10:35] rogpeppe, last weekend, I had a thought related to the api [10:36] fwereade: ok [10:36] rogpeppe, would you agree that the following is a valid perspective: a machine agent can be defined to be trusted, or not, dependent on whether it has a state.Info and can hence connect directly to mongo [10:37] rogpeppe, and that we thus always require that at least one trusted machine exists [10:37] fwereade: given that the state.Info contains a valid password, yeah [10:37] rogpeppe, because we need it to run the API server, through which untrusted machine/unit agents will connect [10:37] fwereade: yup [10:38] fwereade: there must always be at least one API server running [10:39] rogpeppe, ok, so, if we keep the Provisioner and Firewaller just as they are, and only allow them to run on trusted machines -- against a state.Conn, I think you get to cut down the API surface quite pleasingly (and not need to even *touch* the code for the pro/fw) [10:40] fwereade: hmm, i'm not sure [10:40] rogpeppe, that way we don't even expose an EnvironConfig API call that returns the user's credentials [10:40] fwereade: how does a trusted machine get the credentials in the first place? [10:41] rogpeppe, however it does as it is? sorry, I'm not sure of the impact, can you expand? [10:41] rogpeppe, machine 0 would have it magically; subsequent machine agents that need to run trusted tasks would, I presume, get the state info published to them [10:41] fwereade: i'd envisaged that we'd be able to repurpose an existing machine to run any job [10:41] rogpeppe, I had a vague feeling that was in line with the approx plans? [10:42] rogpeppe, yeah, I think we still can [10:42] fwereade: so how do we publish the state info to an existing machine? [10:43] rogpeppe, you had the plans for a Publisher of API info, right? why not analogously for state info, but with more restrictions in the API? [10:43] fwereade: sure. but surely the place to publish it is in the state, no? [10:43] rogpeppe, yeah, via the API... right? [10:44] fwereade: bingo [10:44] [10:40:12] rogpeppe, that way we don't even expose an EnvironConfig API call that returns the user's credentials [10:44] rogpeppe, ok, but the attack surface is limited to that one call... much like Login [10:45] fwereade: ah, no i see [10:45] rogpeppe, and I *think* the savings form not having to implement the API bits that are only used by trusted workers will be handy [10:45] fwereade: yeah, i think that certainly for an interim period, your suggestion is good [10:46] rogpeppe, yeah, we can evaluate how well it works :) [10:46] fwereade: rather than having an EnvironConfig call, we have a MongoStateInfo call (or something) which gives untrammelled access to the underlying state [10:46] rogpeppe, btw, ISTM that the tools param to Environ.StartInstance is used very rarely indeed [10:46] rogpeppe, yeah, exactly [10:47] rogpeppe, that information feels like the stuff we also have to give to a machine running another Stater to connect them all up [10:47] fwereade: i'm not sure long term though [10:47] fwereade: having direct access to the state feels a bit like granting root access [10:47] rogpeppe, don't worry, I'm not laying down cathedral plans ;) [10:47] rogpeppe, sure, agreed [10:48] fwereade: and actually neither provisioner or firewaller need that level of access [10:48] fwereade: only the API server does [10:48] rogpeppe, agreed -- I am not laying down cathedral plans [10:48] fwereade: ok [10:49] rogpeppe, I'm suggesting that it's a good interim goal because it looks like the quickest way to get all our code running with *a* security boundary in place [10:51] fwereade: the only difficulty is that the logic in the machiner becomes more complex [10:52] fwereade: but that's probably a reasonable tradeoff [10:52] rogpeppe, it feels tolerable, yeah [10:57] fwereade: yeah, it looks like we could get rid of the tools arg to StartInstance without losing anything significant [11:04] fwereade: trivial CL: https://codereview.appspot.com/7317050 [11:07] rogpeppe, well, I think the tools interact very closely, I'm still trying to figure out the right way to go [11:08] fwereade: i managed to reproduce that mongodb "--format provided but not defined error" BTW. i'm not entirely sure which command is drawing that error, hence my trivial CL above. [11:08] fwereade: that's the bug i found w.r.t. the mongodb charm, BTW [11:09] rogpeppe, LGTM trivial [11:09] fwereade: thank [11:09] rogpeppe, but it's not reliably reproducible? [11:09] s [11:09] fwereade: yeah, it is [11:10] rogpeppe, ah, fantastic [11:10] fwereade: it just takes a while to do it [11:10] rogpeppe, heh [11:12] rogpeppe, I'm thinking of --upload-tools, which I think at the moment just uses version.Current, which is probably right (given an absence of cross-compiling) [11:13] fwereade: it can't do anything else, yeah [11:13] rogpeppe, in which case we have to check that the series and arch of the image/instance we start actually match what we're uploading [11:14] fwereade: hmm, i have to think about that a bit [11:14] fwereade: currently upload-tools is just an argument to bootstrap [11:14] fwereade: and there's nothing stopping you from provisioning more instances that don't use the originally uploaded tools [11:14] rogpeppe, yeah, and vice versa [11:15] rogpeppe, ok then, cool [11:15] fwereade: i'm not sure what you mean by "vice versa" there actually. [11:15] fwereade: you can't upload tools later [11:15] rogpeppe, we *just* upload the tools we can, and the user is responsible for starting instances on which they will actually run [11:16] rogpeppe, oh, I thought upgrade-juju could do that? [11:16] fwereade: oh yeah, so it does! [11:16] rogpeppe, :D [11:17] [11:16:00] rogpeppe, we *just* upload the tools we can, and the user is responsible for starting instances on which they will actually run [11:17] +1 [11:17] rogpeppe, ok, sweet [11:17] rogpeppe, I am also eyeing environs.FindTools [11:18] rogpeppe, I am suspecting that it should somehow give me a list of available tools matching certain criteria (filter on series and arches, I think) [11:19] fwereade: yeah. the significant issue around this is that currently we choose what tools an instance will run before we actually ask the provider to start the instance [11:19] rogpeppe, that is I think ok [11:19] fwereade: but if the provider itself can decide on an architecture, for example, then that might be a problem [11:20] fwereade: perhaps FindTools should take a Constraints as an argument? [11:20] [11:20:10] fwereade: perhaps FindTools should take a Constraints as an argument? [11:20] although series isn't really a constraint [11:21] rogpeppe, perhaps -- yeah, I'm eyeing (series string, cons Constraints) args [11:21] rogpeppe, that said... it would be *really* convenient if Series was a constraint [11:21] fwereade: yeah, and... why shouldn't it be? [11:22] rogpeppe, because it's not something amenable to direct control like the others [11:22] rogpeppe, the series is determined by the service's charm, which itself may be determined by the environ's default-series [11:22] fwereade: isn't it actually in a way *more* amenable to direct control (we can start different series on a given piece of hardware) [11:23] rogpeppe, from the juju level, it is -- juju deploy cs:precise/foobar -- bam, there's precise [11:23] rogpeppe, and there's the distinct setting of constraints, in which series does not play a part [11:23] fwereade: i'm not intrinsicaly opposed to the idea that a charm might influence the constraints of the machine that's started to deploy it [11:23] rogpeppe, it *must* [11:23] rogpeppe, precise charms run on precise [11:24] rogpeppe, quantal charms run on quantal [11:24] rogpeppe, etc [11:24] fwereade: ok, so how can the series *not* be part of the constraints? [11:25] fwereade: BTW how does getting a list of available tools from FindTools help you? [11:25] rogpeppe, it is not entirely clear that the internal representation of a Constraints should *necessarily* carry with it the series information which is specified in a different way and could I think be inferred where necessary [11:26] fwereade: all constraints are optional, no? so there's no "necessary" there. [11:26] rogpeppe, series is not optional [11:27] rogpeppe, which is another way in which it is different to the other constraints [11:27] fwereade: no constraint is optional when the machine is actually instantiated :-) [11:28] rogpeppe, that's information about a running instance, which we do want to match against constraints in future; but they are not themselves constraints [11:28] rogpeppe, they represent a solution to the constraints, if you like [11:28] fwereade: yeah, and the form of the solution might look exactly like a Constraint :-) [11:29] rogpeppe, they do indeed look very similar [11:29] rogpeppe, but actually not exactly the same :) [11:29] fwereade: anyway, i'm not sure i see the advantage to passing the series around as an extra parameter to the constraints. [11:30] rather, a parameter extra to the constraints [11:30] fwereade: and i definitely see simplicity advantages to including it with the constraints [11:31] rogpeppe, I'm not sure the case is overwhelming either way, is all; it could easily be stored on state.Machine when a unit is assigned -- you always have a series, because the unit has a service has a charm -- as well as the service having constraints [11:31] fwereade: in fact, if series was part of the constraints, we perhaps wouldn't need default-series [11:32] rogpeppe, I don't think it's the same thing, quite [11:32] fwereade: because it could be specified by the environment's series constraint. [11:33] rogpeppe, that's where the default would come from -- but then you override that constraint in a different and magical way when you deploy, and you can't even set it from the UI [11:34] fwereade: i'm not sure it's "magical" - every charm comes with an implied series constraint. [11:35] fwereade: maybe you would want some special case code to prevent you setting a service's series constraint to something other than the charm's series though. [11:35] rogpeppe, I am weighing up the costs and benefits of that special casing [11:35] rogpeppe, I don;t feel entirely in favour of it: I think that doing that in the python was a bit of a mistake [11:36] fwereade: but tbh, "series" doesn't seem like something that should be so special. it's special now because everything's ubuntu-only. [11:36] rogpeppe, I don;t suppose you know if there's a wiki page for the sprint yet? [11:36] fwereade: not afaik [11:36] * rogpeppe must book flights [11:36] rogpeppe, it's gonna be very special one day, I just hope it can bear the load that's put on its shoulders [11:36] rogpeppe, it's in charms, it's in juju, and it's our one way of specifying a target os [11:37] fwereade: i could see it becoming a (os, os-version) tuple [11:37] rogpeppe, indeed it might [11:37] fwereade: but maybe that's just a compound name [11:37] rogpeppe, plausibly [11:37] anyone seen mramm ? [11:37] fwereade: i'd prefer it to be two attributes as part of the constraints though, [11:38] dimitern, we can all dogpile him when he gets on :) [11:38] fwereade: :D sure [11:38] fwereade: to put it another way, what *wouldn't* work well (or be more complex) if series was part of the constraints? [11:40] rogpeppe, environ-level series constraints would be weird -- they'd work a bit like default-series and a bit like the other constraints [11:42] fwereade: say we took default-series to be just the seed for setting the environ-level series constraint? would that cause problems? [11:42] fwereade: (we've already got to segregate default series from the other environment config params) [11:43] fwereade: (mind you, that's true of the agent version field too, and probably others) [11:44] rogpeppe, yeah -- I think that it is tempting to put lots of stuff into constraints but I want to grow it prudently [11:44] fwereade: i would *not* put the agent version into constraints [11:44] rogpeppe, quite so [11:45] fwereade: but i think series does work well as a constraint [11:45] rogpeppe, a constraint that can't be set like the other constraints, can't be changed like the other constraints, and affects parts of the codebase that no other constraints impact? [11:46] rogpeppe, it *may* indeed be a good place for it [11:46] rogpeppe, but it will take some pretty seriously ugliness on the other side to balance that out [11:49] rogpeppe, so, anyway, as I solve the constraints I will eliminate various images and instance-types from consideration, but I will still probably end up with multiple candidates [11:49] rogpeppe, of those that the provider offers, there may not be tools available [11:51] rogpeppe, gaah, sorry [11:51] fwereade: np [11:51] rogpeppe, what was the last thing you saw? [11:51] [11:49:26] rogpeppe, of those that the provider offers, there may not be tools available [11:51] rogpeppe, cool, that was all I'd said [11:52] fwereade: yeah, i see where you're coming from [11:52] rogpeppe, but still I will end up with a bunch of possible instance/image pairs, and appropriate tools for each, and then have to try to pick the "best" according to whatever soft constraints we have [11:53] rogpeppe, that's a separate problem though [11:53] fwereade: the thing to be careful of is that you always want to pick from Storage over PublicStorage where possible. [11:54] rogpeppe, hmm, if you want to use your own storage you're surely using it for higher-than-public versions..? [11:54] fwereade: "where possible" might just mean "where the difference is just in version number" [11:54] fwereade: no, not necessarily [11:55] fwereade: it's important that you be able to upload lower-than-public versions too [11:55] fwereade: and have them used [11:55] fwereade: that was a significant part of the current design [11:57] rogpeppe, ok, sgtm, thank you for pointing that out [11:57] fwereade: it means that if you use upload-tools, you rely on the fact that you're going to run the uploaded tools (assuming that you deploy to the same architecture) [11:57] rogpeppe, but wait [11:57] * rogpeppe waits with baited breath [11:57] or is it "bated bread"? [11:57] breath [11:58] ah, it is [11:58] rogpeppe, the latter -- and fwereade is not sure [11:58] * fwereade has just been reminded that he has to visit the shops for cath's lunch; bbiab [11:58] fwereade: ok [12:27] rogpeppe, heyhey [12:28] fwereade: hihi [12:29] rogpeppe, can we explore the public/private use cases a little more? I think I need a little refresher [12:29] fwereade: ok [12:30] fwereade: motivating example #1: we want to be able to run the local dev version of the tools without worrying about what might be in a public bucket [12:33] fwereade: what in particular are you interested in finding out? [12:35] rogpeppe, hum, ok, so: does FindTools currently return the latest compatible tools in private, or if that's not there the latest compatible tools in public? [12:35] fwereade: yup [12:37] rogpeppe, ok, so, I think the FindTools variant wants to return all latest matching private toolses, followed by all latest matching public toolses? [12:37] * rogpeppe likes "toolses" [12:37] :) [12:38] fwereade: i'd like to see a sketch of your algorithm for constraints solving before i commit to whether that's the right approach or not [12:39] rogpeppe, 1) eliminate non-matching instance types [12:39] rogpeppe, 2) eliminate non-matching images [12:39] rogpeppe, discard bad combinations in (1) x (2) [12:40] rogpeppe, (that may not come exactly there, but will be somewhere) [12:40] rogpeppe, 3) eliminate images for which no tools can be found [12:41] rogpeppe, 4) discard bad combinations [12:41] 5) magic happens here to nail down exactly which one we pick [12:42] fwereade: i've been wondering about the possibility of *starting* with the available tools [12:43] fwereade: but i'm not quite sure how that would look, or whether it would be better or worse. i suppose anything that eliminates more possibilities earlier is to be preferred. [12:43] rogpeppe, yeah, it shouldn't be too hard to reorder stages if we need to [12:46] fwereade: that depends if each stage is dealing with a list of the same things [12:46] rogpeppe, well, yes: we were I think talking about two stages of image-filtering [12:47] fwereade: {instance-type} -> {(instance-type, image)} -> {(instance-type, image, tools)} [12:48] fwereade: is that a reasonable summary of what the data types might look like through each stage? [12:48] fwereade: where {a} represents a set of a, and (a, b) represents a tuple of a and b. [12:48] rogpeppe, yeah, roughly like that [12:51] fwereade: got lunch. back in a short while. [12:58] * dimitern lunch [13:05] niemeyer: yo! [13:22] niemeyer, heyhey [13:23] Heya [13:23] * fwereade goes to eat the other half of lunch that he neglected before [13:43] fwereade: from the mongodb charm uniter log: http://paste.ubuntu.com/1676994/ [14:05] rogpeppe, what's --format json meant to do for relation-set? [14:06] fwereade: ha, good question, i'd missed that [14:06] fwereade: i'm surprised the python version allows it [14:06] rogpeppe, (that is to say: grar, I guess to match python we need to implement the --format stuff on every hook tool, whether or not it makes sense [14:06] ) [14:07] fwereade: we can just ignore it i suppose, mostly [14:07] rogpeppe, yeah, I think so [14:07] rogpeppe, but tyvm, good catch [14:07] fwereade: np [14:08] rogpeppe, do yu have the bug number handy? I can jot in an explanation [14:09] fwereade: sorry, i hadn't yet made a bug - i wanted to replicate it first [14:09] rogpeppe, np -- then just note that we should add it for everything [14:09] fwereade: yea [14:09] h [14:09] rogpeppe, (every hook tool that is) [14:11] fwereade: https://bugs.launchpad.net/juju-core/+bug/1129130 [14:11] <_mup_> Bug #1129130: all hook tools should support --format < https://launchpad.net/bugs/1129130 > [14:11] rogpeppe, cool, tyvm [14:55] bigjools, thanks for that mongo ppa, btw. [15:10] fwereade: ping [15:11] thanks for the review hazmat [15:13] mgz, np [15:17] hazmat: also, missed the review on the last change landed on lp:juju, have left a comment there now [15:18] ack [15:19] the design for that changed too many times, and ended up in a confused state... [15:20] mgz, r597 was pure breakage it appears [15:21] mgz, the value returned by constraints convert is used for comparison and validation, the tests weren't previously getting to a real comparison because the constraints lacked series [15:21] the issue is maas needs the original string, not something that juju constraints have mangled [15:21] mgz, folks using it in practice would hit the issue that the string was being returned but the compare method was issubset [15:22] the previous bug was from passing str(set(['tag-a', 'tag-b'])) which maas didn't understand because it doesn't parse python sets [15:22] so, that's fixable(ish) elsewhere, I just wonder if we've regressed the other bug... [15:22] mgz, hmm.. the original string is preserved and serialized, noted thoug [15:22] mgz, yeah.. not having a maas instance to test against makes this a bit of wackamole [15:23] provided the convert method is only used for juju, and not in the api call, I think we're fine [15:23] but I can't remember what exactly is the case there... [15:24] mgz, the convert call is also used against __getitem__ implicitly so the constraint acquisition for sending to maas may indeed have issue [15:24] checking [15:24] uses constraints.get... which I have a nasty feeling does convert [15:26] argh, and the maas client tests use dicts not real constraint objects because those are a pain to construst outside of a provider context [15:26] not clear that it does [15:26] yeah.. [15:27] mgz, i'll have a look and try to do a proper constraints test with that api [15:38] mgz, thanks [16:11] mgz, digging through the tags stuff last week, i did run into a concern of tags that where valid at the time of service definition that are no longer valid cause issues [16:12] yeah, it's troublesome [16:14] this is generally true for non-trivial constraints, just because it once resolved to something sane, doesn't mean it always will [16:14] so the provisioner needs to handle having a constraint that fails [16:14] rather than just going into a retry loop as it does at present... [16:38] fwereade: you'll like this one. noisy but trivial: https://codereview.appspot.com/7327050 [16:45] rogpeppe, w00t! [16:45] fwereade: :-) [16:46] fwereade: i'm going to unexport state.NotFoundError and export state.NotFoundf [16:46] fwereade: because i want to be able to create a not-found error for testing purposes [16:46] fwereade: and there's no point really in exporting the type when we've got IsNotFound [16:47] rogpeppe, yeah, as long as we have api.IsNotFound I'm not bothered by the precise gubbins [16:47] fwereade: Just for info, I put the backend branch into work in progress again. I discovered a missing capability during the storage testing. [16:47] fwereade: cool [16:47] TheRealMue, ah, thanks === TheRealMue is now known as TheMue [16:48] fwereade: i'm leaning towards something a bit more general actually: api.ErrCode(err) == api.CodeNotFound [16:48] fwereade: although we could have IsNotFound as a short cut for that [16:48] rogpeppe, sgtm [16:48] rogpeppe, clear and close enough ;) === deryck is now known as deryck[lunch] [17:15] hmm, typing this was not a good idea: [17:15] bzr switch lp:~rogpeppe/juju-core/221-instanceid-bool [17:16] now: how to get myself out of it! [17:23] heh [17:23] what was the location before? just a plain branch, or something fancier? [17:25] rogpeppe: what do `bzr info` and `bzr branches` say? [17:25] mgz: it's ok, i've fixed it [17:25] mgz: i just edited the "location" file [17:26] mgz: i was using cobzr, so the location before was a file: branch [17:26] ..that's okay for checkouts, if you also have sane tree state, switching back to the previous location is safer [17:27] mgz: i couldn't use "cobzr switch" because it complained at me [17:28] plain bzr switch, with the magic cobzr location, would work (with --force at least), but that does mean you need to know how cobzr maps names [17:28] mgz: ah, i didn't know that plain bzr had a "switch" command === imbrando1 is now known as imbrandon === deryck[lunch] is now known as deryck [18:37] here's a dilemma: is it ethical to ask the company to pay 400 quid more for a flight so that i can get 4 hours sleep rather than none... ? [19:03] right, time to stop, see y'all tomorrow [22:29] poos [22:29] davecheney: ping [22:30] thumper: ack [22:30] davecheney: I have a slight problem [22:30] shoot [22:30] I've managed to cut out a lot of code duplication [22:30] with one small problem [22:31] in all cases we want to parse the command line flags with "allowIntersperse=true" [22:31] except for the case of a supercommand [22:31] the code is cmd.Main [22:31] * davecheney looks [22:31] and I want to say "if this Command is a SuperCommand, then use false, otherwise use true" [22:32] Command is an interface and SuperCommand just a struct [22:32] what is the best way to ask [22:32] davecheney: the parsing used to be in the Init methods of *every* command [22:32] I'm wanting to remove that duplication [22:32] +1 to that [22:32] thumper: try a type switch [22:32] the code is nice and simple [22:32] davecheney: got an example? [22:33] c is of type cmd.Command [22:33] switch c := c.(type) { [22:33] case *cmd.SuperCommand: // guess [22:33] // do something [22:33] default: [22:33] hmm... lemmie test [22:33] // you are something else that conforms to cmd.Command [22:33] } [22:35] sweet [22:35] works in my small test prog [22:35] will test in main code [22:43] davecheney: I think I have it now, but I have to go collect daughter for lunch [22:43] back online after lunch [22:46] thumper: no worries, i have to pop to the shops for breakfast stuffs [23:13] hazmat: the pleasure was all mine, believe me :)