/srv/irclogs.ubuntu.com/2013/05/21/#juju-dev.txt

* thumper loos for wallyworld_01:39
thumpers/loos/looks/01:39
* thumper sighs01:39
wallyworld_hello01:39
thumperwallyworld_: s'up?01:40
wallyworld_finishing some work to make juju easier to use01:41
wallyworld_using simplestreams metadata, public bucket url in keystone catalog etc01:41
wallyworld_i have something like 6 branchs in review01:42
thumperheh01:42
wallyworld_what you doing?01:42
wallyworld_you were off last  week?01:42
thumperI'm just about to put up the three branches I have to implement plugins fully01:42
thumperyes, last week was a holiday for me01:42
wallyworld_yay01:42
thumperabout to spend the afternoon breaking down work items into bite sized chunks01:42
wallyworld_did you go away anywhre01:43
wallyworld_apparently me, you and frank are on containers01:43
thumperwallyworld_: no, stayed at home and hacked on my personal project01:44
thumpermade good progress01:44
marcoceppiMakyo: did you need help with anything in particular?02:32
marcoceppierr, kyhwana ^^02:32
kyhwanamarcoceppi: not yet ;)02:33
kyhwanastill work time *power cycles some more boxeS*02:33
kyhwanaXFS doesn't like it when you're building a kernel on it and you power cycle the box, even with RAID BBUs :(02:33
marcoceppiWell, it's sleep time here, wanted to make sure you weren't stuck on something before I powered down02:34
kyhwanaoh thanks, will see how I get on02:34
marcoceppikyhwana: feel free to ping in #juju if you have a problem. A lot more charmers tend to lurk in there02:34
marcoceppicheers o/02:35
=== tasdomas_afk is now known as tasdomas
dimiterng'morning07:05
=== liam_ is now known as Guest39447
rogpeppe1dimitern: hiya08:37
dimiternrogpeppe1: heyhey08:37
dimiternrogpeppe1: still struggling with (srv)Pinger stuff08:37
dimiternrogpeppe1: but i hope it'll end soon08:38
rogpeppe1dimitern: ok. feel free to ask if you think there's something i could help with.08:38
dimiternrogpeppe1: cheers08:38
dimiternrogpeppe1: so to be able to use the pinger client-side would I need to define func (r *srvRoot) Pinger(id string) (srvPinger, error) ?08:46
rogpeppe1dimitern: yes08:46
dimiternrogpeppe1: not just have func (m *srvMachine) SetAgentAlive() (params.PingerId, error)08:46
rogpeppe1dimitern: well, probably you'd return *srvPinger08:46
rogpeppe1dimitern: yeah, you'd need that too08:47
dimiternrogpeppe1: but EntityWatcher() returns just srvEntityWatcher08:47
rogpeppe1dimitern: ah, probably because it's only wrapping a pointer.08:47
dimiternrogpeppe1: and errUnknownWatcher08:47
dimiternrogpeppe1: it looks like it's just an empty struct rather than wrapping a pointer08:48
dimiternrogpeppe1: s/empty/uninitialized/08:49
dimiternrogpeppe1: oh.. you know what i mean :)08:49
rogpeppe1dimitern: it's only returning a zero struct when it returns an error08:49
dimiternrogpeppe1: should I follow this and define an error as well or just return a pointer?08:50
rogpeppe1dimitern: otherwise it wraps the *srvWatcher08:50
rogpeppe1dimitern: those are weird alternatives :-)08:50
rogpeppe1dimitern: type srvPinger {*srvWatcher} would seem to be the right approach08:51
dimiternrogpeppe1: I prefer a pointer actually08:51
rogpeppe1dimitern: there's no point :-)08:51
dimiternrogpeppe1: yeah, I did that already08:51
rogpeppe1dimitern: it just means one more allocation for no particular reason08:52
dimiternrogpeppe1: so have errUnknownPinger and use the same pattern08:52
rogpeppe1dimitern: yeah08:52
dimiternrogpeppe1: ok08:52
dimiternrogpeppe1: so which methods do I need to implement on srvPinger? there are Start, Stop and Kill defined, but for srvEntityWatcher I can see only Next() defined and there are more in state.EntityWatcher09:01
rogpeppe1dimitern: i think you probably want Stop and Kill09:03
dimiternrogpeppe1: but how to start it?09:03
rogpeppe1dimitern: SetAgentAlive starts it09:03
dimiternrogpeppe1: ah, right!09:03
rogpeppe1dimitern: BTW, i've just noticed something09:04
dimiternrogpeppe1: yeah?09:04
rogpeppe1dimitern: you probably the resource to Kill the pinger rather than Stopping it09:04
rogpeppe1dimitern: which means you won't be able to just embed the srvResource09:05
dimiternrogpeppe1: why?09:05
rogpeppe1dimitern: because when a connection goes away, i *think* we want the agent to be reported as dead immediately09:05
dimiternrogpeppe1: seems right09:06
dimiternrogpeppe1: but this means I need to both embed srvResource and define Kill09:07
dimiternrogpeppe1: ah, I see your poing - implement Stop() as Kil()09:07
rogpeppe1dimitern: you'll need srvResource as a field, and yes, you'll need to define Stop and Kill on srvPinger09:07
rogpeppe1dimitern: yeah09:07
dimiternrogpeppe1: I need srvResource because?09:08
rogpeppe1dimitern: i think the naming distinction between Stop and Kill in Pinger is a bit too subtle09:08
dimiternrogpeppe1: s/need/need to embed/09:08
dimiternrogpeppe1: actually wrt to the logic above, do I need Stop at all?09:09
rogpeppe1dimitern: not strictly speaking09:09
rogpeppe1dimitern: if we don't currently use it09:09
rogpeppe1dimitern: i think that we should probably have Pinger.Stop and Pinger.StopButLeaveRunning :-)09:09
rogpeppe1dimitern: or something like that09:10
dimiternrogpeppe1: why the second one?09:10
rogpeppe1dimitern: that's what Stop does currently09:10
dimiternrogpeppe1: I can't see Stop being used - perhaps i'm not looking in the right place09:11
rogpeppe1dimitern: currently Stop is the only method being used09:11
rogpeppe1dimitern: which is perhaps not quite right.09:11
dimiternrogpeppe1: I meant presence.Pinger.Stop09:11
rogpeppe1dimitern: that's what i meant too09:12
rogpeppe1dimitern: basically, we should really only be using pinger.Stop when we know we're upgrading09:12
dimiternrogpeppe1: where is it used?09:12
rogpeppe1dimitern: in worker/machiner/machiner.go:/watcher.Stop09:12
dimiternrogpeppe1: hmm09:13
rogpeppe1dimitern: but actually...09:13
dimiternrogpeppe1: when upgrading we need the pinger stopped but alive somehow?09:13
rogpeppe1dimitern: well yes - we don't want to see that the agent has died when in fact it's just restarting09:14
dimiternrogpeppe1: it *is* dead until restarted, isn't it?09:14
rogpeppe1dimitern: just temporarily inactive :-)09:14
dimiternrogpeppe1: i don't see how this matters - it might not come up again09:15
dimiternrogpeppe1: and when it does it'll start a new pinger anyway09:15
rogpeppe1dimitern: yeah, in which case the normal timeout will apply09:15
rogpeppe1dimitern: it will start a new pinger which will take over from the previous one, and noone will know09:15
dimiternrogpeppe1: that's very subtle logic09:16
rogpeppe1dimitern: that was part of the design09:16
rogpeppe1dimitern: well, not the "subtle" bit :-)09:16
dimiternrogpeppe1: so what then - sP.Stop() calls P.Kill and have sP.Pause() ?09:17
dimiternrogpeppe1: calling P.Stop()09:17
* rogpeppe1 inspects the logic inside presence09:18
dimiternrogpeppe1: or just don't complicate things and have sP.Kill() -> P.Kill() and sP.Stop() -> P.Stop()09:20
dimiternrogpeppe1: ?09:20
rogpeppe1dimitern: yes, but a bit more too09:20
dimiternrogpeppe1: please explain09:21
rogpeppe1dimitern: i think you want: type pinger struct {p *presence.Pinger}; and pinger.Stop() -> pinger.p.Kill09:21
dimiternrogpeppe1: by "pinger" you mean srvPinger or it's a separate type?09:22
kyhwanahrm, going through the juju getting started at https://juju.ubuntu.com/docs/getting-started.html in 12.04, trying to use lxc, in "In ~/.juju/environments.yaml, add a section for type "local":" I get error: environment "sample" has an unknown provider type "local" when I run juju bootstrap09:22
rogpeppe1dimitern: it's a separate type09:22
dimiternkyhwana: Go juju (juju-core) does not yet support the local provider09:22
dimiternrogpeppe1: ok, I'm confused now.. hangout?09:23
rogpeppe1dimitern: sure09:23
kyhwanadimitern: what. Why does the getting-started then have instructions for LXC/local?09:23
dimiternrogpeppe1: I'll start one this time09:23
dimiternkyhwana: it's about Python juju mostly, if you want to use the local provider you should stick with Py juju for now09:24
dimiternrogpeppe1: https://plus.google.com/hangouts/_/9849418108b0af37525e7611bc4b9e20837c241d?authuser=0&hl=en09:25
kyhwanadimitern: whats the difference?09:26
dimiternkyhwana: juju-core is actively developed, while py-juju is just maintained09:31
kyhwanaahhh09:32
kyhwanaso I should try it in 13.04?09:33
kyhwanaright, works in 13.0409:46
kyhwanaI know it says "12.04" is in beta, but maybe the getting started page should say "requires 13.04"09:46
dimiternkyhwana: so in 13.04 juju-core is released for the first time, but it does not implement all the features of py-juju; it implements more things as well and generally is the way forward for juju. In 13.10 there is a lot more stuff planned (including the local provider among other things)10:03
kyhwanahmm10:04
dimiternrogpeppe1: all done on the server side i think, now I have a question about SetAgentAlive -> *Pinger, error10:19
dimiternrogpeppe1: (client-side)10:19
rogpeppe1dimitern: ok10:19
dimiternrogpeppe1: I need both to call srvMachine.SetAgentAlive and start a pinger client-side, right?10:19
rogpeppe1dimitern: you just need to call SetAgentAlive10:20
rogpeppe1dimitern: and store the pinger id in the *Pinger that you return from tha10:20
rogpeppe1t10:20
dimiternrogpeppe1: but how about the  loop stuff and Pinger at client-side?10:20
rogpeppe1dimitern: it's all done server side10:21
rogpeppe1dimitern: no loop necessary10:21
dimiternrogpeppe1: so why EntityWatcher defines a loop at client-side then?10:21
rogpeppe1dimitern: because it needs to turn the API calls into channel sends10:21
rogpeppe1dimitern: there's no need for that with a pinger10:22
dimiternrogpeppe1: ah, right; but I still need a Pinger type at client side10:22
rogpeppe1dimitern: yup10:22
rogpeppe1dimitern: type Pinger {id string}10:22
dimiternrogpeppe1: which does what?10:22
rogpeppe1dimitern: it'll just define a Stop method10:22
rogpeppe1dimitern: actually, type Pinger {st *State; id string}10:23
dimiternrogpeppe1: I see10:23
rogpeppe1dimitern: then func (p *Pinger) Stop() error {return p.st.call("Pinger", p.id, "Stop", nil)}10:23
rogpeppe1or something like that10:23
dimiternrogpeppe1: cool :)10:23
dimiternrogpeppe1: how about the result of the call to SetAgentAlive? It returns params.PingerId and error10:27
dimiternrogpeppe1: do I need something like struct result {id params.PingerId, err error}?10:28
rogpeppe1dimitern: no10:28
rogpeppe1dimitern: just pass a PingerId to the result paramter of call10:29
dimiternrogpeppe1: and the error is returned by m.st.Call ?10:29
rogpeppe1dimitern: yup10:29
dimiternrogpeppe1: and for methods w/o arguments and an error result, like EnsureDead? -> return m.st.call("Machine", m.id, "EnsureDead", nil, nil)10:32
rogpeppe1dimitern: yup10:33
dimiternrogpeppe1: i like  it already :)10:33
rogpeppe1dimitern: cool10:33
dimiternrogpeppe1: and Life? there's no error result, just params.Life -> m.st.call("Machine", m.id, "Life", nil, &life); return life?10:35
rogpeppe1dimitern: every API call *must* return a struct10:36
rogpeppe1dimitern: so you'll need a struct with a single Life member10:36
dimiternrogpeppe1: ah, ok10:36
dimiternrogpeppe1: does it have to be a struct with named fields? will type Life struct { string } work?10:37
rogpeppe1dimitern: it should be with named fields, yes10:37
rogpeppe1dimitern: that's kinda the point10:38
dimiternrogpeppe1: so Life { Life string } then10:38
rogpeppe1dimitern: it means that we can add fields later without breaking the API10:38
rogpeppe1dimitern: yeah, that sounds reasonable.10:38
rogpeppe1dimitern: although...10:38
rogpeppe1dimitern: i'm wondering if we need to define "type Life string" in params10:38
rogpeppe1dimitern: so that ServiceInfo can use it10:39
rogpeppe1dimitern: and that means we need to think of another name...10:39
dimiternrogpeppe1: I did that initially, but now I have: http://paste.ubuntu.com/5686558/10:39
rogpeppe1dimitern: so no state.Life type?10:40
dimiternrogpeppe1: well state.Life is an int810:40
rogpeppe1dimitern: yes, but lots of things in the code use state.Life, don't they?10:40
rogpeppe1dimitern: (or maybe they don't actually...)10:40
dimiternrogpeppe1: all of them most probably10:40
dimiternrogpeppe1: Life.String() is used in commands only I think and logs10:41
dimiternrogpeppe1: so then I should have params.LifeResults with Life state.Life? can I do that in params?10:42
rogpeppe1dimitern: hmm, i wouldn't mind just having life as an untypes string10:42
rogpeppe1untyped10:42
rogpeppe1dimitern: but others may well disagree10:42
rogpeppe1dimitern: no10:42
dimiternrogpeppe1: yeah, thought so10:43
rogpeppe1dimitern: you'd need to define params.Life type10:43
rogpeppe1dimitern: e.g. (in params) type Life string10:43
dimiternrogpeppe1: so why not have type Life int8 in params and use that, so there's no fishy string conversions?10:43
rogpeppe1dimitern: i'm not sure i want those constant values to be hardcoded in the javascript10:44
dimiternrogpeppe1: but how about the agents?10:44
rogpeppe1dimitern: i think we should choose a single representation across the whole API10:44
dimiternrogpeppe1: these values has to be defined somewhere if you need to use them - strings or ints10:45
rogpeppe1dimitern: sure.10:45
rogpeppe1dimitern: i'd do (in params) type Life string10:45
dimiternrogpeppe1: but I agree numbers in js are not real numbers, so strings is better10:45
rogpeppe1dimitern: and then 'type LifeResult struct { Life Life }'10:45
dimiternrogpeppe1: ok (and let the bikeshedding begin during the review :)10:46
rogpeppe1dimitern: s/Result/Results/10:46
rogpeppe1dimitern: i think that's relatively uncontroversial actually10:46
dimiternrogpeppe1: you never know :)10:47
rogpeppe1dimitern: v true :-)10:47
dimiternrogpeppe1: so any API call can return: (1) an error, (2) struct, (3) both - and these are all the cases10:48
rogpeppe1dimitern: yeah - read the rpc documentation!10:49
rogpeppe1dimitern: it's all there10:49
dimiternrogpeppe1: sorry for bugging you so much, but it's easier for me to understand things as I go (in context), then the docs will be more useful (as a reminder)10:50
rogpeppe1dimitern: np. it is worth reading (and trying to understand) the docs at least once though, to start with10:51
dimiternrogpeppe1: I agree, my bad10:51
rogpeppe1dimitern: and if you find them incomprehensible, i want to know so i can improve them.10:51
dimiternrogpeppe1: sure10:52
dimiternrogpeppe1: how about doc comments - do I need to copy the state method's comment for both client and server methods?10:54
rogpeppe1dimitern: i'd copy existing convention. definitely copy doc comments for the client methods, but not necessarily for the server methods10:55
dimiternrogpeppe1: or the client one is more important and the server one can be shorter (e.g. EnsureDead is several lines long)10:55
rogpeppe1dimitern: but... we might want that to change actually10:55
dimiternrogpeppe1: right10:56
rogpeppe1dimitern: if we start auto-generating docs for the API10:56
rogpeppe1dimitern: but for the time being, i'd go with that10:56
dimiternrogpeppe1: why in the permission tests allow specifies both machine-0 and machine-1 when (e.g. SetPassword) only affects machine 1?11:19
rogpeppe1dimitern: i'm not sure i understand the question11:19
dimiternrogpeppe1: should i follow this pattern?11:19
dimiternrogpeppe1: opMachine1SetPassword acts on machine 1 only, not both 0 and 111:20
* rogpeppe1 goes to have a look11:20
dimiternrogpeppe1: I think the machine-0 in allow is not needed11:21
rogpeppe1dimitern: ah, it's correct but there should be a comment11:22
dimiternrogpeppe1: explain please?11:22
rogpeppe1dimitern: machine-0 is allowed to set the password because it's an environment manager11:22
dimiternrogpeppe1: but for all other cases only the machine we're acting upon has to be specified in allow, right?11:23
rogpeppe1dimitern: yes.11:23
dimiternrogpeppe1: I'll add a comment about opMachine1SetPassword in the table then11:23
rogpeppe1dimitern: sounds good11:23
dimiternrogpeppe1: so the func() that's being returned resets whatever the operation did?11:27
rogpeppe1dimitern: yes11:27
rogpeppe1dimitern: hmm11:27
rogpeppe1dimitern: that may mean you need to provide a Kill operation11:27
dimiternrogpeppe1: fortunately for EnsureDead it's a no-op, because it won't affect the machine which is alive11:27
dimiternrogpeppe1: oh, for SSA() yeah..11:28
rogpeppe1dimitern: SAA?11:28
dimiternrogpeppe1: or just call pinger.Stop?11:28
dimiternrogpeppe1: SetAgentAlive11:28
rogpeppe1dimitern: actually, that should be fine11:28
dimiternrogpeppe1: ok then11:28
rogpeppe1dimitern: it doesn't matter if we're still notionally alive11:28
jamdimitern, mgz, wallyworld_, danilos: greetings all11:29
wallyworld_hello11:29
dimiternjam: hey, just staring mumble now11:29
jamdanilos: are you there? We see you in mumble but you are deafened and muted11:32
dimiternrogpeppe1: so wrt permissions should all these machine methods be accessible only by the machine's own agent: SetStatus, Life, EnsureDead, SetAgentAlive?11:58
dimiternrogpeppe1: not sure about Life11:58
rogpeppe1dimitern: not Life, but the others, yes11:58
rogpeppe1dimitern: one other thing11:59
rogpeppe1dimitern: the environ manager needs to be able to call SetStatus11:59
dimiternrogpeppe1: why?11:59
rogpeppe1dimitern: what happens when the provisioner can't provision a machine?11:59
dimiternrogpeppe1: it tries again11:59
rogpeppe1dimitern: forever?12:00
dimiternrogpeppe1: let me check12:01
rogpeppe1dimitern: we need to think about what happens if we can't bring up a machine. i'm thinking that the environ manager probably needs to be able to call EnsureDead in that case actually.12:01
dimiternrogpeppe1: actually if the PA fails to start a machine it sets it to an error state and will skip it next time12:02
rogpeppe1dimitern: that's what i thought12:02
rogpeppe1dimitern: so it calls SetStatus, right?12:03
dimiternrogpeppe1: ah, I see your point12:03
dimiternrogpeppe1: yeah, m0 needs to SetStatus12:03
dimiternrogpeppe1: and how about Life() - what should be in allow and deny?12:05
rogpeppe1dimitern: Life shouldn't be in the perms checks12:06
rogpeppe1dimitern: sorry, i just remembered :-)12:06
rogpeppe1dimitern: it's just a field in params.Machine12:06
rogpeppe1dimitern: not a separate API call at all12:06
dimiternrogpeppe1: hmm..12:06
dimiternrogpeppe1: like InstanceId ?12:06
rogpeppe1dimitern: exactly like that12:07
dimiternrogpeppe1: ok, I was wondering the same actually12:07
rogpeppe1dimitern: sorry for not catching that earlier12:07
dimiternrogpeppe1: np12:07
rogpeppe1dimitern: we did mention it yesterday though12:07
danilosjam, dimitern, mgz, wallyworld_: hey, sorry, got too focused on coding :/12:11
jamdanilos: how's it going?12:11
danilosnot that that's necessarily a bad thing, just forgot about the meeting12:11
danilosjam, it's pretty good, thanks12:12
=== gary_poster is now known as gary_poster|away
jamdanilos: finishing up the bootstrap stuff?12:13
danilosjam, yeah12:13
=== gary_poster|away is now known as gary_poster
dimiternrogpeppe1: so no srvMachine.Life(), only client-side12:20
rogpeppe1dimitern: yup12:20
rogpeppe1dimitern: and some tests to check that refresh refreshes the life, etc12:21
dimiternrogpeppe1: it'll be difficult to change the lifecycle with the current scenario12:22
rogpeppe1dimitern: how do you mean?12:22
dimiternrogpeppe1: all machines have assigned units, so cannot be removed or set to dying12:22
rogpeppe1dimitern: isn't that the same as it is now?12:23
rogpeppe1dimitern: you must remove the units, then the machine12:23
dimiternrogpeppe1: ah, ok12:23
=== tasdomas is now known as tasdomas_afk
dimiternrogpeppe1: and then restore the scenario12:23
=== tasdomas_afk is now known as tasdomas
rogpeppe1dimitern: oh, i see, when testing12:24
rogpeppe1dimitern: don't bother12:24
dimiternrogpeppe1: wait - are we talking about perm checks or individual api calls tests?12:24
rogpeppe1dimitern: the perms checks12:24
rogpeppe1dimitern: just try to change the lifecycle and check you get the right kind of error12:24
dimiternrogpeppe1: yeah - i could add a hanging machine with no units that can change life12:25
rogpeppe1dimitern: don't even bother to do that12:25
dimiternrogpeppe1: sgtm12:25
rogpeppe1dimitern: just try to change the life of one of the machines12:25
rogpeppe1dimitern: you should get a "machine has units" error12:25
rogpeppe1dimitern: if you don't, there's a problem12:25
dimiternrogpeppe1: that's exactly what i did :)12:25
rogpeppe1dimitern: but for the individual API test, you should create a machine and test that it actually works12:26
dimiternrogpeppe1: sure12:26
dimiternrogpeppe1: does this look ok to you? http://paste.ubuntu.com/5686802/12:40
dimiternrogpeppe1: because i'm getting permission denied12:41
rogpeppe1dimitern: i think i'd implement isOwnAgent on srvRoot, not srvMachine - it's quite generic12:42
rogpeppe1dimitern: (not that that effects the correctness of the code)12:42
dimiternrogpeppe1: i though about that12:42
dimiternrogpeppe1: but otherwise?12:42
rogpeppe1dimitern: what's the actual output from your test12:44
rogpeppe1dimitern: (yes, i do think i see a potential problem)12:44
dimiternrogpeppe1: http://paste.ubuntu.com/5686827/ (disregard the messed up Life value - fixed that)12:45
rogpeppe1dimitern: look at opClientResolved12:45
rogpeppe1dimitern: you've got a spelling error in your error message for a start12:45
rogpeppe1dimitern: and if you get a permission-denied error, you should return it12:46
rogpeppe1dimitern: on line 29, you can just do c.Assert(err, IsNil)12:46
dimiternrogpeppe1: so I should expect api.CodeUnauthorized at first (Machine("1")) ?12:46
rogpeppe1dimitern: hmm, no you can't12:47
rogpeppe1dimitern: hmm, interesting12:47
dimiternrogpeppe1: I was wondering why about that - why check + return empty func instead of assert12:47
rogpeppe1dimitern: because the actual permission-denied error will happen when trying to get the machine, not on the later call12:49
dimiternrogpeppe1: ah..12:49
dimiternrogpeppe1: i'll poke it a bit more12:50
rogpeppe1dimitern: i think it (and opMachine1SetPassword) could use some improvement actually12:50
rogpeppe1dimitern: they're not actually testing the right thing.12:51
dimiternrogpeppe1: but first - if I move isOwnAgent into srvRoot, how can I get the m.m.Tag() there?12:51
rogpeppe1dimitern: maybe call it m.root.loggedInAs(m.Tag())12:52
dimiternrogpeppe1: there's no m anymore12:53
dimiternrogpeppe1: I have r *srvRoot only12:53
rogpeppe1dimitern: i mean in EnsureDead, you'd call m.root.loggedInAs(m.Tag()) rather than m.isOwnAgent()12:54
dimiternrogpeppe1:  i see.. would've liked to shorten this somehow12:54
dimiternrogpeppe1: because I have also isOwnAgentOrManager - extracted the check from setpassword12:55
dimiternrogpeppe1: maybe I can make it loggedInAs(tag, job) - and job can be nil12:56
rogpeppe1dimitern: hmm, no i don't think that's quite right.12:56
* rogpeppe1 thinks12:57
dimiternrogpeppe1: that's what I need, but the name might be better12:57
dimitern*could b* better12:58
dimiternrogpeppe1: hasPermission(tag, *job) ?12:59
rogpeppe1dimitern: i'm trying to think of a good name too12:59
rogpeppe1dimitern: this is going to be used a lot, so it's worth coming up with something that works well13:00
dimiternrogpeppe1: canAccess? are you ok with the *job arg?13:00
rogpeppe1dimitern: i'm not sure. i think i'd prefer to keep the two checks separate.13:00
dimiternrogpeppe1: we can have multiple: canAccess(tag), canManage(tag, job) ?13:01
dimiternor just canManage and hard code JobManageEnviron check inside13:02
rogpeppe1dimitern: i don't find the meanings of those verbs very obvious13:02
dimiternrogpeppe1: why?13:02
rogpeppe1dimitern: what does canAccess mean? who can access what?13:02
dimiternrogpeppe1: we're asking "can <user> access <tag>"?13:03
rogpeppe1dimitern: the answer to that depends on the operation, no?13:03
dimiternrogpeppe1: not really - it's ancilliary to the operation13:03
rogpeppe1dimitern: the verb seems to imply that it's universal, to me at any rate.13:04
dimiternrogpeppe1: I mean the operation itself has to define what is done13:04
dimiternrogpeppe1: that's why I started with isX13:04
dimiternrogpeppe1: userCanAccess? :)13:05
dimiternrogpeppe1: it has to be not to long as well13:06
rogpeppe1dimitern: personally i think readability is probably more important than length here.13:06
dimiternrogpeppe1: ok, let's dice it step by step - 1) get logged in user's tag, 2) check it matches the passed entity's tag13:07
dimiternrogpeppe1: userMatches(x) -> e.Tag() == x.Tag()13:08
rogpeppe1dimitern: how about "isOwner" as a name13:08
rogpeppe1dimitern: as in m.root.isOwner(m.m)13:09
rogpeppe1hmm, not quite right too13:09
dimiternrogpeppe1: sgtm13:09
dimiternrogpeppe1: we're coming back to isOwnAgent :)13:10
dimitern"agent" here in a more general sense (s/o acting on behalf of)13:11
rogpeppe1dimitern: yeah, i didn't really have a problem with isOwnAgent except the name and the fact we'd need to duplicate similar code for other entities.13:12
rogpeppe1dimitern: although, come to think of it, probably only srvUnit13:12
dimiternrogpeppe1: no, I mean have isOwnAgent in srvRoot13:13
dimiternrogpeppe1: actually you're right - we don't need other perm checks like that (what other agents are there that "own" entities?)13:14
dimiternunits and machines only13:14
rogpeppe1dimitern: yeah13:14
rogpeppe1dimitern: how about this? http://paste.ubuntu.com/5686906/13:15
rogpeppe1dimitern: then we can use the general Auth suffix to apply to various kinds of authorization primitive13:15
rogpeppe1dimitern: where ownerAuth is your isOwnAgent by another name13:16
dimiternrogpeppe1: i like it - we can have envrionManagerAuth on srvRoot actually13:16
rogpeppe1dimitern: ah yes, good point13:16
dimiternrogpeppe1: sgtm, will make it so13:16
rogpeppe1dimitern: cool, thanks for bearing with me13:16
rogpeppe1dimitern: hmm, maybe "auth" would be better as a prefix rather than a suffix13:17
rogpeppe1dimitern: i can't quite decide13:17
dimiternrogpeppe1: i thought the same13:18
rogpeppe1dimitern: in which case, let's do that13:18
dimiternrogpeppe1: let's make it a prefix and also - how about putting authOwner on srvRoot getting x with .Tag()?13:18
dimiternrogpeppe1: so if !m.authOwner(m.m) && !m.authEnvironManager() { return errPerm }13:19
rogpeppe1dimitern: sgtm13:19
dimiternrogpeppe1: cool13:19
dimiternrogpeppe1: what did you say can be improved about opMachine1SetPassword?13:31
=== wedgwood_away is now known as wedgwood
dimiternrogpeppe2: kanban14:03
=== deryck is now known as deryck[afk]
dimiternrogpeppe2: I cannot test SetAgentAlive properly without having AgentAlive() as well14:41
dimiternrogpeppe2: and using the state machine's AgentAlive won't work because the pingers are different14:41
dimiternrogpeppe2: but I can just call it and see it returns no error and calling stop on the returned pinger is also successful14:43
rogpeppe2dimitern: for the permissions check or the actual test?14:44
dimiternrogpeppe2: actual test14:44
dimiternrogpeppe2: permissions test fine14:44
rogpeppe2dimitern: why can't you use AgentAlive on the state Machine ?14:44
dimiternrogpeppe2: it returns false after api.SetAgentAlive14:45
rogpeppe2dimitern: really? that seems a bit weird.14:45
dimiternrogpeppe2: hmm.. maybe something's wrong with my pinger code14:45
rogpeppe2dimitern: ah, you probably need to call state.Sync14:47
dimiternrogpeppe2: oh, forgot about that :)14:47
=== BradCrittenden is now known as bac
dimiternrogpeppe2: all done and all tests pass!  https://codereview.appspot.com/961404315:11
rogpeppe2dimitern: woo!15:12
dimiternrogpeppe2: scrutiny appreciated :)15:13
rogpeppe2dimitern: looking now15:13
rogpeppe2dimitern: reviewed15:37
dimiternrogpeppe2: tyvm15:37
=== tasdomas is now known as tasdomas_afk
dimiternrogpeppe2: the issue with setstatus is you cannot change it back to pending once it's advanced15:40
dimiternrogpeppe2: that's why I added default status and changed the scenario15:40
rogpeppe2dimitern: ah15:41
rogpeppe2dimitern: so you have to set the correct status15:41
dimiternrogpeppe2: what do you mean?15:42
* rogpeppe2 thinks we do make life hard for ourselves sometimes. more code breeds more code.15:42
rogpeppe2dimitern: ah, i see, it's just pending you can't rewind15:43
dimiternrogpeppe2: yes15:43
dimiternrogpeppe2: and anyways, i think the scenario should have all machines in started status15:44
TheRealMuedimitern: another review15:44
rogpeppe2dimitern: you may well be right.15:44
dimiternTheRealMue: cheers15:44
dimiternTheRealMue: I feel the same about the 1 or 2 char vars throughout, but changing that is out of scope I think15:45
* dimitern thinks now once I picked up speed I can ravage through the next agent's needed API calls easily (PA I think) :)15:47
TheRealMuedimitern: But otherwise it never will be changed. ;)15:52
dimiternTheRealMue: not quite - can be changed independently as a whole15:55
dimiternrogpeppe2: HasAssignedUnitsError is a tricky one - what should the CodeHasAssignedUnits be? it's not a const15:56
rogpeppe2dimitern: it should be a const like the others15:56
dimiternrogpeppe2: it can be a format string, but that will duplicate the logic in state15:57
=== rogpeppe2 is now known as rogpeppe
rogpeppedimitern: i'm not sure i see the problem.15:57
rogpeppedimitern: why can't it just be a const code like the other codes?15:57
dimiternrogpeppe: func (e *HasAssignedUnitsError) Error() string { return fmt.Sprintf("machine %s has unit %q assigned", e.MachineId, e.UnitNames[0]) }15:57
rogpeppedimitern: the message is separate from the code15:58
dimiternrogpeppe: ah, ok15:58
rogpeppedimitern: take a look at the serverError implementation15:58
=== deryck[afk] is now known as deryck
=== TheRealMue is now known as TheMue
dimiternrogpeppe: ok, all done, will repropose soon and I'd appreciate one last look (running tests now)16:31
rogpeppedimitern: ok16:31
dimiternrogpeppe: https://codereview.appspot.com/961404316:41
rogpeppedimitern: reviewed16:52
dimiternrogpeppe: thanks16:53
dimiternrogpeppe: I don't get what's wrong with the error code check in opMachine1EnsureDead - do you mean to move the error check into a test similar to TestMachineEnsureDead instead?16:56
rogpeppedimitern: yes. the op checks are only for sanity - they should not be used to test specific functionality16:56
dimiternrogpeppe: ok16:58
dimiternrogpeppe: will do that and land it then16:58
dimiternrogpeppe: ah, perhaps you meant add it to errorTransformTests ?17:00
dimiternrogpeppe: or that as well as the separate test case for EnsureDead?17:01
mgzdimitern: poke me if any of my review comments are unclear or just silly17:02
dimiternmgz: already replied :)17:03
MakyoAnyone up for a review of https://codereview.appspot.com/9566045/ - refactor deploy to statecmd?17:04
mgzdimitern: you can carry forward my lgtm17:06
dimiternmgz: cheers17:06
mgzMakyo: done, poke rog or dimitern as well though17:12
Makyomgz, cool, thanks.  Will poke around the args, too, see what can be reduced.17:13
=== gary_poster is now known as gary_poster|away
* rogpeppe has got to go. g'night all17:22
rogpeppedimitern: yeah, it should be in errorTransformTests17:22
rogpeppedimitern: which probably means you don't need a separate test for the error return17:23
dimiternrogpeppe: well I did both17:23
dimiternrogpeppe: they're different anyway17:23
dimiternrogpeppe: one tests the flow and the other changes to serverError17:23
dimiternok, i'm off - mass effect is calling for me ;)17:27
dimiterng'night all17:28
=== gary_poster|away is now known as gary_poster
=== BradCrittenden is now known as bac
thumpermorning mramm21:30
mrammmorning21:30
thumpermorning wallyworld_21:45
wallyworld_g'day21:45
=== wedgwood is now known as wedgwood_away
=== wedgwood_away is now known as wedgwood
=== wedgwood is now known as wedgwood_away
wallyworld_thumper: in your branch, i can't see where DescriptionTimeout is used to kill the process23:58

Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!